qcacld-3.0: Delete NDI netdev if start bss fails
qcacld-2.0 to qcacld-3.0 propagation
The NAN Data Interface is required to be deleted if start bss
fails for some reason.
Change-Id: I83f2511a9df569fde791a0da110ac873fb0381dd
CRs-Fixed: 962367
diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c
index 6c53f7b..c38ccf7 100644
--- a/core/hdd/src/wlan_hdd_nan_datapath.c
+++ b/core/hdd/src/wlan_hdd_nan_datapath.c
@@ -93,6 +93,62 @@
}
/**
+ * hdd_close_ndi() - close NAN Data interface
+ * @adapter: adapter context
+ *
+ * Close the adapter if start BSS fails
+ *
+ * Returns: 0 on success, negative error code otherwise
+ */
+static int hdd_close_ndi(hdd_adapter_t *adapter)
+{
+ int rc;
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ uint32_t timeout = WLAN_WAIT_TIME_SESSIONOPENCLOSE;
+
+ ENTER();
+
+ /* check if the adapter is in NAN Data mode */
+ if (QDF_NDI_MODE != adapter->device_mode) {
+ hdd_err(FL("Interface is not in NDI mode"));
+ return -EINVAL;
+ }
+ netif_tx_disable(adapter->dev);
+ netif_carrier_off(adapter->dev);
+
+#ifdef WLAN_OPEN_SOURCE
+ cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
+#endif
+ hdd_deregister_tx_flow_control(adapter);
+
+#ifdef WLAN_NS_OFFLOAD
+#ifdef WLAN_OPEN_SOURCE
+ cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
+#endif
+#endif
+ /* check if the session is open */
+ if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
+ INIT_COMPLETION(adapter->session_close_comp_var);
+ if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
+ adapter->sessionId,
+ hdd_sme_close_session_callback, adapter)) {
+ /* Block on a timed completion variable */
+ rc = wait_for_completion_timeout(
+ &adapter->session_close_comp_var,
+ msecs_to_jiffies(timeout));
+ if (!rc)
+ hdd_err(FL("session close timeout"));
+ }
+ }
+
+ /* We are good to close the adapter */
+ hdd_close_adapter(hdd_ctx, adapter, true);
+
+ EXIT();
+ return 0;
+}
+
+/**
* hdd_ndi_start_bss() - Start BSS on NAN data interface
* @adapter: adapter context
* @operating_channel: channel on which the BSS to be started
@@ -243,8 +299,11 @@
op_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
}
ret = hdd_ndi_start_bss(adapter, op_channel);
- if (0 > ret)
+ if (0 > ret) {
hdd_err(FL("NDI start bss failed"));
+ /* Start BSS failed, delete the interface */
+ hdd_close_ndi(adapter);
+ }
EXIT();
return ret;
@@ -404,20 +463,28 @@
uint32_t data_len = (3 * sizeof(uint32_t)) + sizeof(uint16_t) +
NLMSG_HDRLEN + (4 * NLA_HDRLEN);
struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
+ bool create_fail = false;
+ uint8_t create_transaction_id = 0;
+ uint8_t create_status = 0;
ENTER();
if (wlan_hdd_validate_context(hdd_ctx))
+ /* No way the driver can send response back to user space */
return;
- if (!ndi_rsp) {
+ if (ndi_rsp) {
+ create_status = ndi_rsp->status;
+ } else {
hdd_err(FL("Invalid ndi create response"));
- return;
+ create_fail = true;
}
- if (!ndp_ctx) {
+ if (ndp_ctx) {
+ create_transaction_id = ndp_ctx->ndp_create_transaction_id;
+ } else {
hdd_err(FL("ndp_ctx is NULL"));
- return;
+ create_fail = true;
}
/* notify response to the upper layer */
@@ -429,7 +496,8 @@
if (!vendor_event) {
hdd_err(FL("cfg80211_vendor_event_alloc failed"));
- return;
+ create_fail = true;
+ goto close_ndi;
}
/* Sub vendor command */
@@ -441,14 +509,14 @@
/* Transaction id */
if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
- ndp_ctx->ndp_create_transaction_id)) {
+ create_transaction_id)) {
hdd_err(FL("VENDOR_ATTR_NDP_TRANSACTION_ID put fail"));
goto nla_put_failure;
}
/* Status code */
if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE,
- ndi_rsp->status)) {
+ create_status)) {
hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"));
goto nla_put_failure;
}
@@ -465,27 +533,34 @@
QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE);
hddLog(LOG2, FL("create transaction id: %d, value: %d"),
QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
- ndp_ctx->ndp_create_transaction_id);
+ create_transaction_id);
hddLog(LOG2, FL("status code: %d, value: %d"),
- QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, ndi_rsp->status);
+ QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, create_status);
hddLog(LOG2, FL("Return value: %d, value: %d"),
QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0xA5);
cfg80211_vendor_event(vendor_event, GFP_KERNEL);
- ndp_ctx->ndp_create_transaction_id = 0;
-
- if (ndi_rsp->status == QDF_STATUS_SUCCESS) {
+ if (!create_fail && ndi_rsp->status == QDF_STATUS_SUCCESS) {
hdd_err(FL("NDI interface successfully created"));
+ ndp_ctx->ndp_create_transaction_id = 0;
+ ndp_ctx->state = NAN_DATA_NDI_CREATED_STATE;
} else {
hdd_err(FL("NDI interface creation failed with reason %d"),
ndi_rsp->reason);
}
+
+ /* Something went wrong while starting the BSS */
+ if (create_fail)
+ goto close_ndi;
+
EXIT();
return;
nla_put_failure:
kfree_skb(vendor_event);
+close_ndi:
+ hdd_close_ndi(adapter);
return;
}