qcacld-3.0: Do netif_tx_stop_all_queues() instead of netif_tx_disable()

Race condition is happening when tx traffic is running and simulataneously
suspend is going on. hdd_hard_start_xmit() is called under txq->__xmit_lock
and in case of low descriptor scenario, it goes to pause the netif queues
and trying to take adapter->pause_map_lock for doing so which is already
acquired by another thread. In another thread, suspend indication is being
preocessed and as a result is trying to pause netif queues with
netif_action WLAN_NETIF_TX_DISABLE which takes adapter->pause_map_lock and
then calls netif_tx_disable() which is trying to take txq->__xmit_lock
already taken by the thread executing hdd_hard_start_xmit(). This leads to
a deadlock situation.

Replace netif_tx_disable() with netif_tx_stop_all_queues() as
netif_tx_stop_all_queues() is doing the same thing as netif_tx_disable()
only without taking the txq->__xmit_lock which prevents this deadlock.

Change-Id: I5afafe6435707bd8f0e87972a740f908d06ce847
CRs-Fixed: 2030933
Tento commit je obsažen v:
Himanshu Agarwal
2017-04-12 15:45:31 +05:30
odevzdal Sandeep Puligilla
rodič 9d42b441c7
revize 865201d99d
10 změnil soubory, kde provedl 40 přidání a 60 odebrání

Zobrazit soubor

