Snap for 4807121 from d5dc6de2f5230a2935e8d168bdbb7fcb2362df54 to pi-release

Change-Id: Ic65ef2887a065400608cd652aa939463a097ee6b
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index ec15b30..524f4ac 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
diff --git a/ipacm/inc/IPACM_OffloadManager.h b/ipacm/inc/IPACM_OffloadManager.h
index bade0aa..4947a83 100644
--- a/ipacm/inc/IPACM_OffloadManager.h
+++ b/ipacm/inc/IPACM_OffloadManager.h
@@ -110,6 +110,8 @@
 
 	int resetTetherStats(const char *upstream_name);
 
+	int push_iface_up(const char *if_name, bool upstream);
+
 	static const char *DEVICE_NAME;
 
 	/* cache the add_downstream events if netdev is not ready */
diff --git a/ipacm/inc/IPACM_Wlan.h b/ipacm/inc/IPACM_Wlan.h
index 5fee0fa..1dc8ab0 100644
--- a/ipacm/inc/IPACM_Wlan.h
+++ b/ipacm/inc/IPACM_Wlan.h
@@ -234,6 +234,9 @@
 
 	void handle_SCC_MCC_switch(ipa_ip_type);
 
+	/*query wlan-clients */
+	int ipa_query_wlan_client();
+
 };
 
 
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index f7544e8..3a5a51a 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -537,7 +537,7 @@
 			IPACMERR("IPA_HANDLE_WAN_UP_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num);
 			return;
 		}
-#else /* not offload rndis on WIFI mode on MSM targets sky*/
+#else /* not offload rndis on WIFI mode on MSM targets */
 		if (data_wan_tether->is_sta)
 		{
 			IPACMERR("Not support RNDIS offload on WIFI mode, dun install UL filter rules for WIFI mode\n");
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 55a3fd5..34b2dda 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -111,6 +111,9 @@
 #ifdef FEATURE_IPACM_HAL
 	IPACM_OffloadManager* OffloadMng;
 	HAL *hal;
+int ipa_reset();
+/* support ipacm restart */
+int ipa_query_wlan_client();
 #endif
 
 /* start netlink socket monitor*/
@@ -845,6 +848,9 @@
 	(void)argc;
 	(void)argv;
 
+	IPACMDBG_H("RESET IPA-HW rules\n");
+	ipa_reset();
+
 	neigh = new IPACM_Neighbor();
 	ifacemgr = new IPACM_IfaceManager();
 #ifdef FEATURE_IPACM_HAL
@@ -1048,3 +1054,23 @@
 	close(fd);
 	return IPACM_SUCCESS;
 }
