qcacmn: Fix deadlock in wlan_pdev_chan_match due to cross locking

wlan_pdev_chan_match used to take current vdev lock on current
iterating vdev and then on vdev for which channel set is triggered.
If two cores happed to try setting channel on two different vdevs,
cross locking may occur. Fix this by releasing one lock and then
acquiring other lock.

Change-Id: Ic1a6ca448c6d535e949102bc5a8a45971c8babd2
CRs-Fixed: 2460054
This commit is contained in:
Om Prakash Tripathi
2019-05-28 17:20:01 +05:30
committed by nshrivas
parent 6c1cdf307a
commit 03db80d4e7

View File

@@ -311,7 +311,7 @@ static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object,
{
struct wlan_objmgr_vdev *comp_vdev = (struct wlan_objmgr_vdev *)object;
struct wlan_vdev_ch_check_filter *ch_filter = arg;
struct wlan_channel *vdev_chan;
struct wlan_channel vdev_chan, *chan;
struct wlan_channel *iter_vdev_chan;
if (ch_filter->flag)
@@ -321,25 +321,27 @@ static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object,
return;
wlan_vdev_obj_lock(comp_vdev);
wlan_vdev_obj_lock(ch_filter->vdev);
chan = wlan_vdev_get_active_channel(comp_vdev);
if (!chan) {
wlan_vdev_obj_unlock(comp_vdev);
return;
}
wlan_chan_copy(&vdev_chan, chan);
wlan_vdev_obj_unlock(comp_vdev);
vdev_chan = wlan_vdev_get_active_channel(comp_vdev);
if (vdev_chan) {
iter_vdev_chan = wlan_vdev_mlme_get_des_chan(
ch_filter->vdev);
if (wlan_chan_eq(vdev_chan, iter_vdev_chan)
wlan_vdev_obj_lock(ch_filter->vdev);
iter_vdev_chan = wlan_vdev_mlme_get_des_chan(ch_filter->vdev);
if (wlan_chan_eq(&vdev_chan, iter_vdev_chan)
!= QDF_STATUS_SUCCESS) {
ch_filter->flag = 1;
qdf_nofl_err("==> iter vdev id: %d: ieee %d, mode %d",
wlan_vdev_get_id(comp_vdev),
vdev_chan->ch_ieee,
vdev_chan->ch_phymode);
vdev_chan.ch_ieee,
vdev_chan.ch_phymode);
qdf_nofl_err("fl %016llx, fl-ext %08x, s1 %d, s2 %d ",
vdev_chan->ch_flags, vdev_chan->ch_flagext,
vdev_chan->ch_freq_seg1,
vdev_chan->ch_freq_seg2);
vdev_chan.ch_flags, vdev_chan.ch_flagext,
vdev_chan.ch_freq_seg1,
vdev_chan.ch_freq_seg2);
qdf_nofl_err("==> base vdev id: %d: ieee %d mode %d",
wlan_vdev_get_id(ch_filter->vdev),
iter_vdev_chan->ch_ieee,
@@ -350,10 +352,7 @@ static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object,
iter_vdev_chan->ch_freq_seg1,
iter_vdev_chan->ch_freq_seg2);
}
}
wlan_vdev_obj_unlock(ch_filter->vdev);
wlan_vdev_obj_unlock(comp_vdev);
}
QDF_STATUS wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev *pdev,