diff mbox

[6/6] mac80211: avoid mesh peer rate update warning

Message ID 1365444377-9959-6-git-send-email-thomas@cozybit.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Thomas Pedersen April 8, 2013, 6:06 p.m. UTC
Some drivers (like ath9k_htc) will take a mutex in
rate_control_rate_update(), so drop the sta lock before we
get there.

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>

Can go towards 3.9.
---
 net/mac80211/mesh_plink.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

Comments

Johannes Berg April 9, 2013, 9:38 a.m. UTC | #1
On Mon, 2013-04-08 at 11:06 -0700, Thomas Pedersen wrote:
> Some drivers (like ath9k_htc) will take a mutex in
> rate_control_rate_update(), so drop the sta lock before we
> get there.

That driver is broken then. rate_control_rate_update() can be called
from the RX path where this also isn't allowed.

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg April 9, 2013, 9:42 a.m. UTC | #2
On Tue, 2013-04-09 at 11:38 +0200, Johannes Berg wrote:
> On Mon, 2013-04-08 at 11:06 -0700, Thomas Pedersen wrote:
> > Some drivers (like ath9k_htc) will take a mutex in
> > rate_control_rate_update(), so drop the sta lock before we
> > get there.
> 
> That driver is broken then. rate_control_rate_update() can be called
> from the RX path where this also isn't allowed.

 * @sta_rc_update: Notifies the driver of changes to the bitrates that
can be
 *      used to transmit to the station. The changes are advertised with
bits
 *      from &enum ieee80211_rate_control_changed and the values are
reflected
 *      in the station data. This callback should only be used when the
driver
 *      uses hardware rate control (%IEEE80211_HW_HAS_RATE_CONTROL)
since
 *      otherwise the rate control algorithm is notified directly.
 *      Must be atomic.

(note last line)

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thomas Pedersen April 10, 2013, 5:38 p.m. UTC | #3
On Tue, Apr 9, 2013 at 2:42 AM, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2013-04-09 at 11:38 +0200, Johannes Berg wrote:
>> On Mon, 2013-04-08 at 11:06 -0700, Thomas Pedersen wrote:
>> > Some drivers (like ath9k_htc) will take a mutex in
>> > rate_control_rate_update(), so drop the sta lock before we
>> > get there.
>>
>> That driver is broken then. rate_control_rate_update() can be called
>> from the RX path where this also isn't allowed.
>
>  * @sta_rc_update: Notifies the driver of changes to the bitrates that
> can be
>  *      used to transmit to the station. The changes are advertised with
> bits
>  *      from &enum ieee80211_rate_control_changed and the values are
> reflected
>  *      in the station data. This callback should only be used when the
> driver
>  *      uses hardware rate control (%IEEE80211_HW_HAS_RATE_CONTROL)
> since
>  *      otherwise the rate control algorithm is notified directly.
>  *      Must be atomic.
>
> (note last line)

Ah alright. Thanks.
diff mbox

Patch

diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index cdd4183..ca284ee 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -379,8 +379,10 @@  static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 	sta->last_rx = jiffies;
 
 	/* rates and capabilities don't change during peering */
-	if (sta->plink_state == NL80211_PLINK_ESTAB)
-		goto out;
+	if (sta->plink_state == NL80211_PLINK_ESTAB) {
+		spin_unlock_bh(&sta->lock);
+		return;
+	}
 
 	if (sta->sta.supp_rates[band] != rates)
 		changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
@@ -398,13 +400,12 @@  static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 			changed |= IEEE80211_RC_BW_CHANGED;
 		sta->sta.bandwidth = IEEE80211_STA_RX_BW_20;
 	}
+	spin_unlock_bh(&sta->lock);
 
 	if (insert)
 		rate_control_rate_init(sta);
 	else
 		rate_control_rate_update(local, sband, sta, changed);
-out:
-	spin_unlock_bh(&sta->lock);
 }
 
 static struct sta_info *