+
+int ipa_reset()
+{
+	int fd = -1;
+
+	if ((fd = open(IPA_DEVICE_NAME, O_RDWR)) < 0) {
+		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
+		return IPACM_FAILURE;
+	}
+
+	if (ioctl(fd, IPA_IOC_CLEANUP) < 0) {
+		IPACMERR("IOCTL IPA_IOC_CLEANUP call failed: %s \n", strerror(errno));
+		close(fd);
+		return IPACM_FAILURE;
+	}
+
+	IPACMDBG_H("send IPA_IOC_CLEANUP \n");
+	close(fd);
+	return IPACM_SUCCESS;
+}
\ No newline at end of file
diff --git a/ipacm/src/IPACM_OffloadManager.cpp b/ipacm/src/IPACM_OffloadManager.cpp
index 85ef7e4..c0378de 100644
--- a/ipacm/src/IPACM_OffloadManager.cpp
+++ b/ipacm/src/IPACM_OffloadManager.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -233,6 +233,9 @@
 	if (cache_need)
 	{
 		IPACMDBG_H("addDownstream name(%s) currently not support in ipa \n", downstream_name);
+		/* add ipacm restart support */
+		push_iface_up(downstream_name, false);
+
 		/* copy to the cache */
 		for(int i = 0; i < MAX_EVENT_CACHE ;i++)
 		{
@@ -396,6 +399,9 @@
 		if (cache_need)
 		{
 			IPACMDBG_H("setUpstream name(%s) currently not support in ipa \n", upstream_name);
+			/* add ipacm restart support */
+			push_iface_up(upstream_name, true);
+
 			/* copy to the cache */
 			for(int i = 0; i < MAX_EVENT_CACHE ;i++)
 			{
@@ -408,7 +414,7 @@
 					memcpy(&event_cache[latest_cache_index].prefix_cache, &gw_addr_v4, sizeof(event_cache[latest_cache_index].prefix_cache));
 					memcpy(&event_cache[latest_cache_index].prefix_cache_v6, &gw_addr_v6, sizeof(event_cache[latest_cache_index].prefix_cache_v6));
 					if (gw_addr_v4.fam == V4) {
-						IPACMDBG_H("cache event(%d) ipv4 fateway: (%x) dev(%s) on entry (%d)\n",
+						IPACMDBG_H("cache event(%d) ipv4 gateway: (%x) dev(%s) on entry (%d)\n",
 							event_cache[latest_cache_index].event,
 							event_cache[latest_cache_index].prefix_cache.v4Addr,
 							event_cache[latest_cache_index].dev_name,
@@ -727,7 +733,6 @@
 		return FAIL_INPUT_CHECK;
 	}
 	stats.reset_stats = true;
-
 	if (ioctl(fd, WAN_IOC_RESET_TETHER_STATS, &stats) < 0) {
 		IPACMERR("IOCTL WAN_IOC_RESET_TETHER_STATS call failed: %s", strerror(errno));
 		close(fd);
@@ -778,3 +783,87 @@
 	IPACMDBG_H(" not found netdev (%s) has cached event\n", interface_name);
 	return rel;
 }
+
+int IPACM_OffloadManager::push_iface_up(const char * if_name, bool upstream)
+{
+	ipacm_cmd_q_data evt_data;
+	ipacm_event_data_fid *data_fid;
+	ipacm_event_data_mac *data = NULL;
+	int index;
+
+	IPACMDBG_H("name %s, upstream %d\n",
+							 if_name, upstream);
+
+	if(ipa_get_if_index(if_name, &index))
+	{
+		IPACMERR("netdev(%s) not registered ignored\n", if_name);
+		return SUCCESS;
+	}
+
+	if(strncmp(if_name, "rmnet_data", 10) == 0 && upstream)
+	{
+		data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
+		if(data_fid == NULL)
+		{
+			IPACMERR("unable to allocate memory for event data_fid\n");
+			return FAIL_HARDWARE;
+		}
+		data_fid->if_index = index;
+		evt_data.event = IPA_LINK_UP_EVENT;
+		evt_data.evt_data = data_fid;
+		IPACMDBG_H("Posting IPA_LINK_UP_EVENT with if index: %d\n",
+							 data_fid->if_index);
+		IPACM_EvtDispatcher::PostEvt(&evt_data);
+	}
+
+	if(strncmp(if_name, "rndis", 5) == 0 && !upstream)
+	{
+		data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
+		if(data_fid == NULL)
+		{
+			IPACMERR("unable to allocate memory for event data_fid\n");
+			return FAIL_HARDWARE;
+		}
+		data_fid->if_index = index;
+        evt_data.event = IPA_USB_LINK_UP_EVENT;
+		evt_data.evt_data = data_fid;
+		IPACMDBG_H("Posting usb IPA_LINK_UP_EVENT with if index: %d\n",
+				data_fid->if_index);
+		IPACM_EvtDispatcher::PostEvt(&evt_data);
+	}
+
+	if((strncmp(if_name, "softap", 6) == 0 || strncmp(if_name, "wlan", 4) == 0 ) && !upstream)
+	{
+		data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
+		if(data_fid == NULL)
+		{
+			IPACMERR("unable to allocate memory for event data_fid\n");
+			return FAIL_HARDWARE;
+		}
+		data_fid->if_index = index;
+		evt_data.event = IPA_WLAN_AP_LINK_UP_EVENT;
+		evt_data.evt_data = data_fid;
+		IPACMDBG_H("Posting usb IPA_LINK_UP_EVENT with if index: %d\n",
+			data_fid->if_index);
+		IPACM_EvtDispatcher::PostEvt(&evt_data);
+	}
+
+	if(strncmp(if_name, "wlan", 4) == 0 && upstream)
+	{
+		data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac));
+		if(data == NULL)
+		{
+			IPACMERR("unable to allocate memory for event_wlan data\n");
+			return FAIL_HARDWARE;
+		}
+		data->if_index = index;
+		evt_data.event = IPA_WLAN_STA_LINK_UP_EVENT;
+		evt_data.evt_data = data;
+		IPACMDBG_H("Posting IPA_WLAN_STA_LINK_UP_EVENT with if index: %d\n",
+			data_fid->if_index);
+		IPACM_EvtDispatcher::PostEvt(&evt_data);
+	}
+
+	return IPACM_SUCCESS;
+}
+
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index a97c0a0..090aee2 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -267,6 +267,9 @@
 						IPACMDBG_H("IPv4 address:0x%x, IPv4 address mask:0x%x\n",
 										 info->ipv4_addr, info->addr_mask);
 						IPACM_EvtDispatcher::PostEvt(&evt_data);
+
+						/* Query wlan-clients */
+						ipa_query_wlan_client();
 					}
 
 					if(handle_addr_evt(data) == IPACM_FAILURE)
@@ -557,7 +560,7 @@
 				memcpy(&prefix[data->prefix.iptype], &data->prefix,
 					sizeof(prefix[data->prefix.iptype]));
 
-				if(is_upstream_set[data->prefix.iptype] == true)
+				if (is_upstream_set[data->prefix.iptype] == true)
 				{
 					IPACMDBG_H("Upstream was set before, adding modem UL rules.\n");
 					if(ip_type == IPA_IP_MAX || ip_type == data->prefix.iptype)
@@ -2243,6 +2246,26 @@
 	return;
 }
 
+int IPACM_Wlan::ipa_query_wlan_client()
+{
+	int fd = -1;
+
+	if ((fd = open(IPA_DEVICE_NAME, O_RDWR)) < 0) {
+		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
+		return IPACM_FAILURE;
+	}
+
+	if (ioctl(fd, IPA_IOC_QUERY_WLAN_CLIENT) < 0) {
+		IPACMERR("IOCTL IPA_IOC_QUERY_WLAN_CLIENT call failed: %s \n", strerror(errno));
+		close(fd);
+		return IPACM_FAILURE;
+	}
+
+	IPACMDBG_H("send IPA_IOC_QUERY_WLAN_CLIENT \n");
+	close(fd);
+	return IPACM_SUCCESS;
+}
+
 void IPACM_Wlan::eth_bridge_handle_wlan_mode_switch()
 {
 	uint32_t i;