From patchwork Thu Jan 23 12:28:16 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Emmanuel Grumbach X-Patchwork-Id: 3528321 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8ADB5C02DC for ; Thu, 23 Jan 2014 12:30:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 72A2A20173 for ; Thu, 23 Jan 2014 12:30:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 442E02017E for ; Thu, 23 Jan 2014 12:30:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752726AbaAWMac (ORCPT ); Thu, 23 Jan 2014 07:30:32 -0500 Received: from mga03.intel.com ([143.182.124.21]:37066 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752101AbaAWMaM (ORCPT ); Thu, 23 Jan 2014 07:30:12 -0500 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by azsmga101.ch.intel.com with ESMTP; 23 Jan 2014 04:29:58 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,706,1384329600"; d="scan'208";a="463466491" Received: from egrumbaclab.jer.intel.com ([10.12.217.137]) by fmsmga001.fm.intel.com with ESMTP; 23 Jan 2014 04:29:56 -0800 From: Emmanuel Grumbach To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Emmanuel Grumbach , Subject: [PATCH] mac80211: avoid deadlock revealed by lockdep Date: Thu, 23 Jan 2014 14:28:16 +0200 Message-Id: <1390480096-15150-1-git-send-email-emmanuel.grumbach@intel.com> X-Mailer: git-send-email 1.8.3.2 MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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: [] flush_work+0x0/0x90 but task is already holding lock: (&wdev->mtx){+.+.+.}, at: [] 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){+.+.+.}: [] lock_acquire+0x79/0xe0 [] mutex_lock_nested+0x4a/0x360 [] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211] [] process_one_work+0x198/0x450 [] worker_thread+0xf9/0x320 [] kthread+0x9f/0xb0 [] ret_from_kernel_thread+0x1b/0x28 -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}: [] __lock_acquire+0x183f/0x1910 [] lock_acquire+0x79/0xe0 [] flush_work+0x47/0x90 [] __cancel_work_timer+0x67/0xe0 [] cancel_work_sync+0xf/0x20 [] ieee80211_stop_ap+0x8c/0x340 [mac80211] [] cfg80211_stop_ap+0x8c/0x230 [cfg80211] [] cfg80211_leave+0x79/0x100 [cfg80211] [] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211] [] notifier_call_chain+0x59/0x130 [] __raw_notifier_call_chain+0x1e/0x30 [] raw_notifier_call_chain+0x1f/0x30 [] call_netdevice_notifiers_info+0x33/0x70 [] call_netdevice_notifiers+0x13/0x20 [] __dev_close_many+0x34/0xb0 [] dev_close_many+0x6e/0xc0 [] rollback_registered_many+0xa7/0x1f0 [] unregister_netdevice_many+0x14/0x60 [] ieee80211_remove_interfaces+0xe9/0x170 [mac80211] [] ieee80211_unregister_hw+0x56/0x110 [mac80211] [] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm] [] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi] [] iwl_opmode_deregister+0x6f/0x90 [iwlwifi] [] __exit_compat+0xd/0x19 [iwlmvm] [] SyS_delete_module+0x179/0x2b0 [] sysenter_do_call+0x12/0x32 Fixes: 687da132234f ("mac80211: implement SMPS for AP") Cc: [3.13] Reported-by: Ilan Peer Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- net/mac80211/cfg.c | 3 +-- net/mac80211/ht.c | 4 +++- net/mac80211/iface.c | 15 +++++++++++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 2279258..53917b7 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 fab7b91..70dd013 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 6af9bbf..4fa8a5f 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.