Merge "qcacmn: Fix deadlock in dp_delete_pending_vdev() API"

This commit is contained in:
Linux Build Service Account 2018-09-28 03:35:09 -07:00 • committed by Gerrit - the friendly Code Review server
commit a647143904
2 changed files with 188 additions and 28 deletions

View file

@ -4648,40 +4648,44 @@ static void dp_reset_and_release_peer_mem(struct dp_soc *soc,
qdf_mem_free(peer);
}
static void dp_delete_pending_vdev(struct dp_pdev *pdev, uint32_t vdev_id)
/**
* dp_delete_pending_vdev() - check and process vdev delete
* @pdev: DP specific pdev pointer
* @vdev: DP specific vdev pointer
* @vdev_id: vdev id corresponding to vdev
*
* This API does following:
* 1) It releases tx flow pools buffers as vdev is
* going down and no peers are associated.
* 2) It also detaches vdev before cleaning vdev (struct dp_vdev) memory
*/
static void dp_delete_pending_vdev(struct dp_pdev *pdev, struct dp_vdev *vdev,
uint8_t vdev_id)
{
struct dp_vdev *vdev = NULL;
ol_txrx_vdev_delete_cb vdev_delete_cb = NULL;
void *vdev_delete_context = NULL;
qdf_spin_lock_bh(&pdev->vdev_list_lock);
TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
if (vdev->vdev_id == vdev_id)
break;
}
if (!vdev) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"vdev is NULL");
} else if (vdev->delete.pending) {
vdev_delete_cb = vdev->delete.callback;
vdev_delete_context = vdev->delete.context;
vdev_delete_cb = vdev->delete.callback;
vdev_delete_context = vdev->delete.context;
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
FL("deleting vdev object %pK (%pM)- its last peer is done"),
vdev, vdev->mac_addr.raw);
/* all peers are gone, go ahead and delete it */
dp_tx_flow_pool_unmap_handler(pdev, vdev_id,
FLOW_TYPE_VDEV, vdev_id);
dp_tx_vdev_detach(vdev);
TAILQ_REMOVE(&pdev->vdev_list, vdev, vdev_list_elem);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
FL("deleting vdev object %pK (%pM)"),
vdev, vdev->mac_addr.raw);
qdf_mem_free(vdev);
vdev = NULL;
}
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
FL("deleting vdev object %pK (%pM)- its last peer is done"),
vdev, vdev->mac_addr.raw);
/* all peers are gone, go ahead and delete it */
dp_tx_flow_pool_unmap_handler(pdev, vdev_id,
FLOW_TYPE_VDEV, vdev_id);
dp_tx_vdev_detach(vdev);
qdf_spin_lock_bh(&pdev->vdev_list_lock);
TAILQ_REMOVE(&pdev->vdev_list, vdev, vdev_list_elem);
qdf_spin_unlock_bh(&pdev->vdev_list_lock);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
FL("deleting vdev object %pK (%pM)"),
vdev, vdev->mac_addr.raw);
qdf_mem_free(vdev);
vdev = NULL;
if (vdev_delete_cb)
vdev_delete_cb(vdev_delete_context);
}
@ -4701,6 +4705,7 @@ void dp_peer_unref_delete(void *peer_handle)
int found = 0;
uint16_t peer_id;
uint16_t vdev_id;
bool delete_vdev;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
"%s: peer %pK ref_cnt(before decrement): %d\n", __func__,
@ -4762,6 +4767,11 @@ void dp_peer_unref_delete(void *peer_handle)
/* check whether the parent vdev has no peers left */
if (TAILQ_EMPTY(&vdev->peer_list)) {
/*
* capture vdev delete pending flag's status
* while holding peer_ref_mutex lock
*/
delete_vdev = vdev->delete.pending;
/*
* Now that there are no references to the peer, we can
* release the peer reference lock.
@ -4771,7 +4781,8 @@ void dp_peer_unref_delete(void *peer_handle)
* Check if the parent vdev was waiting for its peers
* to be deleted, in order for it to be deleted too.
*/
dp_delete_pending_vdev(pdev, vdev_id);
if (delete_vdev)
dp_delete_pending_vdev(pdev, vdev, vdev_id);
} else {
qdf_spin_unlock_bh(&soc->peer_ref_mutex);
}

View file

