From 03db80d4e7cbdf6f33f2c938618907e9d2c0634f Mon Sep 17 00:00:00 2001 From: Om Prakash Tripathi Date: Tue, 28 May 2019 17:20:01 +0530 Subject: [PATCH] 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 --- umac/cmn_services/utils/src/wlan_utility.c | 63 +++++++++++----------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/umac/cmn_services/utils/src/wlan_utility.c b/umac/cmn_services/utils/src/wlan_utility.c index 318d62baabf6..5bab3e124d4d 100644 --- a/umac/cmn_services/utils/src/wlan_utility.c +++ b/umac/cmn_services/utils/src/wlan_utility.c @@ -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,39 +321,38 @@ 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); - - 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) - != 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); - 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); - - qdf_nofl_err("==> base vdev id: %d: ieee %d mode %d", - wlan_vdev_get_id(ch_filter->vdev), - iter_vdev_chan->ch_ieee, - iter_vdev_chan->ch_phymode); - qdf_nofl_err("fl %016llx, fl-ext %08x s1 %d, s2 %d", - iter_vdev_chan->ch_flags, - iter_vdev_chan->ch_flagext, - iter_vdev_chan->ch_freq_seg1, - iter_vdev_chan->ch_freq_seg2); - } + chan = wlan_vdev_get_active_channel(comp_vdev); + if (!chan) { + wlan_vdev_obj_unlock(comp_vdev); + return; } - - wlan_vdev_obj_unlock(ch_filter->vdev); + wlan_chan_copy(&vdev_chan, chan); wlan_vdev_obj_unlock(comp_vdev); + + 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); + 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); + qdf_nofl_err("==> base vdev id: %d: ieee %d mode %d", + wlan_vdev_get_id(ch_filter->vdev), + iter_vdev_chan->ch_ieee, + iter_vdev_chan->ch_phymode); + qdf_nofl_err("fl %016llx, fl-ext %08x s1 %d, s2 %d", + iter_vdev_chan->ch_flags, + iter_vdev_chan->ch_flagext, + iter_vdev_chan->ch_freq_seg1, + iter_vdev_chan->ch_freq_seg2); + } + wlan_vdev_obj_unlock(ch_filter->vdev); } QDF_STATUS wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev *pdev,