diff mbox

[v2,01/10] rtlwifi: Use mutex to replace spin_lock to protect IPS and LPS

Message ID 20180111070932.9929-2-pkshih@realtek.com (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show

Commit Message

Ping-Ke Shih Jan. 11, 2018, 7:09 a.m. UTC
From: Ping-Ke Shih <pkshih@realtek.com>

Enter/leavel IPS and LPS are large critical section, and they can't use
sleep function because running in atomic-context, which own a spin_lock.
In commit ba9f93f82aba ("rtlwifi: Fix enter/exit power_save"), it moves
LPS functions to thread-context, so this commit can simply change LPS's
spin lock to mutex.
Considering IPS functions, rtl_ips_nic_on() may be called by TX tasklet
(softirq-context) that check whether packet is auth frame. Fortunately,
current mac80211 will ask driver to leave IPS using op_config with
changed flag IEEE80211_CONF_CHANGE_IDLE, before issuing auth frame, so
IPS functions can run in thread-context and use mutex to protect critical
section, too.
Also, this commit removes some useless spin locks.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtlwifi/base.c |  6 ++----
 drivers/net/wireless/realtek/rtlwifi/ps.c   | 24 ++++++++++--------------
 drivers/net/wireless/realtek/rtlwifi/usb.c  |  1 -
 drivers/net/wireless/realtek/rtlwifi/wifi.h | 10 ++--------
 4 files changed, 14 insertions(+), 27 deletions(-)

Comments

Larry Finger Jan. 12, 2018, 7:36 p.m. UTC | #1
On 01/11/2018 01:09 AM, pkshih@realtek.com wrote:
> From: Ping-Ke Shih <pkshih@realtek.com>
> 
> Enter/leavel IPS and LPS are large critical section, and they can't use
> sleep function because running in atomic-context, which own a spin_lock.
> In commit ba9f93f82aba ("rtlwifi: Fix enter/exit power_save"), it moves
> LPS functions to thread-context, so this commit can simply change LPS's
> spin lock to mutex.
> Considering IPS functions, rtl_ips_nic_on() may be called by TX tasklet
> (softirq-context) that check whether packet is auth frame. Fortunately,
> current mac80211 will ask driver to leave IPS using op_config with
> changed flag IEEE80211_CONF_CHANGE_IDLE, before issuing auth frame, so
> IPS functions can run in thread-context and use mutex to protect critical
> section, too.
> Also, this commit removes some useless spin locks.
> 
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>

Acked-by: Larry Finger <Larry.Finger@lwfinger.net>


> ---
>   drivers/net/wireless/realtek/rtlwifi/base.c |  6 ++----
>   drivers/net/wireless/realtek/rtlwifi/ps.c   | 24 ++++++++++--------------
>   drivers/net/wireless/realtek/rtlwifi/usb.c  |  1 -
>   drivers/net/wireless/realtek/rtlwifi/wifi.h | 10 ++--------
>   4 files changed, 14 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
> index 0ba9c0cc95e1..89ec318598ea 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/base.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/base.c
> @@ -551,7 +551,8 @@ int rtl_init_core(struct ieee80211_hw *hw)
>   
>   	/* <4> locks */
>   	mutex_init(&rtlpriv->locks.conf_mutex);
> -	spin_lock_init(&rtlpriv->locks.ips_lock);
> +	mutex_init(&rtlpriv->locks.ips_mutex);
> +	mutex_init(&rtlpriv->locks.lps_mutex);
>   	spin_lock_init(&rtlpriv->locks.irq_th_lock);
>   	spin_lock_init(&rtlpriv->locks.h2c_lock);
>   	spin_lock_init(&rtlpriv->locks.rf_ps_lock);
> @@ -561,9 +562,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
>   	spin_lock_init(&rtlpriv->locks.c2hcmd_lock);
>   	spin_lock_init(&rtlpriv->locks.scan_list_lock);
>   	spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock);
> -	spin_lock_init(&rtlpriv->locks.check_sendpkt_lock);
>   	spin_lock_init(&rtlpriv->locks.fw_ps_lock);
> -	spin_lock_init(&rtlpriv->locks.lps_lock);
>   	spin_lock_init(&rtlpriv->locks.iqk_lock);
>   	/* <5> init list */
>   	INIT_LIST_HEAD(&rtlpriv->entry_list);
> @@ -1229,7 +1228,6 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
>   	}
>   	if (ieee80211_is_auth(fc)) {
>   		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
> -		rtl_ips_nic_on(hw);
>   
>   		mac->link_state = MAC80211_LINKING;
>   		/* Dul mac */
> diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c
> index 24c87fae5382..6a4008845f49 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/ps.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
> @@ -289,7 +289,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
>   
>   	cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq);
>   
> -	spin_lock(&rtlpriv->locks.ips_lock);
> +	mutex_lock(&rtlpriv->locks.ips_mutex);
>   	if (ppsc->inactiveps) {
>   		rtstate = ppsc->rfpwr_state;
>   
> @@ -306,7 +306,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
>   									ppsc->inactive_pwrstate);
>   		}
>   	}
> -	spin_unlock(&rtlpriv->locks.ips_lock);
> +	mutex_unlock(&rtlpriv->locks.ips_mutex);
>   }
>   EXPORT_SYMBOL_GPL(rtl_ips_nic_on);
>   
> @@ -415,7 +415,6 @@ static void rtl_lps_enter_core(struct ieee80211_hw *hw)
>   	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
>   	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
>   	struct rtl_priv *rtlpriv = rtl_priv(hw);
> -	unsigned long flag;
>   
>   	if (!ppsc->fwctrl_lps)
>   		return;
> @@ -436,7 +435,7 @@ static void rtl_lps_enter_core(struct ieee80211_hw *hw)
>   	if (mac->link_state != MAC80211_LINKED)
>   		return;
>   
> -	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
> +	mutex_lock(&rtlpriv->locks.lps_mutex);
>   
>   	/* Don't need to check (ppsc->dot11_psmode == EACTIVE), because
>   	 * bt_ccoexist may ask to enter lps.
> @@ -446,7 +445,7 @@ static void rtl_lps_enter_core(struct ieee80211_hw *hw)
>   		 "Enter 802.11 power save mode...\n");
>   	rtl_lps_set_psmode(hw, EAUTOPS);
>   
> -	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
> +	mutex_unlock(&rtlpriv->locks.lps_mutex);
>   }
>   
>   /* Interrupt safe routine to leave the leisure power save mode.*/
> @@ -455,9 +454,8 @@ static void rtl_lps_leave_core(struct ieee80211_hw *hw)
>   	struct rtl_priv *rtlpriv = rtl_priv(hw);
>   	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
>   	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
> -	unsigned long flag;
>   
> -	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
> +	mutex_lock(&rtlpriv->locks.lps_mutex);
>   
>   	if (ppsc->fwctrl_lps) {
>   		if (ppsc->dot11_psmode != EACTIVE) {
> @@ -478,7 +476,7 @@ static void rtl_lps_leave_core(struct ieee80211_hw *hw)
>   			rtl_lps_set_psmode(hw, EACTIVE);
>   		}
>   	}
> -	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
> +	mutex_unlock(&rtlpriv->locks.lps_mutex);
>   }
>   
>   /* For sw LPS*/
> @@ -568,7 +566,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
>   	struct rtl_priv *rtlpriv = rtl_priv(hw);
>   	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
>   	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
> -	unsigned long flag;
>   
>   	if (!rtlpriv->psc.swctrl_lps)
>   		return;
> @@ -581,9 +578,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
>   		RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
>   	}
>   
> -	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
> +	mutex_lock(&rtlpriv->locks.lps_mutex);
>   	rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
> -	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
> +	mutex_unlock(&rtlpriv->locks.lps_mutex);
>   }
>   
>   void rtl_swlps_rfon_wq_callback(void *data)
> @@ -600,7 +597,6 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
>   	struct rtl_priv *rtlpriv = rtl_priv(hw);
>   	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
>   	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
> -	unsigned long flag;
>   	u8 sleep_intv;
>   
>   	if (!rtlpriv->psc.sw_ps_enabled)
> @@ -624,9 +620,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
>   	}
>   	spin_unlock(&rtlpriv->locks.rf_ps_lock);
>   
> -	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
> +	mutex_lock(&rtlpriv->locks.lps_mutex);
>   	rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
> -	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
> +	mutex_unlock(&rtlpriv->locks.lps_mutex);
>   
>   	if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
>   	    !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
> diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
> index 39b033b3b53a..ce3103bb8ebb 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/usb.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
> @@ -962,7 +962,6 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw,
>   	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
>   	if (ieee80211_is_auth(fc)) {
>   		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
> -		rtl_ips_nic_on(hw);
>   	}
>   
>   	if (rtlpriv->psc.sw_ps_enabled) {
> diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
> index 0b1c54381a2f..941694060f48 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
> +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
> @@ -2325,17 +2325,14 @@ struct rtl_hal_cfg {
>   struct rtl_locks {
>   	/* mutex */
>   	struct mutex conf_mutex;
> -	struct mutex ps_mutex;
> +	struct mutex ips_mutex;	/* mutex for enter/leave IPS */
> +	struct mutex lps_mutex;	/* mutex for enter/leave LPS */
>   
>   	/*spin lock */
> -	spinlock_t ips_lock;
>   	spinlock_t irq_th_lock;
> -	spinlock_t irq_pci_lock;
> -	spinlock_t tx_lock;
>   	spinlock_t h2c_lock;
>   	spinlock_t rf_ps_lock;
>   	spinlock_t rf_lock;
> -	spinlock_t lps_lock;
>   	spinlock_t waitq_lock;
>   	spinlock_t entry_list_lock;
>   	spinlock_t usb_lock;
> @@ -2348,9 +2345,6 @@ struct rtl_locks {
>   	/*Dual mac*/
>   	spinlock_t cck_and_rw_pagea_lock;
>   
> -	/*Easy concurrent*/
> -	spinlock_t check_sendpkt_lock;
> -
>   	spinlock_t iqk_lock;
>   };
>   
>
diff mbox

Patch

diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 0ba9c0cc95e1..89ec318598ea 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -551,7 +551,8 @@  int rtl_init_core(struct ieee80211_hw *hw)
 
 	/* <4> locks */
 	mutex_init(&rtlpriv->locks.conf_mutex);
-	spin_lock_init(&rtlpriv->locks.ips_lock);
+	mutex_init(&rtlpriv->locks.ips_mutex);
+	mutex_init(&rtlpriv->locks.lps_mutex);
 	spin_lock_init(&rtlpriv->locks.irq_th_lock);
 	spin_lock_init(&rtlpriv->locks.h2c_lock);
 	spin_lock_init(&rtlpriv->locks.rf_ps_lock);
@@ -561,9 +562,7 @@  int rtl_init_core(struct ieee80211_hw *hw)
 	spin_lock_init(&rtlpriv->locks.c2hcmd_lock);
 	spin_lock_init(&rtlpriv->locks.scan_list_lock);
 	spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock);
-	spin_lock_init(&rtlpriv->locks.check_sendpkt_lock);
 	spin_lock_init(&rtlpriv->locks.fw_ps_lock);
-	spin_lock_init(&rtlpriv->locks.lps_lock);
 	spin_lock_init(&rtlpriv->locks.iqk_lock);
 	/* <5> init list */
 	INIT_LIST_HEAD(&rtlpriv->entry_list);
@@ -1229,7 +1228,6 @@  bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
 	}
 	if (ieee80211_is_auth(fc)) {
 		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
-		rtl_ips_nic_on(hw);
 
 		mac->link_state = MAC80211_LINKING;
 		/* Dul mac */
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c
index 24c87fae5382..6a4008845f49 100644
--- a/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -289,7 +289,7 @@  void rtl_ips_nic_on(struct ieee80211_hw *hw)
 
 	cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq);
 
-	spin_lock(&rtlpriv->locks.ips_lock);
+	mutex_lock(&rtlpriv->locks.ips_mutex);
 	if (ppsc->inactiveps) {
 		rtstate = ppsc->rfpwr_state;
 
@@ -306,7 +306,7 @@  void rtl_ips_nic_on(struct ieee80211_hw *hw)
 									ppsc->inactive_pwrstate);
 		}
 	}
