From patchwork Tue Feb 26 00:13:21 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Larry Finger X-Patchwork-Id: 2183521 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 5256F3FCA4 for ; Tue, 26 Feb 2013 00:16:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759993Ab3BZAQj (ORCPT ); Mon, 25 Feb 2013 19:16:39 -0500 Received: from mail-oa0-f53.google.com ([209.85.219.53]:42405 "EHLO mail-oa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759878Ab3BZAOS (ORCPT ); Mon, 25 Feb 2013 19:14:18 -0500 Received: by mail-oa0-f53.google.com with SMTP id m1so4087358oag.40 for ; Mon, 25 Feb 2013 16:14:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=sS/AgcySiAfaxfqu3LIxFnz95JUXoTRKpeqMt9j3DN8=; b=pmROxGgQ+GJQrMLZ9J3uTRKmxnmqsPHbm1a9paIKk2QzUCWQhNSOoQEJTWTepBHZEM j9d0YD+IU0ljVmzmEKWMcoOAZgKuELAskhhMuYhY3K4saN6GgaTYtRymSsHzZr42sOI/ pZYkOwC1Xck4vyDSsLUeAmgCpGhKVW2XeM+74vI4DgMNYWdV0o9l8b3nJdb9kh4HStxq MnK4hgUNnen8TxmvWZ0PStHiSm1pmefhMqTgDlotKlZDRehyHYp/WWeNDIhJOaaZoPBy EZSwvZx70TTWJE+Z8miB4Br06T83fySUSlKR3eddy6yvgyTkPrwv8OdJ49bo88qzGQbJ WOmw== X-Received: by 10.60.10.34 with SMTP id f2mr168577oeb.104.1361837656586; Mon, 25 Feb 2013 16:14:16 -0800 (PST) Received: from linux-2liw.lan (CPE-75-81-36-228.kc.res.rr.com. [75.81.36.228]) by mx.google.com with ESMTPS id d10sm8177318oeh.7.2013.02.25.16.14.14 (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 25 Feb 2013 16:14:16 -0800 (PST) From: Larry Finger To: linville@tuxdriver.com Cc: linux-wireless@vger.kernel.org, Larry Finger , netdev@vger.kernel.org, jcheung@suse.com, machen@suse.com, mmarek@suse.cz Subject: [RFC/RFT 09/27] rtlwifi: Rework rtl_lps_leave() and rtl_lps_enter() to use work queue Date: Mon, 25 Feb 2013 18:13:21 -0600 Message-Id: <1361837619-2985-10-git-send-email-Larry.Finger@lwfinger.net> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1361837619-2985-1-git-send-email-Larry.Finger@lwfinger.net> References: <1361837619-2985-1-git-send-email-Larry.Finger@lwfinger.net> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org In commit a5ffbe0, some of the calls to rtl_lps_leave() were switched to be called from a work queue to avoid a scheduling while atomic bug. This patch converts the remaining calls to use the work queue. In addition, the call to rtl_lps_enter() is also switched to the work queue. None of these newly converted calls had triggered the bug (yet), but this change make all of them fit a single pattern. Signed-off-by: Larry Finger Cc: jcheung@suse.com Cc: machen@suse.com Cc: mmarek@suse.cz --- drivers/net/wireless/rtlwifi/base.c | 19 +++++++++---------- drivers/net/wireless/rtlwifi/core.c | 9 ++++++--- drivers/net/wireless/rtlwifi/pci.c | 26 +++++++++++++++++--------- drivers/net/wireless/rtlwifi/wifi.h | 3 ++- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index acea8e8..e5b14b8 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -1086,8 +1086,9 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) is_tx ? "Tx" : "Rx"); if (is_tx) { + rtlpriv->enter_ps = false; schedule_work(&rtlpriv-> - works.lps_leave_work); + works.lps_change_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } @@ -1097,7 +1098,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) } } else if (ETH_P_ARP == ether_type) { if (is_tx) { - schedule_work(&rtlpriv->works.lps_leave_work); + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } @@ -1107,7 +1109,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); if (is_tx) { - schedule_work(&rtlpriv->works.lps_leave_work); + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } @@ -1316,7 +1319,6 @@ void rtl_watchdog_wq_callback(void *data) u32 aver_tx_cnt_inperiod = 0; u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; - bool enter_ps = false; if (is_hal_stop(rtlhal)) return; @@ -1398,15 +1400,12 @@ void rtl_watchdog_wq_callback(void *data) if (((rtlpriv->link_info.num_rx_inperiod + rtlpriv->link_info.num_tx_inperiod) > 8) || (rtlpriv->link_info.num_rx_inperiod > 2)) - enter_ps = false; + rtlpriv->enter_ps = true; else - enter_ps = true; + rtlpriv->enter_ps = false; /* LeisurePS only work in infra mode. */ - if (enter_ps) - rtl_lps_enter(hw); - else - schedule_work(&rtlpriv->works.lps_leave_work); + schedule_work(&rtlpriv->works.lps_change_work); } rtlpriv->link_info.num_rx_inperiod = 0; diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 470a67d..3706182 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -742,8 +742,10 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "BSS_CHANGED_ASSOC\n"); } else { - if (mac->link_state == MAC80211_LINKED) - schedule_work(&rtlpriv->works.lps_leave_work); + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + } if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); @@ -1018,7 +1020,8 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) rtlpriv->cfg->ops->chk_switch_dmdp(hw); } if (mac->link_state == MAC80211_LINKED) { - schedule_work(&rtlpriv->works.lps_leave_work); + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); mac->link_state = MAC80211_LINKED_SCANNING; } else { rtl_ips_nic_on(hw); diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 70c2497..3bd98f7 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -655,7 +655,8 @@ tx_status_ok: if (((rtlpriv->link_info.num_rx_inperiod + rtlpriv->link_info.num_tx_inperiod) > 8) || (rtlpriv->link_info.num_rx_inperiod > 2)) { - schedule_work(&rtlpriv->works.lps_leave_work); + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); } } @@ -837,8 +838,10 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) if (((rtlpriv->link_info.num_rx_inperiod + rtlpriv->link_info.num_tx_inperiod) > 8) || - (rtlpriv->link_info.num_rx_inperiod > 2)) - schedule_work(&rtlpriv->works.lps_leave_work); + (rtlpriv->link_info.num_rx_inperiod > 2)) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + } _rtl_pci_init_one_rxdesc(hw, pdesc, rxring_idx, rtlpci->rx_ring[rxring_idx].idx); @@ -1029,13 +1032,17 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) return; } -static void rtl_lps_leave_work_callback(struct work_struct *work) +static void rtl_lps_change_work_callback(struct work_struct *work) { struct rtl_works *rtlworks = - container_of(work, struct rtl_works, lps_leave_work); + container_of(work, struct rtl_works, lps_change_work); struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); - rtl_lps_leave(hw); + if (rtlpriv->enter_ps) + rtl_lps_enter(hw); + else + rtl_lps_leave(hw); } static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) @@ -1099,7 +1106,8 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, (unsigned long)hw); - INIT_WORK(&rtlpriv->works.lps_leave_work, rtl_lps_leave_work_callback); + INIT_WORK(&rtlpriv->works.lps_change_work, + rtl_lps_change_work_callback); } static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, @@ -1530,7 +1538,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw) synchronize_irq(rtlpci->pdev->irq); tasklet_kill(&rtlpriv->works.irq_tasklet); - cancel_work_sync(&rtlpriv->works.lps_leave_work); + cancel_work_sync(&rtlpriv->works.lps_change_work); flush_workqueue(rtlpriv->works.rtl_wq); destroy_workqueue(rtlpriv->works.rtl_wq); @@ -1605,7 +1613,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) set_hal_stop(rtlhal); rtlpriv->cfg->ops->disable_interrupt(hw); - cancel_work_sync(&rtlpriv->works.lps_leave_work); + cancel_work_sync(&rtlpriv->works.lps_change_work); spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); while (ppsc->rfchange_inprogress) { diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index a57b876..f6825c1 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1794,7 +1794,7 @@ struct rtl_works { struct delayed_work ps_rfon_wq; struct delayed_work fwevt_wq; - struct work_struct lps_leave_work; + struct work_struct lps_change_work; }; struct rtl_debug { @@ -1964,6 +1964,7 @@ struct rtl_priv { bool bt_operation_on; }; }; + bool enter_ps; /* true when entering PS */ /*This must be the last item so that it points to the data allocated