浏览代码

qcacld-3.0: Ensure adapter is up before ip change work

Currently, the host driver blindly configures ARP/NS offloads and other
work when it receives an IP address change notification from the kernel.
Ensure the specificed adapter is still up before processing IP address
change notification changes from the kernel to prevent extra work and
invalid access.

Change-Id: I087b72a9ffd735a0482d1c4ff9ad62cb8beb036b
CRs-Fixed: 2049976
Dustin Brown 8 年之前
父节点
当前提交
f13b8c35e5
共有 3 个文件被更改,包括 118 次插入56 次删除
  1. 11 0
      core/hdd/inc/wlan_hdd_main.h
  2. 36 0
      core/hdd/src/wlan_hdd_main.c
  3. 71 56
      core/hdd/src/wlan_hdd_power.c

+ 11 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -1768,6 +1768,17 @@ QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *pAdapter);
 QDF_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx);
 void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx);
 int wlan_hdd_validate_context(hdd_context_t *pHddCtx);
+
+/**
+ * hdd_validate_adapter() - Validate the given adapter
+ * @adapter: the adapter to validate
+ *
+ * This function validates the given adapter, and ensures that it is open.
+ *
+ * Return: Errno
+ */
+int hdd_validate_adapter(hdd_adapter_t *adapter);
+
 bool hdd_is_valid_mac_address(const uint8_t *pMacAddr);
 QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx);
 

+ 36 - 0
core/hdd/src/wlan_hdd_main.c

@@ -628,6 +628,42 @@ int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
 	return 0;
 }
 
+int hdd_validate_adapter(hdd_adapter_t *adapter)
+{
+	if (!adapter) {
+		hdd_err("adapter is null");
+		return -EINVAL;
+	}
+
+	if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
+		hdd_err("bad adapter magic: 0x%x (should be 0x%x)",
+			adapter->magic, WLAN_HDD_ADAPTER_MAGIC);
+		return -EINVAL;
+	}
+
+	if (!adapter->dev) {
+		hdd_err("adapter net_device is null");
+		return -EINVAL;
+	}
+
+	if (!(adapter->dev->flags & IFF_UP)) {
+		hdd_info("adapter net_device is not up");
+		return -EAGAIN;
+	}
+
+	if (adapter->sessionId == HDD_SESSION_ID_INVALID) {
+		hdd_info("adapter session is not open");
+		return -EAGAIN;
+	}
+
+	if (adapter->sessionId >= MAX_NUMBER_OF_ADAPTERS) {
+		hdd_err("bad adapter session Id: %u", adapter->sessionId);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
  * @hdd_adapter_t Hdd adapter.

+ 71 - 56
core/hdd/src/wlan_hdd_power.c

@@ -201,37 +201,37 @@ static void hdd_disable_gtk_offload(hdd_adapter_t *adapter)
  *	other callbacks
  */
 static int __wlan_hdd_ipv6_changed(struct notifier_block *nb,
-				 unsigned long data, void *arg)
+				   unsigned long data, void *arg)
 {
 	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
 	struct net_device *ndev = ifa->idev->dev;
-	hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
-	hdd_context_t *pHddCtx;
-	hdd_station_ctx_t *sta_ctx;
-	int status;
+	hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
+	hdd_context_t *hdd_ctx;
+	int errno;
 
 	ENTER_DEV(ndev);
 
-	if ((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
-		hdd_err("Adapter context is invalid %p", pAdapter);
-		return NOTIFY_DONE;
-	}
+	errno = hdd_validate_adapter(adapter);
+	if (errno)
+		goto exit;
+
+	if (adapter->dev == ndev &&
+	    (adapter->device_mode == QDF_STA_MODE ||
+	     adapter->device_mode == QDF_P2P_CLIENT_MODE ||
+	     adapter->device_mode == QDF_NDI_MODE)) {
+		hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+		errno = wlan_hdd_validate_context(hdd_ctx);
+		if (errno)
+			goto exit;
 
-	if ((pAdapter->dev == ndev) &&
-	    (pAdapter->device_mode == QDF_STA_MODE ||
-	     pAdapter->device_mode == QDF_P2P_CLIENT_MODE ||
-	     pAdapter->device_mode == QDF_NDI_MODE)) {
-		pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
-		status = wlan_hdd_validate_context(pHddCtx);
-		if (0 != status)
-			return NOTIFY_DONE;
-		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 		hdd_debug("invoking sme_dhcp_done_ind");
-		sme_dhcp_done_ind(pHddCtx->hHal,
-					  pAdapter->sessionId);
-		schedule_work(&pAdapter->ipv6NotifierWorkQueue);
+		sme_dhcp_done_ind(hdd_ctx->hHal, adapter->sessionId);
+		schedule_work(&adapter->ipv6NotifierWorkQueue);
 	}
+
+exit:
 	EXIT();
+
 	return NOTIFY_DONE;
 }
 
@@ -464,19 +464,25 @@ out:
  */
 static void __hdd_ipv6_notifier_work_queue(struct work_struct *work)
 {
-	hdd_adapter_t *pAdapter =
-		container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue);
-	hdd_context_t *pHddCtx;
-	int status;
+	hdd_context_t *hdd_ctx;
+	hdd_adapter_t *adapter;
+	int errno;
 
 	ENTER();
 
-	pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
-	status = wlan_hdd_validate_context(pHddCtx);
-	if (0 != status)
-		return;
+	adapter = container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue);
+	errno = hdd_validate_adapter(adapter);
+	if (errno)
+		goto exit;
 
-	hdd_enable_ns_offload(pAdapter, pmo_ipv6_change_notify);
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	errno = wlan_hdd_validate_context(hdd_ctx);
+	if (errno)
+		goto exit;
+
+	hdd_enable_ns_offload(adapter, pmo_ipv6_change_notify);
+
+exit:
 	EXIT();
 }
 