-	spin_unlock(&rtlpriv->locks.ips_lock);
+	mutex_unlock(&rtlpriv->locks.ips_mutex);
 }
 EXPORT_SYMBOL_GPL(rtl_ips_nic_on);
 
@@ -415,7 +415,6 @@  static void rtl_lps_enter_core(struct ieee80211_hw *hw)
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	unsigned long flag;
 
 	if (!ppsc->fwctrl_lps)
 		return;
@@ -436,7 +435,7 @@  static void rtl_lps_enter_core(struct ieee80211_hw *hw)
 	if (mac->link_state != MAC80211_LINKED)
 		return;
 
-	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+	mutex_lock(&rtlpriv->locks.lps_mutex);
 
 	/* Don't need to check (ppsc->dot11_psmode == EACTIVE), because
 	 * bt_ccoexist may ask to enter lps.
@@ -446,7 +445,7 @@  static void rtl_lps_enter_core(struct ieee80211_hw *hw)
 		 "Enter 802.11 power save mode...\n");
 	rtl_lps_set_psmode(hw, EAUTOPS);
 
-	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+	mutex_unlock(&rtlpriv->locks.lps_mutex);
 }
 
 /* Interrupt safe routine to leave the leisure power save mode.*/
@@ -455,9 +454,8 @@  static void rtl_lps_leave_core(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	unsigned long flag;
 
-	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+	mutex_lock(&rtlpriv->locks.lps_mutex);
 
 	if (ppsc->fwctrl_lps) {
 		if (ppsc->dot11_psmode != EACTIVE) {
@@ -478,7 +476,7 @@  static void rtl_lps_leave_core(struct ieee80211_hw *hw)
 			rtl_lps_set_psmode(hw, EACTIVE);
 		}
 	}
-	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+	mutex_unlock(&rtlpriv->locks.lps_mutex);
 }
 
 /* For sw LPS*/
