> > > The patch below does not apply to the 3.13-stable tree. > If someone wants it applied there, or to any other stable or longterm tree, > then please email the backport, including the original git commit id to > <stable@xxxxxxxxxxxxxxx>. > N/M - after all, this patch isn't crucial in 3.13. We don't use this feature there anyway. We’ll not port it to 3.13. Thanks! > thanks, > > greg k-h > > ------------------ original commit in Linus's tree ------------------ > > From 8ffcc704c963b4157391bd87a4544cdfd18b574d Mon Sep 17 00:00:00 > 2001 > From: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> > Date: Thu, 23 Jan 2014 14:28:16 +0200 > Subject: [PATCH] mac80211: avoid deadlock revealed by lockdep > MIME-Version: 1.0 > Content-Type: text/plain; charset=UTF-8 > Content-Transfer-Encoding: 8bit > > sdata->u.ap.request_smps_work can’t be flushed synchronously > under wdev_lock(wdev) since ieee80211_request_smps_ap_work itself > locks the same lock. > While at it, reset the driver_smps_mode when the ap is stopped to its > default: OFF. > > This solves: > > ====================================================== > [ INFO: possible circular locking dependency detected ] > 3.12.0-ipeer+ #2 Tainted: G O > ------------------------------------------------------- > rmmod/2867 is trying to acquire lock: > ((&sdata->u.ap.request_smps_work)){+.+...}, at: [<c105b8d0>] > flush_work+0x0/0x90 > > but task is already holding lock: > (&wdev->mtx){+.+.+.}, at: [<f9b32626>] cfg80211_stop_ap+0x26/0x230 > [cfg80211] > > which lock already depends on the new lock. > > the existing dependency chain (in reverse order) is: > > -> #1 (&wdev->mtx){+.+.+.}: > [<c10aefa9>] lock_acquire+0x79/0xe0 > [<c1607a1a>] mutex_lock_nested+0x4a/0x360 > [<fb06288b>] ieee80211_request_smps_ap_work+0x2b/0x50 > [mac80211] > [<c105cdd8>] process_one_work+0x198/0x450 > [<c105d469>] worker_thread+0xf9/0x320 > [<c10669ff>] kthread+0x9f/0xb0 > [<c1613397>] ret_from_kernel_thread+0x1b/0x28 > > -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}: > [<c10ae9df>] __lock_acquire+0x183f/0x1910 > [<c10aefa9>] lock_acquire+0x79/0xe0 > [<c105b917>] flush_work+0x47/0x90 > [<c105d867>] __cancel_work_timer+0x67/0xe0 > [<c105d90f>] cancel_work_sync+0xf/0x20 > [<fb0765cc>] ieee80211_stop_ap+0x8c/0x340 [mac80211] > [<f9b3268c>] cfg80211_stop_ap+0x8c/0x230 [cfg80211] > [<f9b0d8f9>] cfg80211_leave+0x79/0x100 [cfg80211] > [<f9b0da72>] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211] > [<c160f2c9>] notifier_call_chain+0x59/0x130 > [<c106c6de>] __raw_notifier_call_chain+0x1e/0x30 > [<c106c70f>] raw_notifier_call_chain+0x1f/0x30 > [<c14f8213>] call_netdevice_notifiers_info+0x33/0x70 > [<c14f8263>] call_netdevice_notifiers+0x13/0x20 > [<c14f82a4>] __dev_close_many+0x34/0xb0 > [<c14f83fe>] dev_close_many+0x6e/0xc0 > [<c14f9c77>] rollback_registered_many+0xa7/0x1f0 > [<c14f9dd4>] unregister_netdevice_many+0x14/0x60 > [<fb06f4d9>] ieee80211_remove_interfaces+0xe9/0x170 [mac80211] > [<fb055116>] ieee80211_unregister_hw+0x56/0x110 [mac80211] > [<fa3e9396>] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm] > [<f9b9d8ca>] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi] > [<f9b9d96f>] iwl_opmode_deregister+0x6f/0x90 [iwlwifi] > [<fa405179>] __exit_compat+0xd/0x19 [iwlmvm] > [<c10b8bf9>] SyS_delete_module+0x179/0x2b0 > [<c1613421>] sysenter_do_call+0x12/0x32 > > Fixes: 687da132234f ("mac80211: implement SMPS for AP") > Cc: <stable@xxxxxxxxxxxxxxx> [3.13] > Reported-by: Ilan Peer <ilan.peer@xxxxxxxxx> > Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> > Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx> > > diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index > 94b4acb5aabb..33acdca4a1df 100644 > --- a/net/mac80211/cfg.c > +++ b/net/mac80211/cfg.c > @@ -1090,8 +1090,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, > struct net_device *dev) > kfree(sdata->u.ap.next_beacon); > sdata->u.ap.next_beacon = NULL; > > - cancel_work_sync(&sdata->u.ap.request_smps_work); > - > /* turn off carrier for this interface and dependent VLANs */ > list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) > netif_carrier_off(vlan->dev); > @@ -1103,6 +1101,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, > struct net_device *dev) > kfree_rcu(old_beacon, rcu_head); > if (old_probe_resp) > kfree_rcu(old_probe_resp, rcu_head); > + sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; > > __sta_info_flush(sdata, true); > ieee80211_free_keys(sdata, true); > diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index > fab7b91923e0..70dd013de836 100644 > --- a/net/mac80211/ht.c > +++ b/net/mac80211/ht.c > @@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(struct > work_struct *work) > u.ap.request_smps_work); > > sdata_lock(sdata); > - __ieee80211_request_smps_ap(sdata, sdata- > >u.ap.driver_smps_mode); > + if (sdata_dereference(sdata->u.ap.beacon, sdata)) > + __ieee80211_request_smps_ap(sdata, > + sdata->u.ap.driver_smps_mode); > sdata_unlock(sdata); > } > > diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index > 3dfd20a453ab..ae2eb148a028 100644 > --- a/net/mac80211/iface.c > +++ b/net/mac80211/iface.c > @@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct > ieee80211_sub_if_data *sdata, > > ieee80211_roc_purge(local, sdata); > > - if (sdata->vif.type == NL80211_IFTYPE_STATION) > + switch (sdata->vif.type) { > + case NL80211_IFTYPE_STATION: > ieee80211_mgd_stop(sdata); > - > - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) > + break; > + case NL80211_IFTYPE_ADHOC: > ieee80211_ibss_stop(sdata); > - > + break; > + case NL80211_IFTYPE_AP: > + cancel_work_sync(&sdata->u.ap.request_smps_work); > + break; > + default: > + break; > + } > > /* > * Remove all stations associated with this interface. ��.n��������+%������w��{.n�����������ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f