@@ -690,18 +696,28 @@ static int hdd_set_grat_arp_keepalive(hdd_adapter_t *adapter)
  */
 static void __hdd_ipv4_notifier_work_queue(struct work_struct *work)
 {
-	hdd_adapter_t *adapter;
 	hdd_context_t *hdd_ctx;
+	hdd_adapter_t *adapter;
+	int errno;
 
 	ENTER();
 
 	adapter = container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue);
-	hdd_enable_arp_offload(adapter, pmo_ipv4_change_notify);
+	errno = hdd_validate_adapter(adapter);
+	if (errno)
+		goto exit;
 
 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	errno = wlan_hdd_validate_context(hdd_ctx);
+	if (errno)
+		goto exit;
+
+	hdd_enable_arp_offload(adapter, pmo_ipv4_change_notify);
+
 	if (hdd_ctx->config->sta_keepalive_method == HDD_STA_KEEPALIVE_GRAT_ARP)
 		hdd_set_grat_arp_keepalive(adapter);
 
+exit:
 	EXIT();
 }
 
@@ -736,44 +752,43 @@ static int __wlan_hdd_ipv4_changed(struct notifier_block *nb,
 {
 	struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
 	struct net_device *ndev = ifa->ifa_dev->dev;
-	hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
-	hdd_context_t *pHddCtx;
-	hdd_station_ctx_t *sta_ctx;
-	int status;
+	hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
+	hdd_context_t *hdd_ctx;
+	int errno;
 
 	ENTER_DEV(ndev);
 
-	if ((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
-		hdd_err("Adapter context is invalid %p", pAdapter);
-		return NOTIFY_DONE;
-	}
+	errno = hdd_validate_adapter(adapter);
+	if (errno)
+		goto exit;
 
-	if ((pAdapter->dev == ndev) &&
-	    (pAdapter->device_mode == QDF_STA_MODE ||
-	     pAdapter->device_mode == QDF_P2P_CLIENT_MODE ||
-	     pAdapter->device_mode == QDF_NDI_MODE)) {
+	if (adapter->dev == ndev &&
+	    (adapter->device_mode == QDF_STA_MODE ||
+	     adapter->device_mode == QDF_P2P_CLIENT_MODE ||
+	     adapter->device_mode == QDF_NDI_MODE)) {
 
-		pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
-		status = wlan_hdd_validate_context(pHddCtx);
-		if (0 != status)
-			return NOTIFY_DONE;
+		hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+		errno = wlan_hdd_validate_context(hdd_ctx);
+		if (errno)
+			goto exit;
 
-		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 		hdd_debug("invoking sme_dhcp_done_ind");
-		sme_dhcp_done_ind(pHddCtx->hHal,
-					  pAdapter->sessionId);
+		sme_dhcp_done_ind(hdd_ctx->hHal, adapter->sessionId);
 
-		if (!pHddCtx->config->fhostArpOffload) {
+		if (!hdd_ctx->config->fhostArpOffload) {
 			hdd_debug("Offload not enabled ARPOffload=%d",
-				pHddCtx->config->fhostArpOffload);
-			return NOTIFY_DONE;
+				  hdd_ctx->config->fhostArpOffload);
+			goto exit;
 		}
 
-		ifa = hdd_lookup_ifaddr(pAdapter);
+		ifa = hdd_lookup_ifaddr(adapter);
 		if (ifa && ifa->ifa_local)
-			schedule_work(&pAdapter->ipv4NotifierWorkQueue);
+			schedule_work(&adapter->ipv4NotifierWorkQueue);
 	}
+
+exit:
 	EXIT();
+
 	return NOTIFY_DONE;
 }