@@ -568,7 +566,6 @@  void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	unsigned long flag;
 
 	if (!rtlpriv->psc.swctrl_lps)
 		return;
@@ -581,9 +578,9 @@  void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
 		RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
 	}
 
-	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+	mutex_lock(&rtlpriv->locks.lps_mutex);
 	rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
-	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+	mutex_unlock(&rtlpriv->locks.lps_mutex);
 }
 
 void rtl_swlps_rfon_wq_callback(void *data)
@@ -600,7 +597,6 @@  void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	unsigned long flag;
 	u8 sleep_intv;
 
 	if (!rtlpriv->psc.sw_ps_enabled)
@@ -624,9 +620,9 @@  void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
 	}
 	spin_unlock(&rtlpriv->locks.rf_ps_lock);
 
-	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+	mutex_lock(&rtlpriv->locks.lps_mutex);
 	rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
-	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+	mutex_unlock(&rtlpriv->locks.lps_mutex);
 
 	if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
 	    !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 39b033b3b53a..ce3103bb8ebb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -962,7 +962,6 @@  static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw,
 	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
 	if (ieee80211_is_auth(fc)) {
 		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
-		rtl_ips_nic_on(hw);
 	}
 
 	if (rtlpriv->psc.sw_ps_enabled) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 0b1c54381a2f..941694060f48 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -2325,17 +2325,14 @@  struct rtl_hal_cfg {
 struct rtl_locks {
 	/* mutex */
 	struct mutex conf_mutex;
-	struct mutex ps_mutex;
+	struct mutex ips_mutex;	/* mutex for enter/leave IPS */
+	struct mutex lps_mutex;	/* mutex for enter/leave LPS */
 
 	/*spin lock */
-	spinlock_t ips_lock;
 	spinlock_t irq_th_lock;
-	spinlock_t irq_pci_lock;
-	spinlock_t tx_lock;
 	spinlock_t h2c_lock;
 	spinlock_t rf_ps_lock;
 	spinlock_t rf_lock;
-	spinlock_t lps_lock;
 	spinlock_t waitq_lock;
 	spinlock_t entry_list_lock;
 	spinlock_t usb_lock;
@@ -2348,9 +2345,6 @@  struct rtl_locks {
 	/*Dual mac*/
 	spinlock_t cck_and_rw_pagea_lock;
 
-	/*Easy concurrent*/
-	spinlock_t check_sendpkt_lock;
-
 	spinlock_t iqk_lock;
 };