@ -6116,10 +6116,159 @@ enum qca_wlan_vendor_attr_wifi_test_config {
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP = 22,
/* Nested attribute values required to setup the TWT session.
* enum qca_wlan_vendor_attr_twt_setup provides the necessary
* information to set up the session. It contains broadcast flags,
* set_up flags, trigger value, flow type, flow ID, wake interval
* exponent, protection, target wake time, wake duration, wake interval
* mantissa. These nested attributes are used to setup a host triggered
* TWT session.
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP = 23,
/* This nested attribute is used to terminate the current TWT session.
* It does not currently carry any attributes.
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE = 24,
/* This nested attribute is used to suspend the current TWT session.
* It does not currently carry any attributes.
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SUSPEND = 25,
/* Nested attribute values to indicate the request for resume.
* This attribute is used to resume the TWT session.
* enum qca_wlan_vendor_attr_twt_resume provides the necessary
* parameters required to resume the TWT session.
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME = 26,
/* keep last */
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST - 1,
};
/**
* enum qca_wlan_vendor_attr_twt_setup: Represents attributes for
* TWT (Target Wake Time) setup request. These attributes are sent as part of
* %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and
* %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST: Flag attribute.
* Disable (flag attribute not present) - Individual TWT
* Enable (flag attribute present) - Broadcast TWT.
* Individual means the session is between the STA and the AP.
* This session is established using a separate negotiation between
* STA and AP.
* Broadcast means the session is across multiple STAs and an AP. The
* configuration parameters are announced in Beacon frames by the AP.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE: Required (u8).
* Unsigned 8-bit qca_wlan_vendor_twt_setup_req_type to
* specify the TWT request type
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER: Flag attribute
* Enable (flag attribute present) - TWT with trigger support.
* Disable (flag attribute not present) - TWT without trigger support.
* Trigger means the AP will send the trigger frame to allow STA to send data.
* Without trigger, the STA will wait for the MU EDCA timer before
* transmitting the data.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE: Required (u8)
* 0 - Announced TWT - In this mode, STA may skip few service periods to
* save more power. If STA wants to wake up, it will send a PS-POLL/QoS
* NULL frame to AP.
* 1 - Unannounced TWT - The STA will wakeup during every SP.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID: Optional (u8)
* Flow ID is the unique identifier for each TWT session.
* Currently this is not required and dialog ID will be set to zero.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8)
* This attribute (exp) is used along with the mantissa to derive the
* wake interval using the following formula:
* pow(2,exp) = wake_intvl_us/wake_intvl_mantis
* Wake interval is the interval between 2 successive SP.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION: Flag attribute
* Enable (flag attribute present) - Protection required.
* Disable (flag attribute not present) - Protection not required.
* If protection is enabled, then the AP will use protection
* mechanism using RTS/CTS to self to reserve the airtime.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME: Optional (u32)
* This attribute is used as the SP offset which is the offset from
* TSF after which the wake happens. The units are in microseconds. If
* this attribute is not provided, then the value will be set to zero.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION: Required (u32)
* This is the duration of the service period. The units are in TU.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA: Required (u32)
* This attribute is used to configure wake interval mantissa.
* The units are in TU.
*/
enum qca_wlan_vendor_attr_twt_setup {
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST = 1,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE = 2,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER = 3,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE = 4,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID = 5,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP = 6,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION = 7,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME = 8,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION = 9,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA = 10,
/* keep last */
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX =
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST - 1,
};
/**
* enum qca_wlan_vendor_attr_twt_resume: Represents attributes for
* TWT (Target Wake Time) resume request. These attributes are sent as part of
* %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME and
* %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT: Optional (u8)
* This attribute is used as the SP offset which is the offset from
* TSF after which the wake happens. The units are in microseconds.
* If this attribute is not provided, then the value will be set to
* zero.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE: Required (u32)
* This attribute represents the next TWT subfield size.
*/
enum qca_wlan_vendor_attr_twt_resume {
QCA_WLAN_VENDOR_ATTR_TWT_RESUME_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT = 1,
QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE = 2,
/* keep last */
QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAX =
QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST - 1,
};
/**
* enum qca_wlan_vendor_twt_setup_req_type - Required (u8)
* Represents the setup type being requested for TWT.
* @QCA_WLAN_VENDOR_TWT_SETUP_REQUEST: STA is not specifying all the TWT
* parameters but relying on AP to fill the parameters during the negotiation.
* @QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST: STA will provide all the suggested
* values which the AP may accept or AP may provide alternative parameters
* which the STA may accept.
* @QCA_WLAN_VENDOR_TWT_SETUP_DEMAND: STA is not willing to accept any
* alternate parameters than the requested ones.
*/
enum qca_wlan_vendor_twt_setup_req_type {
QCA_WLAN_VENDOR_TWT_SETUP_REQUEST = 1,
QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST = 2,
QCA_WLAN_VENDOR_TWT_SETUP_DEMAND = 3,
};
#endif