summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRavi Joshi <ravij@qca.qualcomm.com>2016-03-22 17:13:56 -0700
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-03-30 12:36:41 +0530
commitce9fb49f08f12596abccf12641c853855529575e (patch)
tree155d8d1698e35b52b7f414e64311daad306b8697
parentc65abc4359220a2c561aa49772abe1a11d998c26 (diff)
qcacld-2.0: Delete NDI netdev if start bss fails
The NAN Data Interface is required to be deleted if start bss fails for some reason. Change-Id: I83f2511a9df569fde791a0da110ac873fb0381dd CRs-Fixed: 962367
-rw-r--r--CORE/HDD/src/wlan_hdd_nan_datapath.c105
1 files changed, 91 insertions, 14 deletions
diff --git a/CORE/HDD/src/wlan_hdd_nan_datapath.c b/CORE/HDD/src/wlan_hdd_nan_datapath.c
index 3c4d6dd87381..1b5e4db3100c 100644
--- a/CORE/HDD/src/wlan_hdd_nan_datapath.c
+++ b/CORE/HDD/src/wlan_hdd_nan_datapath.c
@@ -95,6 +95,62 @@ void hdd_nan_datapath_target_config(hdd_context_t *hdd_ctx,
}
/**
+ * 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 (WLAN_HDD_NDI != adapter->device_mode) {
+ hddLog(LOGE, 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
+ wlan_hdd_clean_tx_flow_control_timer(hdd_ctx, 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 (eHAL_STATUS_SUCCESS == sme_CloseSession(hdd_ctx->hHal,
+ adapter->sessionId,
+ hdd_smeCloseSessionCallback, adapter)) {
+ /* Block on a timed completion variable */
+ rc = wait_for_completion_timeout(
+ &adapter->session_close_comp_var,
+ msecs_to_jiffies(timeout));
+ if (!rc)
+ hddLog(LOGE, 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
@@ -253,8 +309,11 @@ static int hdd_ndi_create_req_handler(hdd_context_t *hdd_ctx,
op_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
}
ret = hdd_ndi_start_bss(adapter, op_channel);
- if (0 > ret)
+ if (0 > ret) {
hddLog(LOGE, FL("NDI start bss failed"));
+ /* Start BSS failed, delete the interface */
+ hdd_close_ndi(adapter);
+ }
EXIT();
return ret;
@@ -393,6 +452,9 @@ static int hdd_ndp_schedule_req_handler(hdd_context_t *hdd_ctx,
* @adapter: pointer to adapter context
* @rsp_params: response parameters
*
+ * The function is expected to send a response back to the user space
+ * even if the creation of BSS has failed
+ *
* Return: none
*/
static void hdd_ndp_iface_create_rsp_handler(hdd_adapter_t *adapter,
@@ -404,20 +466,28 @@ static void hdd_ndp_iface_create_rsp_handler(hdd_adapter_t *adapter,
uint32_t data_len = (2 * sizeof(uint32_t)) + sizeof(uint16_t) +
NLMSG_HDRLEN + (3 * 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 {
hddLog(LOGE, 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 {
hddLog(LOGE, FL("ndp_ctx is NULL"));
- return;
+ create_fail = true;
}
/* notify response to the upper layer */
@@ -429,7 +499,8 @@ static void hdd_ndp_iface_create_rsp_handler(hdd_adapter_t *adapter,
if (!vendor_event) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
- return;
+ create_fail = true;
+ goto close_ndi;
}
/* Sub vendor command */
@@ -441,14 +512,14 @@ static void hdd_ndp_iface_create_rsp_handler(hdd_adapter_t *adapter,
/* Transaction id */
if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
- ndp_ctx->ndp_create_transaction_id)) {
+ create_transaction_id)) {
hddLog(LOGE, 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)) {
hddLog(LOGE, FL("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"));
goto nla_put_failure;
}
@@ -465,29 +536,35 @@ static void hdd_ndp_iface_create_rsp_handler(hdd_adapter_t *adapter,
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;
- ndp_ctx->state = NAN_DATA_NDI_CREATED_STATE;
-
- if (ndi_rsp->status == VOS_STATUS_SUCCESS) {
+ if (!create_fail && ndi_rsp->status == VOS_STATUS_SUCCESS) {
hddLog(LOGE, FL("NDI interface successfully created"));
+ ndp_ctx->ndp_create_transaction_id = 0;
+ ndp_ctx->state = NAN_DATA_NDI_CREATED_STATE;
} else {
hddLog(LOGE,
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;
}