@@ -1839,7 +1839,7 @@ void ol_txrx_vdev_pause(struct cdp_vdev *pvdev, uint32_t reason)
if (netif_reason == WLAN_REASON_TYPE_MAX)
return;
pdev->pause_cb(vdev->vdev_id, WLAN_NETIF_TX_DISABLE, netif_reason);
pdev->pause_cb(vdev->vdev_id, WLAN_STOP_ALL_NETIF_QUEUE, netif_reason);
}
/**

Zobrazit soubor

@@ -1553,8 +1553,9 @@ static QDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter,
}
/* notify apps that we can't pass traffic anymore */
hdd_notice("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
wlan_hdd_netif_queue_control(pAdapter,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
if (hdd_ipa_is_enabled(pHddCtx))
hdd_ipa_wlan_evt(pAdapter, pHddStaCtx->conn_info.staId[0],
@@ -2986,7 +2987,7 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
hdd_info("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
}
@@ -3493,7 +3494,7 @@ roam_roam_connect_status_update_handler(hdd_adapter_t *pAdapter,
/* Stop only when we are inactive */
hdd_info("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
hdd_conn_set_connection_state(pAdapter,
eConnectionState_NotConnected);
@@ -4781,7 +4782,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
hdd_debug("Roam Synch Ind: NAPI Serialize ON");
hdd_napi_serialize(1);
wlan_hdd_netif_queue_control(pAdapter,
WLAN_NETIF_TX_DISABLE,
WLAN_STOP_ALL_NETIF_QUEUE,
WLAN_CONTROL_PATH);
status = hdd_roam_deregister_sta(pAdapter,
pHddStaCtx->conn_info.staId[0]);
@@ -4803,7 +4804,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
/* notify apps that we can't pass traffic anymore */
hdd_debug("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter,
WLAN_NETIF_TX_DISABLE,
WLAN_STOP_ALL_NETIF_QUEUE,
WLAN_CONTROL_PATH);
if (pHddStaCtx->ft_carrier_on == false) {
wlan_hdd_netif_queue_control(pAdapter,
@@ -4816,7 +4817,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
hdd_debug("Roaming started due to connection lost");
hdd_info("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
break;
}
@@ -5048,7 +5049,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
case eCSR_ROAM_START:
hdd_debug("Process ROAM_START from firmware");
wlan_hdd_netif_queue_control(pAdapter,
WLAN_NETIF_TX_DISABLE,
WLAN_STOP_ALL_NETIF_QUEUE,
WLAN_CONTROL_PATH);
hdd_napi_serialize(1);
hdd_set_connection_in_progress(true);

Zobrazit soubor

@@ -14274,7 +14274,7 @@ static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
/* stop tx queues */
hdd_debug("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
INIT_COMPLETION(pAdapter->disconnect_comp_var);

Zobrazit soubor

@@ -312,8 +312,9 @@ static int __hdd_hostapd_stop(struct net_device *dev)
clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
/* Stop all tx queues */
hdd_notice("Disabling queues");
wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
wlan_hdd_netif_queue_control(adapter,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
EXIT();
return 0;
@@ -2103,8 +2104,8 @@ stopbss:
*/
hdd_notice("Disabling queues");
wlan_hdd_netif_queue_control(pHostapdAdapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
/* reclaim all resources allocated to the BSS */
qdf_status = hdd_softap_stop_bss(pHostapdAdapter);
@@ -8096,7 +8097,8 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
sizeof(struct sap_acs_cfg));
/* Stop all tx queues */
hdd_notice("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
wlan_hdd_netif_queue_control(pAdapter,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
old = pAdapter->sessionCtx.ap.beacon;

Zobrazit soubor

@@ -2308,8 +2308,9 @@ static int __hdd_stop(struct net_device *dev)
* be called on that interface
*/
hdd_notice("Disabling queues");
wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
wlan_hdd_netif_queue_control(adapter,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
/*
* NAN data interface is different in some sense. The traffic on NDI is
@@ -3669,8 +3670,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
/* Stop the Interface TX queue. */
hdd_info("Disabling queues");
wlan_hdd_netif_queue_control(adapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
break;
@@ -3698,8 +3699,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
}
hdd_info("Disabling queues");
wlan_hdd_netif_queue_control(adapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
break;
case QDF_FTM_MODE:
adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
@@ -3719,8 +3720,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
/* Stop the Interface TX queue. */
hdd_info("Disabling queues");
wlan_hdd_netif_queue_control(adapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
break;
default:
hdd_err("Invalid session type %d", session_type);
@@ -3930,8 +3931,9 @@ QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
scan_info = &adapter->scan_info;
hdd_notice("Disabling queues");
wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
wlan_hdd_netif_queue_control(adapter,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
switch (adapter->device_mode) {
case QDF_STA_MODE:
case QDF_P2P_CLIENT_MODE:
@@ -4163,7 +4165,7 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
if (hdd_ctx->config->sap_internal_restart &&
adapter->device_mode == QDF_SAP_MODE) {
wlan_hdd_netif_queue_control(adapter,
WLAN_NETIF_TX_DISABLE,
WLAN_STOP_ALL_NETIF_QUEUE,
WLAN_CONTROL_PATH);
if (test_bit(SOFTAP_BSS_STARTED,
&adapter->event_flags)) {
@@ -4174,7 +4176,7 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
} else {
wlan_hdd_netif_queue_control(adapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
}

Zobrazit soubor

@@ -132,7 +132,7 @@ static int hdd_close_ndi(hdd_adapter_t *adapter)
return -EINVAL;
}
wlan_hdd_netif_queue_control(adapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
#ifdef WLAN_OPEN_SOURCE

Zobrazit soubor

@@ -410,8 +410,9 @@ static int hdd_ocb_set_config_req(hdd_adapter_t *adapter,
cookie = hdd_request_cookie(hdd_request);
hdd_notice("Disabling queues");
wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_CONTROL_PATH);
wlan_hdd_netif_queue_control(adapter,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
/* Call the SME API to set the config */
status = sme_ocb_set_config(hdd_ctx->hHal, cookie,

Zobrazit soubor

@@ -1035,8 +1035,9 @@ hdd_suspend_wlan(void)
/* stop all TX queues before suspend */
hdd_debug("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE,
WLAN_CONTROL_PATH);
wlan_hdd_netif_queue_control(pAdapter,
WLAN_STOP_ALL_NETIF_QUEUE,
WLAN_CONTROL_PATH);
/* Configure supported OffLoads */
hdd_enable_host_offloads(pAdapter, pmo_apps_suspend);

Zobrazit soubor

@@ -1190,8 +1190,6 @@ const char *hdd_action_type_to_string(enum netif_action_type action)
CASE_RETURN_STRING(WLAN_WAKE_ALL_NETIF_QUEUE);
CASE_RETURN_STRING(WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER);
CASE_RETURN_STRING(WLAN_START_ALL_NETIF_QUEUE_N_CARRIER);
CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE);
CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE_N_CARRIER);
CASE_RETURN_STRING(WLAN_NETIF_CARRIER_ON);
CASE_RETURN_STRING(WLAN_NETIF_CARRIER_OFF);
default:
@@ -1211,8 +1209,6 @@ static void wlan_hdd_update_queue_oper_stats(hdd_adapter_t *adapter,
switch (action) {
case WLAN_STOP_ALL_NETIF_QUEUE:
case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER:
case WLAN_NETIF_TX_DISABLE:
case WLAN_NETIF_TX_DISABLE_N_CARRIER:
adapter->queue_oper_stats[reason].pause_count++;
break;
case WLAN_START_ALL_NETIF_QUEUE:
@@ -1377,29 +1373,6 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
spin_unlock_bh(&adapter->pause_map_lock);
break;
case WLAN_NETIF_TX_DISABLE:
spin_lock_bh(&adapter->pause_map_lock);
if (!adapter->pause_map) {
netif_tx_disable(adapter->dev);
wlan_hdd_update_txq_timestamp(adapter->dev);
wlan_hdd_update_unpause_time(adapter);
}
adapter->pause_map |= (1 << reason);
spin_unlock_bh(&adapter->pause_map_lock);
break;
case WLAN_NETIF_TX_DISABLE_N_CARRIER:
spin_lock_bh(&adapter->pause_map_lock);
if (!adapter->pause_map) {
netif_tx_disable(adapter->dev);
wlan_hdd_update_txq_timestamp(adapter->dev);
wlan_hdd_update_unpause_time(adapter);
}
adapter->pause_map |= (1 << reason);
netif_carrier_off(adapter->dev);
spin_unlock_bh(&adapter->pause_map_lock);
break;
default:
hdd_err("unsupported action %d", action);
}

Zobrazit soubor

@@ -7187,7 +7187,7 @@ static int __iw_set_mlme(struct net_device *dev,
hdd_notice("Disabling queues");
wlan_hdd_netif_queue_control(pAdapter,
WLAN_NETIF_TX_DISABLE_N_CARRIER,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
} else {