Message ID | 20210717204057.67495-6-martin.blumenstingl@googlemail.com |
---|---|
State | New |
Headers | show |
Series | rtw88: prepare locking for SDIO support | expand |
> -----Original Message----- > From: Martin Blumenstingl [mailto:martin.blumenstingl@googlemail.com] > Sent: Sunday, July 18, 2021 4:41 AM > To: linux-wireless@vger.kernel.org > Cc: tony0620emma@gmail.com; kvalo@codeaurora.org; johannes@sipsolutions.net; netdev@vger.kernel.org; > linux-kernel@vger.kernel.org; Neo Jou; Jernej Skrabec; Martin Blumenstingl > Subject: [PATCH RFC v1 5/7] rtw88: Configure the registers from rtw_bf_assoc() outside the RCU lock > > Upcoming SDIO support may sleep in the read/write handlers. Configure > the chip's BFEE configuration set from rtw_bf_assoc() outside the > rcu_read_lock section to prevent a "scheduling while atomic" issue. > > Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> > --- > drivers/net/wireless/realtek/rtw88/bf.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/wireless/realtek/rtw88/bf.c b/drivers/net/wireless/realtek/rtw88/bf.c > index aff70e4ae028..06034d5d6f6c 100644 > --- a/drivers/net/wireless/realtek/rtw88/bf.c > +++ b/drivers/net/wireless/realtek/rtw88/bf.c > @@ -39,6 +39,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, > struct ieee80211_sta_vht_cap *vht_cap; > struct ieee80211_sta_vht_cap *ic_vht_cap; > const u8 *bssid = bss_conf->bssid; > + bool config_bfee = false; > u32 sound_dim; > u8 i; > The rcu_read_lock() in this function is used to access ieee80211_find_sta() and protect 'sta'. A simple way is to shrink the critical section, like: rcu_read_lock(); sta = ieee80211_find_sta(vif, bssid); if (!sta) { rtw_warn(rtwdev, "failed to find station entry for bss %pM\n", bssid); rcu_read_unlock(); } vht_cap = &sta->vht_cap; rcu_read_unlock(); -- Ping-Ke
Hi Ping-Ke, On Mon, Jul 19, 2021 at 7:47 AM Pkshih <pkshih@realtek.com> wrote: [...] > The rcu_read_lock() in this function is used to access ieee80211_find_sta() and protect 'sta'. > A simple way is to shrink the critical section, like: > > rcu_read_lock(); > > sta = ieee80211_find_sta(vif, bssid); > if (!sta) { > rtw_warn(rtwdev, "failed to find station entry for bss %pM\n", > bssid); > rcu_read_unlock(); > } > > vht_cap = &sta->vht_cap; > > rcu_read_unlock(); I agree that reducing the amount of code under the lock will help my use-case as well in your code-example I am wondering if we should change struct ieee80211_sta_vht_cap *vht_cap; vht_cap = &sta->vht_cap; to struct ieee80211_sta_vht_cap vht_cap; vht_cap = sta->vht_cap; My thinking is that ieee80211_sta may be freed in parallel to this code running. If that cannot happen then your code will be fine. So I am hoping that you can also share your thoughts on this one. Thank you and best regards, Martin
> -----Original Message----- > From: Martin Blumenstingl [mailto:martin.blumenstingl@googlemail.com] > Sent: Monday, July 26, 2021 5:36 AM > To: Pkshih > Cc: linux-wireless@vger.kernel.org; tony0620emma@gmail.com; kvalo@codeaurora.org; > johannes@sipsolutions.net; netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Neo Jou; Jernej > Skrabec > Subject: Re: [PATCH RFC v1 5/7] rtw88: Configure the registers from rtw_bf_assoc() outside the RCU lock > > Hi Ping-Ke, > > On Mon, Jul 19, 2021 at 7:47 AM Pkshih <pkshih@realtek.com> wrote: > [...] > > The rcu_read_lock() in this function is used to access ieee80211_find_sta() and protect 'sta'. > > A simple way is to shrink the critical section, like: > > > > rcu_read_lock(); > > > > sta = ieee80211_find_sta(vif, bssid); > > if (!sta) { > > rtw_warn(rtwdev, "failed to find station entry for bss %pM\n", > > bssid); > > rcu_read_unlock(); > > } > > > > vht_cap = &sta->vht_cap; > > > > rcu_read_unlock(); > I agree that reducing the amount of code under the lock will help my > use-case as well > in your code-example I am wondering if we should change > struct ieee80211_sta_vht_cap *vht_cap; > vht_cap = &sta->vht_cap; > to > struct ieee80211_sta_vht_cap vht_cap; > vht_cap = sta->vht_cap; > > My thinking is that ieee80211_sta may be freed in parallel to this code running. > If that cannot happen then your code will be fine. > > So I am hoping that you can also share your thoughts on this one. > When we enter rtw_bf_assoc(), the mutex rtwdev->mutex is held; as well as rtw_sta_add()/rtw_sta_remove(). So, I think it cannot happen that ieee80211_sta was freed in parallel. -- Ping-Ke
diff --git a/drivers/net/wireless/realtek/rtw88/bf.c b/drivers/net/wireless/realtek/rtw88/bf.c index aff70e4ae028..06034d5d6f6c 100644 --- a/drivers/net/wireless/realtek/rtw88/bf.c +++ b/drivers/net/wireless/realtek/rtw88/bf.c @@ -39,6 +39,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta_vht_cap *vht_cap; struct ieee80211_sta_vht_cap *ic_vht_cap; const u8 *bssid = bss_conf->bssid; + bool config_bfee = false; u32 sound_dim; u8 i; @@ -70,7 +71,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, bfee->aid = bss_conf->aid; bfinfo->bfer_mu_cnt++; - rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true); + config_bfee = true; } else if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) && (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { if (bfinfo->bfer_su_cnt >= chip->bfer_su_max_num) { @@ -96,11 +97,14 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, } } - rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true); + config_bfee = true; } out_unlock: rcu_read_unlock(); + + if (config_bfee) + rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true); } void rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev,
Upcoming SDIO support may sleep in the read/write handlers. Configure the chip's BFEE configuration set from rtw_bf_assoc() outside the rcu_read_lock section to prevent a "scheduling while atomic" issue. Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> --- drivers/net/wireless/realtek/rtw88/bf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)