* [PATCH 7/8] ath9k: announce that ath9k supports 5/10 MHz
From: a @ 2013-05-09 18:10 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
drivers/net/wireless/ath/ath9k/init.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 0959729..30c3ddf 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -794,6 +794,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+ hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
#ifdef CONFIG_PM_SLEEP
--
1.7.10.4
^ permalink raw reply related
* [PATCH 4/8] mac80211: fix timing for 5 MHz and 10 MHz channels
From: a @ 2013-05-09 18:10 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
according to IEEE 802.11-2012 section 18, various timings change
when using 5 MHz and 10 MHz. Reflect this by using a "divisor" when
calculating durations.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
net/mac80211/ieee80211_i.h | 42 ++++++++++++++++++++++++++++++++++-
net/mac80211/rc80211_minstrel.c | 14 +++++++-----
net/mac80211/rc80211_minstrel_ht.c | 8 ++++---
net/mac80211/tx.c | 10 ++++++---
net/mac80211/util.c | 43 +++++++++++++++++++++++++-----------
5 files changed, 92 insertions(+), 25 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 1079c27..e9d3da9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -792,6 +792,45 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
return band;
}
+static inline int
+ieee80211_vif_get_divisor(struct ieee80211_vif *vif)
+{
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ int divisor = 1;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(vif->chanctx_conf);
+ if (chanctx_conf) {
+ switch (chanctx_conf->def.width) {
+ case NL80211_CHAN_WIDTH_5:
+ divisor = 4;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ divisor = 2;
+ break;
+ default:
+ divisor = 1;
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+ return divisor;
+}
+
+static inline int
+ieee80211_hw_get_divisor(struct ieee80211_hw *hw)
+{
+ switch (hw->conf.chandef.width) {
+ case NL80211_CHAN_WIDTH_5:
+ return 4;
+ case NL80211_CHAN_WIDTH_10:
+ return 2;
+ default:
+ return 1;
+ }
+}
+
enum sdata_queue_type {
IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0,
IEEE80211_SDATA_QUEUE_AGG_START = 1,
@@ -1448,7 +1487,8 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
enum nl80211_iftype type);
int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
- int rate, int erp, int short_preamble);
+ int rate, int erp, int short_preamble,
+ int divisor);
void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
struct ieee80211_hdr *hdr, const u8 *tsc,
gfp_t gfp);
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index ac7ef54..3fe134a 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -382,14 +382,17 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
static void
calc_rate_durations(enum ieee80211_band band,
struct minstrel_rate *d,
- struct ieee80211_rate *rate)
+ struct ieee80211_rate *rate,
+ struct minstrel_priv *mp)
{
int erp = !!(rate->flags & IEEE80211_RATE_ERP_G);
d->perfect_tx_time = ieee80211_frame_duration(band, 1200,
- rate->bitrate, erp, 1);
+ rate->bitrate, erp, 1,
+ ieee80211_hw_get_divisor(mp->hw));
d->ack_time = ieee80211_frame_duration(band, 10,
- rate->bitrate, erp, 1);
+ rate->bitrate, erp, 1,
+ ieee80211_hw_get_divisor(mp->hw));
}
static void
@@ -430,7 +433,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
ctl_rate = &sband->bitrates[mi->lowest_rix];
mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10,
ctl_rate->bitrate,
- !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1);
+ !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1,
+ ieee80211_hw_get_divisor(mp->hw));
memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate));
mi->max_prob_rate = 0;
@@ -448,7 +452,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
mr->rix = i;
mr->bitrate = sband->bitrates[i].bitrate / 5;
- calc_rate_durations(sband->band, mr, &sband->bitrates[i]);
+ calc_rate_durations(sband->band, mr, &sband->bitrates[i], mp);
/* calculate maximum number of retransmissions before
* fallback (based on maximum segment size) */
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 5b2d301..f05eeff 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -844,7 +844,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
u16 sta_cap = sta->ht_cap.cap;
int n_supported = 0;
- int ack_dur;
+ int ack_dur, divisor;
int stbc;
int i;
@@ -861,8 +861,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
mi->sta = sta;
mi->stats_update = jiffies;
- ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1);
- mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1) + ack_dur;
+ divisor = ieee80211_hw_get_divisor(mp->hw);
+ ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, divisor);
+ mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1,
+ divisor) + ack_dur;
mi->overhead_rtscts = mi->overhead + 2 * ack_dur;
mi->avg_ampdu_len = MINSTREL_FRAC(1, 1);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4a5fbf8..4bed9fd 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -40,7 +40,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
struct sk_buff *skb, int group_addr,
int next_frag_len)
{
- int rate, mrate, erp, dur, i;
+ int rate, mrate, erp, dur, i, divisor;
struct ieee80211_rate *txrate;
struct ieee80211_local *local = tx->local;
struct ieee80211_supported_band *sband;
@@ -153,6 +153,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
rate = mrate;
}
+ divisor = ieee80211_vif_get_divisor(&tx->sdata->vif);
+
/* Don't calculate ACKs for QoS Frames with NoAck Policy set */
if (ieee80211_is_data_qos(hdr->frame_control) &&
*(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
@@ -162,7 +164,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
* (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
* to closest integer */
dur = ieee80211_frame_duration(sband->band, 10, rate, erp,
- tx->sdata->vif.bss_conf.use_short_preamble);
+ tx->sdata->vif.bss_conf.use_short_preamble,
+ divisor);
if (next_frag_len) {
/* Frame is fragmented: duration increases with time needed to
@@ -171,7 +174,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
/* next fragment */
dur += ieee80211_frame_duration(sband->band, next_frag_len,
txrate->bitrate, erp,
- tx->sdata->vif.bss_conf.use_short_preamble);
+ tx->sdata->vif.bss_conf.use_short_preamble,
+ divisor);
}
return cpu_to_le16(dur);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 27e0715..ad03800 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -107,7 +107,8 @@ void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
}
int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
- int rate, int erp, int short_preamble)
+ int rate, int erp, int short_preamble,
+ int divisor)
{
int dur;
@@ -118,6 +119,13 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
*
* rate is in 100 kbps, so divident is multiplied by 10 in the
* DIV_ROUND_UP() operations.
+ *
+ * divisor may be 4 for 5 MHz channels or 2 for 1 MHz channels, and
+ * is assumed to be 1 otherwise. For 5 and 10 MHz channels, the
+ * according 20 MHz rates are assumed. For example, a datarate of
+ * 1.5mbps in a 5 MHz channel would be reported as rate == 60,
+ * because the corresponding datarate in 20mbps with the same
+ * modulation would be 6 mbps.
*/
if (band == IEEE80211_BAND_5GHZ || erp) {
@@ -130,15 +138,21 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
* TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
*
* T_SYM = 4 usec
- * 802.11a - 17.5.2: aSIFSTime = 16 usec
+ * 802.11a - 18.5.2: aSIFSTime = 16 usec
* 802.11g - 19.8.4: aSIFSTime = 10 usec +
* signal ext = 6 usec
*/
dur = 16; /* SIFS + signal ext */
- dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */
- dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */
+ dur += 16; /* IEEE 802.11-2012 18.3.2.4: T_PREAMBLE = 16 usec */
+ dur += 4; /* IEEE 802.11-2012 18.3.2.4: T_SIGNAL = 4 usec */
dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
4 * rate); /* T_SYM x N_SYM */
+
+ /* IEEE 802.11-2012 18.3.2.4: all values above are:
+ * * times 4 for 5 MHz
+ * * times 2 for 10 MHz
+ */
+ dur *= divisor;
} else {
/*
* 802.11b or 802.11g with 802.11b compatibility:
@@ -168,7 +182,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
{
struct ieee80211_sub_if_data *sdata;
u16 dur;
- int erp;
+ int erp, divisor = 1;
bool short_preamble = false;
erp = 0;
@@ -177,10 +191,11 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
short_preamble = sdata->vif.bss_conf.use_short_preamble;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
+ divisor = ieee80211_vif_get_divisor(vif);
}
dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp,
- short_preamble);
+ short_preamble, divisor);
return cpu_to_le16(dur);
}
@@ -194,7 +209,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
struct ieee80211_rate *rate;
struct ieee80211_sub_if_data *sdata;
bool short_preamble;
- int erp;
+ int erp, divisor = 1;
u16 dur;
struct ieee80211_supported_band *sband;
@@ -210,17 +225,18 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
short_preamble = sdata->vif.bss_conf.use_short_preamble;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
+ divisor = ieee80211_vif_get_divisor(vif);
}
/* CTS duration */
dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate,
- erp, short_preamble);
+ erp, short_preamble, divisor);
/* Data frame duration */
dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate,
- erp, short_preamble);
+ erp, short_preamble, divisor);
/* ACK duration */
dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate,
- erp, short_preamble);
+ erp, short_preamble, divisor);
return cpu_to_le16(dur);
}
@@ -235,7 +251,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
struct ieee80211_rate *rate;
struct ieee80211_sub_if_data *sdata;
bool short_preamble;
- int erp;
+ int erp, divisor = 1;
u16 dur;
struct ieee80211_supported_band *sband;
@@ -250,15 +266,16 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
short_preamble = sdata->vif.bss_conf.use_short_preamble;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
+ divisor = ieee80211_vif_get_divisor(vif);
}
/* Data frame duration */
dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate,
- erp, short_preamble);
+ erp, short_preamble, divisor);
if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) {
/* ACK duration */
dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate,
- erp, short_preamble);
+ erp, short_preamble, divisor);
}
return cpu_to_le16(dur);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/8] mac80211: change IBSS channel state to chandef
From: a @ 2013-05-09 18:10 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
This should make some parts cleaner and is also required for handling
5/10 MHz properly.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
net/mac80211/ibss.c | 22 +++++++++++-----------
net/mac80211/ieee80211_i.h | 3 +--
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 4e1fb81..ef07b65 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -81,7 +81,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
- cfg80211_chandef_create(&chandef, chan, ifibss->channel_type);
+ chandef = ifibss->chandef;
if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
chandef.width = NL80211_CHAN_WIDTH_20;
chandef.center_freq1 = chan->center_freq;
@@ -514,7 +514,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
set_sta_flag(sta, WLAN_STA_WME);
if (sta && elems->ht_operation && elems->ht_cap_elem &&
- sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) {
+ sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
+ sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_5 &&
+ sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_10) {
/* we both use HT */
struct ieee80211_ht_cap htcap_ie;
struct cfg80211_chan_def chandef;
@@ -529,8 +531,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
* fall back to HT20 if we don't use or use
* the other extension channel
*/
- if (cfg80211_get_chandef_type(&chandef) !=
- sdata->u.ibss.channel_type)
+ if (chandef.center_freq1 !=
+ sdata->u.ibss.chandef.center_freq1)
htcap_ie.cap_info &=
cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40);
@@ -569,7 +571,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
/* different channel */
if (sdata->u.ibss.fixed_channel &&
- sdata->u.ibss.channel != cbss->channel)
+ sdata->u.ibss.chandef.chan != cbss->channel)
goto put_bss;
/* different SSID */
@@ -757,7 +759,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
sdata->drop_unencrypted = 0;
__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
- ifibss->channel, ifibss->basic_rates,
+ ifibss->chandef.chan, ifibss->basic_rates,
capability, 0, true);
}
@@ -789,7 +791,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
if (ifibss->fixed_bssid)
bssid = ifibss->bssid;
if (ifibss->fixed_channel)
- chan = ifibss->channel;
+ chan = ifibss->chandef.chan;
if (!is_zero_ether_addr(ifibss->bssid))
bssid = ifibss->bssid;
cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
@@ -1059,9 +1061,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
- sdata->u.ibss.channel = params->chandef.chan;
- sdata->u.ibss.channel_type =
- cfg80211_get_chandef_type(¶ms->chandef);
+ sdata->u.ibss.chandef = params->chandef;
sdata->u.ibss.fixed_channel = params->channel_fixed;
if (params->ie) {
@@ -1124,7 +1124,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
if (ifibss->privacy)
capability |= WLAN_CAPABILITY_PRIVACY;
- cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->channel,
+ cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan,
ifibss->bssid, ifibss->ssid,
ifibss->ssid_len, WLAN_CAPABILITY_IBSS |
WLAN_CAPABILITY_PRIVACY,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 44be28c..1079c27 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -505,8 +505,7 @@ struct ieee80211_if_ibss {
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len, ie_len;
u8 *ie;
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
unsigned long ibss_join_req;
/* probe response/beacon for IBSS */
--
1.7.10.4
^ permalink raw reply related
* [PATCH 6/8] ath9k: convert to chandef, enable support for 5/10 MHz channels
From: a @ 2013-05-09 18:10 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
To enable support for 5/10 MHz, also some internal functions must be
converted from using the (old) channel_type to chandef. This is a good
chance to change all remaining occurences.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
drivers/net/wireless/ath/ath9k/common.c | 67 +++++++++++++++----------
drivers/net/wireless/ath/ath9k/common.h | 3 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 5 +-
drivers/net/wireless/ath/ath9k/init.c | 4 +-
drivers/net/wireless/ath/ath9k/main.c | 8 ++-
drivers/net/wireless/ath/ath9k/rc.c | 4 +-
6 files changed, 51 insertions(+), 40 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 344fdde..d3063c2 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -49,37 +49,40 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
}
EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
-static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type)
+static u32 ath9k_get_extchanmode(struct cfg80211_chan_def *chandef)
{
u32 chanmode = 0;
- switch (chan->band) {
+ switch (chandef->chan->band) {
case IEEE80211_BAND_2GHZ:
- switch (channel_type) {
- case NL80211_CHAN_NO_HT:
- case NL80211_CHAN_HT20:
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
chanmode = CHANNEL_G_HT20;
break;
- case NL80211_CHAN_HT40PLUS:
- chanmode = CHANNEL_G_HT40PLUS;
+ case NL80211_CHAN_WIDTH_40:
+ if (chandef->center_freq1 > chandef->chan->center_freq)
+ chanmode = CHANNEL_G_HT40PLUS;
+ else
+ chanmode = CHANNEL_G_HT40MINUS;
break;
- case NL80211_CHAN_HT40MINUS:
- chanmode = CHANNEL_G_HT40MINUS;
+ default:
break;
}
break;
case IEEE80211_BAND_5GHZ:
- switch (channel_type) {
- case NL80211_CHAN_NO_HT:
- case NL80211_CHAN_HT20:
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
chanmode = CHANNEL_A_HT20;
break;
- case NL80211_CHAN_HT40PLUS:
- chanmode = CHANNEL_A_HT40PLUS;
+ case NL80211_CHAN_WIDTH_40:
+ if (chandef->center_freq1 > chandef->chan->center_freq)
+ chanmode = CHANNEL_A_HT40PLUS;
+ else
+ chanmode = CHANNEL_A_HT40MINUS;
break;
- case NL80211_CHAN_HT40MINUS:
- chanmode = CHANNEL_A_HT40MINUS;
+ default:
break;
}
break;
@@ -94,13 +97,12 @@ static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
* Update internal channel flags.
*/
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type)
+ struct cfg80211_chan_def *chandef)
{
- ichan->channel = chan->center_freq;
- ichan->chan = chan;
+ ichan->channel = chandef->chan->center_freq;
+ ichan->chan = chandef->chan;
- if (chan->band == IEEE80211_BAND_2GHZ) {
+ if (chandef->chan->band == IEEE80211_BAND_2GHZ) {
ichan->chanmode = CHANNEL_G;
ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
} else {
@@ -108,8 +110,22 @@ void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
}
- if (channel_type != NL80211_CHAN_NO_HT)
- ichan->chanmode = ath9k_get_extchanmode(chan, channel_type);
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_5:
+ ichan->channelFlags |= CHANNEL_QUARTER;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ ichan->channelFlags |= CHANNEL_HALF;
+ break;
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ break;
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_40:
+ ichan->chanmode = ath9k_get_extchanmode(chandef);
+ break;
+ default:
+ WARN_ON(1);
+ }
}
EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
@@ -125,8 +141,7 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
chan_idx = curchan->hw_value;
channel = &ah->channels[chan_idx];
- ath9k_cmn_update_ichannel(channel, curchan,
- cfg80211_get_chandef_type(&hw->conf.chandef));
+ ath9k_cmn_update_ichannel(channel, &hw->conf.chandef);
return channel;
}
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 207d069..e039bcb 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -44,8 +44,7 @@
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type);
+ struct cfg80211_chan_def *chandef);
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
struct ath_hw *ah);
int ath9k_cmn_count_streams(unsigned int chainmask, int max);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 0743a47..8c25c7a 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1194,16 +1194,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
struct ieee80211_channel *curchan = hw->conf.chandef.chan;
- enum nl80211_channel_type channel_type =
- cfg80211_get_chandef_type(&hw->conf.chandef);
int pos = curchan->hw_value;
ath_dbg(common, CONFIG, "Set channel: %d MHz\n",
curchan->center_freq);
ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
- hw->conf.chandef.chan,
- channel_type);
+ &hw->conf.chandef);
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
ath_err(common, "Unable to set channel\n");
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 3be2eb0..0959729 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -684,13 +684,15 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan;
struct ath_hw *ah = sc->sc_ah;
+ struct cfg80211_chan_def chandef;
int i;
sband = &sc->sbands[band];
for (i = 0; i < sband->n_channels; i++) {
chan = &sband->channels[i];
ah->curchan = &ah->channels[chan->hw_value];
- ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
+ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
+ ath9k_cmn_update_ichannel(ah->curchan, &chandef);
ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
}
}
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a383483..6804f4f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1189,8 +1189,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
struct ieee80211_channel *curchan = hw->conf.chandef.chan;
- enum nl80211_channel_type channel_type =
- cfg80211_get_chandef_type(&conf->chandef);
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
@@ -1198,8 +1196,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (ah->curchan)
old_pos = ah->curchan - &ah->channels[0];
- ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n",
- curchan->center_freq, channel_type);
+ ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
+ curchan->center_freq, hw->conf.chandef.width);
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
@@ -1214,7 +1212,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath9k_hw_getnf(ah, ah->curchan);
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
- curchan, channel_type);
+ &conf->chandef);
/*
* If the operating channel changes, change the survey in-use flags
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index aa4d368..ed57d57 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1327,8 +1327,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
ath_rc_init(sc, priv_sta);
ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
- "Operating HT Bandwidth changed to: %d\n",
- cfg80211_get_chandef_type(&sc->hw->conf.chandef));
+ "Operating Bandwidth changed to: %d\n",
+ &sc->hw->conf.chandef->width);
}
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/8] mac80211: fix various components for the new 5 and 10 MHz widths
From: a @ 2013-05-09 18:10 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
This is a collection of minor fixes:
* don't allow HT IEs in IBSS for 5/10 MHz
* don't allow HT IEs in Mesh for 5/10 MHz
* consider 5 and 10 MHz channels when downgrading
* don't try HT rates for 5 and 10 MHz channels when selecting rates
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
net/mac80211/ibss.c | 2 ++
net/mac80211/mesh.c | 4 +++-
net/mac80211/mesh_plink.c | 8 +++++++-
net/mac80211/mlme.c | 12 ++++++++++++
net/mac80211/rate.c | 8 +++++++-
5 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 170f9a7..4e1fb81 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -176,6 +176,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
/* add HT capability and information IEs */
if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
+ chandef.width != NL80211_CHAN_WIDTH_5 &&
+ chandef.width != NL80211_CHAN_WIDTH_10 &&
sband->ht_cap.ht_supported) {
pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
sband->ht_cap.cap);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6952760..5227b73 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -417,7 +417,9 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[band];
if (!sband->ht_cap.ht_supported ||
- sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
return 0;
if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 09bebed..02c05fa 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -154,8 +154,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
u16 ht_opmode;
bool non_ht_sta = false, ht20_sta = false;
- if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
+ switch (sdata->vif.bss_conf.chandef.width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
return 0;
+ default:
+ break;
+ }
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list, list) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2bfcdda..07cb2f3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -224,6 +224,12 @@ static u32 chandef_downgrade(struct cfg80211_chan_def *c)
c->width = NL80211_CHAN_WIDTH_20_NOHT;
ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
break;
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
+ WARN_ON_ONCE(1);
+ /* keep c->width */
+ ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
+ break;
}
WARN_ON_ONCE(!cfg80211_chandef_valid(c));
@@ -3850,6 +3856,12 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
*/
ret = ieee80211_vif_use_channel(sdata, &chandef,
IEEE80211_CHANCTX_SHARED);
+
+ /* don't downgrade for 5 and 10 MHz channels, though. */
+ if (chandef.width == NL80211_CHAN_WIDTH_5 ||
+ chandef.width == NL80211_CHAN_WIDTH_10)
+ return ret;
+
while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
ifmgd->flags |= chandef_downgrade(&chandef);
ret = ieee80211_vif_use_channel(sdata, &chandef,
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index d3f414f..dbbcd57 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -397,8 +397,14 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
return;
/* if HT BSS, and we handle a data frame, also try HT rates */
- if (chan_width == NL80211_CHAN_WIDTH_20_NOHT)
+ switch (chan_width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
return;
+ default:
+ break;
+ }
alt_rate.idx = 0;
/* keep protection flags */
--
1.7.10.4
^ permalink raw reply related
* [PATCH 8/8] ath5k: enable support for 5 MHz and 10 MHz channels
From: a @ 2013-05-09 18:10 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
drivers/net/wireless/ath/ath5k/ath5k.h | 1 +
drivers/net/wireless/ath/ath5k/base.c | 25 ++++++++++++++++++++++---
drivers/net/wireless/ath/ath5k/base.h | 2 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
4 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 2d691b8..74bd54d 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -29,6 +29,7 @@
#include <linux/average.h>
#include <linux/leds.h>
#include <net/mac80211.h>
+#include <net/cfg80211.h>
/* RX/TX descriptor hw structs
* TODO: Driver part should only see sw structs */
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 9b20d9e..e7a5708 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -56,6 +56,7 @@
#include <linux/etherdevice.h>
#include <linux/nl80211.h>
+#include <net/cfg80211.h>
#include <net/ieee80211_radiotap.h>
#include <asm/unaligned.h>
@@ -434,11 +435,27 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
* Called with ah->lock.
*/
int
-ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan)
+ath5k_chan_set(struct ath5k_hw *ah, struct cfg80211_chan_def *chandef)
{
ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
"channel set, resetting (%u -> %u MHz)\n",
- ah->curchan->center_freq, chan->center_freq);
+ ah->curchan->center_freq, chandef->chan->center_freq);
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ ah->ah_bwmode = AR5K_BWMODE_DEFAULT;
+ break;
+ case NL80211_CHAN_WIDTH_5:
+ ah->ah_bwmode = AR5K_BWMODE_5MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ ah->ah_bwmode = AR5K_BWMODE_10MHZ;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
/*
* To switch channels clear any pending DMA operations;
@@ -446,7 +463,7 @@ ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan)
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
- return ath5k_reset(ah, chan, true);
+ return ath5k_reset(ah, chandef->chan, true);
}
void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
@@ -2453,6 +2470,8 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
/* SW support for IBSS_RSN is provided by mac80211 */
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+ hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
+
/* both antennas can be configured as RX or TX */
hw->wiphy->available_antennas_tx = 0x3;
hw->wiphy->available_antennas_rx = 0x3;
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 6c94c7f..130075b 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -99,7 +99,7 @@ void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
void ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
struct ieee80211_vif *vif);
-int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
+int ath5k_chan_set(struct ath5k_hw *ah, struct cfg80211_chan_def *chandef);
void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 06f86f4..2129330 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -202,7 +202,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&ah->lock);
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- ret = ath5k_chan_set(ah, conf->chandef.chan);
+ ret = ath5k_chan_set(ah, &conf->chandef);
if (ret < 0)
goto unlock;
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/8] nl80211/cfg80211: add 5 and 10 MHz defines and wiphy flag
From: a @ 2013-05-09 18:10 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Add defines for 5 and 10 MHz channel width and fix channel
handling functions accordingly.
Also check for and report the WIPHY_FLAG_SUPPORTS_5_10_MHZ
capability.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 4 ++++
net/wireless/chan.c | 29 +++++++++++++++++++++++++++++
net/wireless/nl80211.c | 21 +++++++++++++++++----
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 26e9113..2aeecfa 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2321,6 +2321,7 @@ struct cfg80211_ops {
* responds to probe-requests in hardware.
* @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
* @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
+ * @WIPHY_FLAG_SUPPORTS_5_10_MHZ: Device supports 5 MHz and 10 MHz channels.
*/
enum wiphy_flags {
WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
@@ -2344,6 +2345,7 @@ enum wiphy_flags {
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD = BIT(19),
WIPHY_FLAG_OFFCHAN_TX = BIT(20),
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL = BIT(21),
+ WIPHY_FLAG_SUPPORTS_5_10_MHZ = BIT(22),
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index b484307..ed4f106 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2738,6 +2738,8 @@ enum nl80211_channel_type {
* and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well
* @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
* attribute must be provided as well
+ * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel
+ * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel
*/
enum nl80211_chan_width {
NL80211_CHAN_WIDTH_20_NOHT,
@@ -2746,6 +2748,8 @@ enum nl80211_chan_width {
NL80211_CHAN_WIDTH_80,
NL80211_CHAN_WIDTH_80P80,
NL80211_CHAN_WIDTH_160,
+ NL80211_CHAN_WIDTH_5,
+ NL80211_CHAN_WIDTH_10,
};
/**
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index fd556ac..4052815 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -54,6 +54,8 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
control_freq = chandef->chan->center_freq;
switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_20_NOHT:
if (chandef->center_freq1 != control_freq)
@@ -152,6 +154,12 @@ static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
int width;
switch (c->width) {
+ case NL80211_CHAN_WIDTH_5:
+ width = 5;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ width = 10;
+ break;
case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_20_NOHT:
width = 20;
@@ -194,6 +202,16 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
if (c1->width == c2->width)
return NULL;
+ /*
+ * can't be compatible if one of them are 5 or 10 MHz,
+ * but they have not the same width.
+ */
+ if (c1->width == NL80211_CHAN_WIDTH_5 ||
+ c1->width == NL80211_CHAN_WIDTH_10 ||
+ c2->width == NL80211_CHAN_WIDTH_5 ||
+ c2->width == NL80211_CHAN_WIDTH_10)
+ return NULL;
+
if (c1->width == NL80211_CHAN_WIDTH_20_NOHT ||
c1->width == NL80211_CHAN_WIDTH_20)
return c2;
@@ -349,6 +367,12 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
control_freq = chandef->chan->center_freq;
switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_5:
+ width = 5;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ width = 10;
+ break;
case NL80211_CHAN_WIDTH_20:
if (!ht_cap->ht_supported)
return false;
@@ -405,6 +429,11 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
if (width > 20)
prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
+ /* 5 and 10 MHz are only defined for the OFDM PHY */
+ if (width < 20)
+ prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
+
+
if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
width, prohibited_flags))
return false;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9cdcd9e..f67d825 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1228,6 +1228,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
goto nla_put_failure;
+ if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
+ nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ))
+ goto nla_put_failure;
(*split_start)++;
if (split)
@@ -1771,6 +1774,11 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
IEEE80211_CHAN_DISABLED))
return -EINVAL;
+ if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
+ chandef->width == NL80211_CHAN_WIDTH_10) &&
+ !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ))
+ return -EINVAL;
+
return 0;
}
@@ -6326,11 +6334,16 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef))
return -EINVAL;
- if (ibss.chandef.width > NL80211_CHAN_WIDTH_40)
- return -EINVAL;
- if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
- !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
+ switch (ibss.chandef.width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ break;
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_40:
+ if (rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)
+ break;
+ default:
return -EINVAL;
+ }
ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] ath9k: Disable spectral scan code to fix crash on rmmod.
From: Simon Wunderlich @ 2013-05-09 18:18 UTC (permalink / raw)
To: Sujith Manoharan; +Cc: greearb, linux-wireless, ath9k-devel
In-Reply-To: <20875.13834.615920.337442@gargle.gargle.HOWL>
[-- Attachment #1: Type: text/plain, Size: 4245 bytes --]
On Thu, May 09, 2013 at 11:07:14AM +0530, Sujith Manoharan wrote:
> greearb@candelatech.com wrote:
> > From: Ben Greear <greearb@candelatech.com>
> >
> > With CONFIG_ATH9K_DEBUGFS enabled, and slub memory poisoning
> > enabled, I see this crash on rmmod of ath9k. I'm not sure how
> > to fix this properly, but in the meantime, this patch to disable
> > the spectral scan code works around the problem for me.
> >
> > With memory poisoning and the verify_mem_not_deleted code
> > below added, the crash looks as follows... The dentry
> > is not *always* freed at this point, probably because rcu
> > callbacks haven't completed. You still get a crash soon
> > after, however.
>
> The relay file should probably be closed before calling ieee80211_unregister_hw().
> The ath9k debugfs directory is created inside the phy#/ directory and that would
> get cleaned up when the wiphy is unregistered.
>
> Does this help ?
Looks good to me, moving the closing of the relayfs file before the unregistering. Thanks
a lot for fixing my bugs, Sujith. :)
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
(BTW, would you mind sending this as proper [PATCH] again?)
>
> diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
> index 4101c4a..cecbe1f 100644
> --- a/drivers/net/wireless/ath/ath9k/debug.c
> +++ b/drivers/net/wireless/ath/ath9k/debug.c
> @@ -1684,6 +1684,14 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
> WARN_ON(i != ATH9K_SSTATS_LEN);
> }
>
> +void ath9k_deinit_debug(struct ath_softc *sc)
> +{
> + if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
> + relay_close(sc->rfs_chan_spec_scan);
> + sc->rfs_chan_spec_scan = NULL;
> + }
> +}
> +
> int ath9k_init_debug(struct ath_hw *ah)
> {
> struct ath_common *common = ath9k_hw_common(ah);
> diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
> index 62da19c..223418d 100644
> --- a/drivers/net/wireless/ath/ath9k/debug.h
> +++ b/drivers/net/wireless/ath/ath9k/debug.h
> @@ -297,6 +297,7 @@ struct ath9k_debug {
> };
>
> int ath9k_init_debug(struct ath_hw *ah);
> +void ath9k_deinit_debug(struct ath_softc *sc);
>
> void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
> void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
> @@ -332,6 +333,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
> return 0;
> }
>
> +static inline void ath9k_deinit_debug(struct ath_softc *sc)
> +{
> +}
> +
> static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
> enum ath9k_int status)
> {
> diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
> index c7b888f..c0aa4ff 100644
> --- a/drivers/net/wireless/ath/ath9k/init.c
> +++ b/drivers/net/wireless/ath/ath9k/init.c
> @@ -903,7 +903,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
> if (!ath_is_world_regd(reg)) {
> error = regulatory_hint(hw->wiphy, reg->alpha2);
> if (error)
> - goto unregister;
> + goto debug_cleanup;
> }
>
> ath_init_leds(sc);
> @@ -911,6 +911,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
>
> return 0;
>
> +debug_cleanup:
> + ath9k_deinit_debug(sc);
> unregister:
> ieee80211_unregister_hw(hw);
> rx_cleanup:
> @@ -939,11 +941,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
> sc->dfs_detector->exit(sc->dfs_detector);
>
> ath9k_eeprom_release(sc);
> -
> - if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
> - relay_close(sc->rfs_chan_spec_scan);
> - sc->rfs_chan_spec_scan = NULL;
> - }
> }
>
> void ath9k_deinit_device(struct ath_softc *sc)
> @@ -957,6 +954,7 @@ void ath9k_deinit_device(struct ath_softc *sc)
>
> ath9k_ps_restore(sc);
>
> + ath9k_deinit_debug(sc);
> ieee80211_unregister_hw(hw);
> ath_rx_cleanup(sc);
> ath9k_deinit_softc(sc);
> --
> 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
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH 0/8] Add support for 5 and 10 MHz channels
From: Simon Wunderlich @ 2013-05-09 18:20 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
[-- Attachment #1: Type: text/plain, Size: 265 bytes --]
On Thu, May 09, 2013 at 08:10:28PM +0200, a@pandem0nium wrote:
> [...]
I wonder if I'll ever learn to use send git send-email properly ... please
consider this as sent "From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>"
and sorry for the confusion.
Thanks!
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH 2/8] mac80211: fix various components for the new 5 and 10 MHz widths
From: Felix Fietkau @ 2013-05-09 18:31 UTC (permalink / raw)
Cc: linux-wireless, Johannes Berg, Mathias Kretschmer,
Simon Wunderlich
In-Reply-To: <1368123036-22721-3-git-send-email-a>
On 2013-05-09 8:10 PM, a@pandem0nium wrote:
> From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
>
> This is a collection of minor fixes:
> * don't allow HT IEs in IBSS for 5/10 MHz
> * don't allow HT IEs in Mesh for 5/10 MHz
> * consider 5 and 10 MHz channels when downgrading
> * don't try HT rates for 5 and 10 MHz channels when selecting rates
Why? HT rates work with 5/10 MHz just fine.
- Felix
^ permalink raw reply
* Re: Fun with QoS in AP mode.
From: Ben Greear @ 2013-05-09 18:50 UTC (permalink / raw)
To: Krishna Chaitanya
Cc: Sujith Manoharan, Cyril Segretain, linux-wireless@vger.kernel.org
In-Reply-To: <CABPxzY+t1bZRtYf26-3yjVqv15m2FjB0eZ29ixniqbVPZ2NoNA@mail.gmail.com>
On 05/09/2013 10:00 AM, Krishna Chaitanya wrote:
> On Thu, May 9, 2013 at 10:09 PM, Ben Greear <greearb@candelatech.com> wrote:
>>
>> On 05/09/2013 09:32 AM, Sujith Manoharan wrote:
>>>
>>> Ben Greear wrote:
>>>>
>>>> I suspect we need to set up rules with 'tc' and maybe iptables.
>>>>
>>>> I'm not having any luck finding any examples out on the web, but
>>>> surely the info is somewhere w/out having to fully understand 'tc'.
>>>
>>>
>>> DSCP can be used...
>>>
>>> Something like "iptables -t mangle -A OUTPUT -p tcp --dport 5005 -j DSCP --set-dscp-class "CS6""
>>> (Change the class for other priorities).
>>
>>
>> In my case, I'd like to match on the ToS set in the IP headers.
>>
>> Basically, just map ToS 192 to VO, for instance.
>
> Talking about rules, Are you able to see the ToS marked in the IP header in
> the sniffer and not in the 802.11 header? Then we can concentrate on
> marking the packet (or) mapping in the driver?
>
Ahh, in my case, I introduced the bug in my code trying to fix a kernel
splat when using pktgen to drive packets against wifi interfaces.
When I remove that, then the AP uses queues as expected. I'm going to
have to make the pktgen hack a bit better it seems.
With this in mind, other folks that want QoS working on their APs
probably just needs to somehow mangle the ToS on their packets
to get it automatically working. Hopefully no 'tc' or similar commands
would be needed.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [PATCH] bcma: add more core IDs
From: Rafał Miłecki @ 2013-05-09 19:24 UTC (permalink / raw)
To: linux-wireless, John W. Linville; +Cc: Hauke Mehrtens, Rafał Miłecki
PCIe and ARM CR4 cores were found on 14e4:43b1 AKA BCM4352.
Reported-by: Gabriel Thörnblad <gabriel@thornblad.com>
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
drivers/bcma/scan.c | 2 ++
include/linux/bcma/bcma.h | 5 ++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index bca9c80..8bffa5c 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -84,6 +84,8 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = {
{ BCMA_CORE_I2S, "I2S" },
{ BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
{ BCMA_CORE_SHIM, "SHIM" },
+ { BCMA_CORE_PCIE2, "PCIe Gen2" },
+ { BCMA_CORE_ARM_CR4, "ARM CR4" },
{ BCMA_CORE_DEFAULT, "Default" },
};
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index f14a98a..2e34db8 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -134,7 +134,10 @@ struct bcma_host_ops {
#define BCMA_CORE_I2S 0x834
#define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */
#define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */
-#define BCMA_CORE_ARM_CR4 0x83e
+#define BCMA_CORE_PHY_AC 0x83B
+#define BCMA_CORE_PCIE2 0x83C /* PCI Express Gen2 */
+#define BCMA_CORE_USB30_DEV 0x83D
+#define BCMA_CORE_ARM_CR4 0x83E
#define BCMA_CORE_DEFAULT 0xFFF
#define BCMA_MAX_NR_CORES 16
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 2/8] mac80211: fix various components for the new 5 and 10 MHz widths
From: Simon Wunderlich @ 2013-05-09 19:46 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Johannes Berg, Mathias Kretschmer,
Simon Wunderlich
In-Reply-To: <518BEB88.5090600@openwrt.org>
[-- Attachment #1: Type: text/plain, Size: 1325 bytes --]
Hello Felix,
On Thu, May 09, 2013 at 08:31:36PM +0200, Felix Fietkau wrote:
> On 2013-05-09 8:10 PM, a@pandem0nium wrote:
> > From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
> >
> > This is a collection of minor fixes:
> > * don't allow HT IEs in IBSS for 5/10 MHz
> > * don't allow HT IEs in Mesh for 5/10 MHz
> > * consider 5 and 10 MHz channels when downgrading
> > * don't try HT rates for 5 and 10 MHz channels when selecting rates
> Why? HT rates work with 5/10 MHz just fine.
Hm, to be honest I did not try - IEEE 802.11-2012 only mentions 5 and
10 MHz channels in section 18 (OFDM PHY) according with timing and other
parameters, but nothing like this (as far as I see) is mentioned in
Section 20 (High Throughput PHY).
On the other hand, it appears that AR9xxx based chipsets also support
2.4 GHz rates (DSSS, ERP-OFDM), so I can imagine also HT rates can
be supported as well.
The question is, how would we handle that? Allow HT IEs also for 5 and
10 MHz, and behave like it would be a 20 MHz channel? Are there any
other WiFi chipsets which support 5/10 MHz, should we consider them
(maybe they don't support that)? And what do others think about deviate
from standard? Personally, I don't mind, it would be cool to use HT rates
on these bandwidths too. :)
Cheers,
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH 2/8] mac80211: fix various components for the new 5 and 10 MHz widths
From: Felix Fietkau @ 2013-05-09 20:32 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, Johannes Berg, Mathias Kretschmer,
Simon Wunderlich
In-Reply-To: <20130509194620.GA24307@pandem0nium>
On 2013-05-09 9:46 PM, Simon Wunderlich wrote:
> Hello Felix,
>
> On Thu, May 09, 2013 at 08:31:36PM +0200, Felix Fietkau wrote:
>> On 2013-05-09 8:10 PM, a@pandem0nium wrote:
>> > From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
>> >
>> > This is a collection of minor fixes:
>> > * don't allow HT IEs in IBSS for 5/10 MHz
>> > * don't allow HT IEs in Mesh for 5/10 MHz
>> > * consider 5 and 10 MHz channels when downgrading
>> > * don't try HT rates for 5 and 10 MHz channels when selecting rates
>> Why? HT rates work with 5/10 MHz just fine.
>
> Hm, to be honest I did not try - IEEE 802.11-2012 only mentions 5 and
> 10 MHz channels in section 18 (OFDM PHY) according with timing and other
> parameters, but nothing like this (as far as I see) is mentioned in
> Section 20 (High Throughput PHY).
>
> On the other hand, it appears that AR9xxx based chipsets also support
> 2.4 GHz rates (DSSS, ERP-OFDM), so I can imagine also HT rates can
> be supported as well.
>
> The question is, how would we handle that? Allow HT IEs also for 5 and
> 10 MHz, and behave like it would be a 20 MHz channel?
Yes, I had 5/10 MHz running that way with a debugfs hack just fine.
> Are there any
> other WiFi chipsets which support 5/10 MHz, should we consider them
> (maybe they don't support that)?
No idea.
- Felix
^ permalink raw reply
* [PATCH 05/12] net/wireless: ATH9K should depend on HAS_DMA
From: Geert Uytterhoeven @ 2013-05-09 21:04 UTC (permalink / raw)
To: linux-kernel
Cc: Geert Uytterhoeven, Luis R. Rodriguez, John W. Linville,
linux-wireless, netdev
In-Reply-To: <1368133494-22198-1-git-send-email-geert@linux-m68k.org>
If NO_DMA=y:
drivers/built-in.o: In function `ath9k_beacon_generate':
drivers/net/wireless/ath/ath9k/beacon.c:146: undefined reference to `dma_unmap_single'
drivers/net/wireless/ath/ath9k/beacon.c:174: undefined reference to `dma_map_single'
drivers/net/wireless/ath/ath9k/beacon.c:176: undefined reference to `dma_mapping_error'
drivers/built-in.o: In function `ath9k_beacon_remove_slot':
drivers/net/wireless/ath/ath9k/beacon.c:252: undefined reference to `dma_unmap_single'
drivers/built-in.o: In function `ath_descdma_setup':
drivers/net/wireless/ath/ath9k/init.c:382: undefined reference to `dmam_alloc_coherent'
drivers/built-in.o: In function `ath_edma_get_buffers':
drivers/net/wireless/ath/ath9k/recv.c:616: undefined reference to `dma_sync_single_for_cpu'
drivers/built-in.o: In function `ath_get_next_rx_buf':
drivers/net/wireless/ath/ath9k/recv.c:740: undefined reference to `dma_sync_single_for_cpu'
drivers/built-in.o: In function `ath_rx_edma_cleanup':
drivers/net/wireless/ath/ath9k/recv.c:176: undefined reference to `dma_unmap_single'
drivers/built-in.o: In function `ath_rx_cleanup':
drivers/net/wireless/ath/ath9k/recv.c:340: undefined reference to `dma_unmap_single'
drivers/built-in.o: In function `ath_rx_edma_buf_link':
drivers/net/wireless/ath/ath9k/recv.c:122: undefined reference to `dma_sync_single_for_cpu'
drivers/built-in.o: In function `ath_rx_tasklet':
drivers/net/wireless/ath/ath9k/recv.c:1275: undefined reference to `dma_map_single'
drivers/net/wireless/ath/ath9k/recv.c:1277: undefined reference to `dma_mapping_error'
drivers/net/wireless/ath/ath9k/recv.c:1283: undefined reference to `dma_unmap_single'
drivers/built-in.o: In function `ath_rx_edma_init':
drivers/net/wireless/ath/ath9k/recv.c:226: undefined reference to `dma_map_single'
drivers/net/wireless/ath/ath9k/recv.c:229: undefined reference to `dma_mapping_error'
drivers/built-in.o: In function `ath_rx_init':
drivers/net/wireless/ath/ath9k/recv.c:303: undefined reference to `dma_map_single'
drivers/net/wireless/ath/ath9k/recv.c:306: undefined reference to `dma_mapping_error'
drivers/built-in.o: In function `ath_tx_complete_buf':
drivers/net/wireless/ath/ath9k/xmit.c:2088: undefined reference to `dma_unmap_single'
drivers/built-in.o: In function `ath_txstatus_setup':
drivers/net/wireless/ath/ath9k/xmit.c:2344: undefined reference to `dmam_alloc_coherent'
drivers/built-in.o: In function `ath_tx_set_retry':
drivers/net/wireless/ath/ath9k/xmit.c:307: undefined reference to `dma_sync_single_for_cpu'
drivers/built-in.o: In function `ath_tx_setup_buffer':
drivers/net/wireless/ath/ath9k/xmit.c:1887: undefined reference to `dma_map_single'
drivers/net/wireless/ath/ath9k/xmit.c:1889: undefined reference to `dma_mapping_error'
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
Cc: John W. Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
---
drivers/net/wireless/ath/ath9k/Kconfig | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 17507dc..f3dc124 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -17,7 +17,7 @@ config ATH9K_BTCOEX_SUPPORT
config ATH9K
tristate "Atheros 802.11n wireless cards support"
- depends on MAC80211
+ depends on MAC80211 && HAS_DMA
select ATH9K_HW
select MAC80211_LEDS
select LEDS_CLASS
--
1.7.0.4
^ permalink raw reply related
* Re: atheros AR5B22, using ath9k, can't switch between inscure and WEP/WPA
From: Wally @ 2013-05-10 3:16 UTC (permalink / raw)
To: Sujith Manoharan; +Cc: Adrian Chadd, linux-wireless, ath9k-devel
In-Reply-To: <20875.9473.525821.266607@gargle.gargle.HOWL>
[-- Attachment #1: Type: text/plain, Size: 3697 bytes --]
於 四,2013-05-09 於 09:54 +0530,Sujith Manoharan 提到:
> Wally wrote:
> > Recently I got a atheros mini-PCIE wifi module AR5B22, so I download
> > the latest version of compat-driver(compat-drivers-2013-03-28.tar.gz),
> > and build it for armel on my arm board, it works great but with one
> > little problem:
> >
> > If I connect to an inscure AP then change to a WEP/WPA AP, I can't
> > connect the inscure one again, I have to run "modprobe -r ath9k;
> > modprobe ath9k" to connect the inscure AP.
> >
> > I think this may be a bug in the ath9k driver, I also search this
> > bug on web but without an answer, so I send this letter for help.
>
> What commands do you use to connect to the APs ? Also, can you post the
> kernel log / wpa_supplicant log when the issue happens ?
>
> Sujith
Hi, Sujjth:
I do following steps to reproduce this problem:
/**********************************************************************/
first step, I connect to an inscure AP
1. sudo iwconfig wlan0 mode managed key off essid "dlink FRANCE"
2. sudo dhclient wlan0
dmesg give these messages:
[ 224.937500] wlan0: authenticate with 00:1c:f0:eb:9a:ed
[ 224.945312] wlan0: send auth to 00:1c:f0:eb:9a:ed (try 1/3)
[ 224.953125] wlan0: authenticated
[ 224.953125] ath9k 0000:01:00.0: wlan0: disabling HT as WMM/QoS is not
supported by the AP
[ 224.953125] ath9k 0000:01:00.0: wlan0: disabling VHT as WMM/QoS is
not supported by the AP
[ 224.960937] wlan0: associate with 00:1c:f0:eb:9a:ed (try 1/3)
[ 224.960937] wlan0: RX AssocResp from 00:1c:f0:eb:9a:ed (capab=0x421
status=0 aid=2)
[ 224.960937] wlan0: associated
second step, I connect to another WEP AP:
1. sudo dhclient -r
2. sudo iwconfig wlan0 mode managed essid "sw-wifi"
3. sudo wpa_supplicant -B -D wext -i wlan0 -c ./auth_file
4. sudo dhclient wlan0
dmesg give these messages:
[ 1425.843750] wlan0: deauthenticating from 00:1c:f0:eb:9a:ed by local
choice (reason=3)
[ 1436.296875] wlan0: authenticate with 00:26:5a:ff:c9:6d
[ 1436.312500] wlan0: send auth to 00:26:5a:ff:c9:6d (try 1/3)
[ 1436.312500] wlan0: deauthenticating from 00:26:5a:ff:c9:6d by local
choice (reason=3)
[ 1436.312500] wlan0: authenticate with 00:26:5a:ff:c9:6d
[ 1436.328125] wlan0: send auth to 00:26:5a:ff:c9:6d (try 1/3)
[ 1436.328125] wlan0: send auth to 00:26:5a:ff:c9:6d (try 2/3)
[ 1436.328125] wlan0: authenticated
[ 1436.328125] ath9k 0000:01:00.0: wlan0: disabling HT/VHT due to
WEP/TKIP use
[ 1436.328125] ath9k 0000:01:00.0: wlan0: disabling HT as WMM/QoS is not
supported by the AP
[ 1436.328125] ath9k 0000:01:00.0: wlan0: disabling VHT as WMM/QoS is
not supported by the AP
[ 1436.335937] wlan0: associate with 00:26:5a:ff:c9:6d (try 1/3)
[ 1436.335937] wlan0: RX AssocResp from 00:26:5a:ff:c9:6d (capab=0x431
status=0 aid=16)
[ 1436.335937] wlan0: associated
third step, I reconnect the inscure AP agian and failed:
1. sudo dhclient -r
2. sudo killall wpa_supplicant
2. sudo iwconfig wlan0 mode managed key off essid "dlink FRANCE"
3. sudo dhclient wlan0 <-- system can't get an IP forever...
dmesg give these messages:
[ 2049.585937] wlan0: deauthenticating from 00:26:5a:ff:c9:6d by local
choice (reason=3)
[ 2049.609375] cfg80211: Calling CRDA to update world regulatory domain
/**********************************************************************/
very weird, at third step, dmesg only print two messages, and not
start to do authenticate anymore. if I retry second step, it still can
connect WEP/WPA APs.
Hope this messages helps. the attach file is my auth_file using in
second step.
Wally
[-- Attachment #2: auth_file --]
[-- Type: text/plain, Size: 144 bytes --]
ctrl_interface=/var/run/wpa_supplicant
network={
scan_ssid=0
ssid="sw-wifi"
key_mgmt=NONE
wep_key0="3616atrust361"
wep_tx_keyidx=0
priority=5
}
^ permalink raw reply
* Re: [PATCH 0/8] Add support for 5 and 10 MHz channels
From: Johannes Berg @ 2013-05-10 7:26 UTC (permalink / raw)
To: a; +Cc: linux-wireless, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368123036-22721-1-git-send-email-a>
On Thu, 2013-05-09 at 20:10 +0200, a@pandem0nium wrote:
> Comments:
> * Is there any special requirement for handling beacons? For example,
> rates are halfed or quartered, but some rates could not be represented
> in the rate IEs. For example, 2.25 mbit/s can not be represented as
> multiple of 500 kbps.
> * therefore, all rates are handled like the corresponding 20 MHz
> rates
> internally, which makes a lot of things easier (no changes required
> for rc-algos, beacon creation, etc...). We might consider adjusting
> the
> output of rates for nl80211 or radiotap, though.
This seems completely wrong, since Clause 18 says:
The OFDM system also provides a “half-clocked” operation using
10 MHz channel spacings with data communications capabilities of
3, 4.5, 6, 9, 12, 18, 24, and 27 Mb/s. The support of
transmitting and receiving at data rates of 3, 6, and 12 Mb/s is
mandatory when using 10 MHz channel spacing. The half-clocked
operation doubles symbol times and clear channel assessment
(CCA) times when using 10 MHz channel spacing. The regulatory
requirements and information regarding use of this OFDM PHY are
in Annex D and Annex E.
IOW, it treats the rates as actually the rate they should be. Besides,
what's so hard about rounding up? (8.4.2.4)
and bits 6 to 0 are set to the data rate, if necessary rounded
up to the next 500kb/s, in units of 500 kb/s.
I also think you really need to handle this. If you just want a hack for
5/10 MHz, you can put it into drivers' debugfs, if not, then it should
be done properly :-)
johannes
^ permalink raw reply
* [PATCH] wl12xx: fix minimum required firmware version for wl127x multirole
From: Luciano Coelho @ 2013-05-10 7:32 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho, levipearson, hashcode0f
There was a typo in commit 8675f9 (wlcore/wl12xx/wl18xx: verify
multi-role and single-role fw versions), which was causing the
multirole firmware for wl127x (WiLink6) to be rejected. The actual
minimum version needed for wl127x multirole is 6.5.7.0.42.
Reported-by: Levi Pearson <levipearson@gmail.com>
Reported-by: Michael Scott <hashcode0f@gmail.com>
Cc: stable@kernel.org # 3.9+
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
drivers/net/wireless/ti/wl12xx/wl12xx.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index 222d035..139da4d 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -41,7 +41,7 @@
#define WL127X_IFTYPE_MR_VER 5
#define WL127X_MAJOR_MR_VER 7
#define WL127X_SUBTYPE_MR_VER WLCORE_FW_VER_IGNORE
-#define WL127X_MINOR_MR_VER 115
+#define WL127X_MINOR_MR_VER 42
/* FW chip version for wl128x */
#define WL128X_CHIP_VER 7
--
1.7.10.4
^ permalink raw reply related
* [PATCH] wl12xx: increase minimum singlerole firmware version required
From: Luciano Coelho @ 2013-05-10 7:47 UTC (permalink / raw)
To: linux-wireless; +Cc: coelho, tony
The minimum firmware version required for singlerole after recent
driver changes is 6/7.3.10.0.133.
Reported-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
drivers/net/wireless/ti/wl12xx/wl12xx.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index 139da4d..9e5484a 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -36,7 +36,7 @@
#define WL127X_IFTYPE_SR_VER 3
#define WL127X_MAJOR_SR_VER 10
#define WL127X_SUBTYPE_SR_VER WLCORE_FW_VER_IGNORE
-#define WL127X_MINOR_SR_VER 115
+#define WL127X_MINOR_SR_VER 133
/* minimum multi-role FW version for wl127x */
#define WL127X_IFTYPE_MR_VER 5
#define WL127X_MAJOR_MR_VER 7
@@ -49,7 +49,7 @@
#define WL128X_IFTYPE_SR_VER 3
#define WL128X_MAJOR_SR_VER 10
#define WL128X_SUBTYPE_SR_VER WLCORE_FW_VER_IGNORE
-#define WL128X_MINOR_SR_VER 115
+#define WL128X_MINOR_SR_VER 133
/* minimum multi-role FW version for wl128x */
#define WL128X_IFTYPE_MR_VER 5
#define WL128X_MAJOR_MR_VER 7
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 0/8] Add support for 5 and 10 MHz channels
From: Adrian Chadd @ 2013-05-10 9:12 UTC (permalink / raw)
To: Johannes Berg; +Cc: a, linux-wireless, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1368170776.8390.4.camel@jlt4.sipsolutions.net>
On 10 May 2013 00:26, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Thu, 2013-05-09 at 20:10 +0200, a@pandem0nium wrote:
>
>> Comments:
>> * Is there any special requirement for handling beacons? For example,
>> rates are halfed or quartered, but some rates could not be represented
>> in the rate IEs. For example, 2.25 mbit/s can not be represented as
>> multiple of 500 kbps.
>> * therefore, all rates are handled like the corresponding 20 MHz
>> rates
>> internally, which makes a lot of things easier (no changes required
>> for rc-algos, beacon creation, etc...). We might consider adjusting
>> the
>> output of rates for nl80211 or radiotap, though.
>
> This seems completely wrong, since Clause 18 says:
>
> The OFDM system also provides a “half-clocked” operation using
> 10 MHz channel spacings with data communications capabilities of
> 3, 4.5, 6, 9, 12, 18, 24, and 27 Mb/s. The support of
> transmitting and receiving at data rates of 3, 6, and 12 Mb/s is
> mandatory when using 10 MHz channel spacing. The half-clocked
> operation doubles symbol times and clear channel assessment
> (CCA) times when using 10 MHz channel spacing. The regulatory
> requirements and information regarding use of this OFDM PHY are
> in Annex D and Annex E.
>
> IOW, it treats the rates as actually the rate they should be. Besides,
> what's so hard about rounding up? (8.4.2.4)
>
> and bits 6 to 0 are set to the data rate, if necessary rounded
> up to the next 500kb/s, in units of 500 kb/s.
>
>
> I also think you really need to handle this. If you just want a hack for
> 5/10 MHz, you can put it into drivers' debugfs, if not, then it should
> be done properly :-)
I think net80211 from FreeBSD and madwifi do this. Ie, they advertise
the half and quarter rate speeds as their real speeds at half/quarter
rate.
If anything, interoperability would be nice.
Adrian
^ permalink raw reply
* Re: [PATCH 0/8] Add support for 5 and 10 MHz channels
From: Simon Wunderlich @ 2013-05-10 9:32 UTC (permalink / raw)
To: Adrian Chadd
Cc: Johannes Berg, linux-wireless, Mathias Kretschmer,
Simon Wunderlich
In-Reply-To: <CAJ-Vmo=RCVOD1ffraTexETgqYP6LbLAa_g0d2DVd8yTO99Q1AQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2413 bytes --]
Hey,
On Fri, May 10, 2013 at 02:12:00AM -0700, Adrian Chadd wrote:
> On 10 May 2013 00:26, Johannes Berg <johannes@sipsolutions.net> wrote:
> > On Thu, 2013-05-09 at 20:10 +0200, a@pandem0nium wrote:
> >
> >> Comments:
> >> * Is there any special requirement for handling beacons? For example,
> >> rates are halfed or quartered, but some rates could not be represented
> >> in the rate IEs. For example, 2.25 mbit/s can not be represented as
> >> multiple of 500 kbps.
> >> * therefore, all rates are handled like the corresponding 20 MHz
> >> rates
> >> internally, which makes a lot of things easier (no changes required
> >> for rc-algos, beacon creation, etc...). We might consider adjusting
> >> the
> >> output of rates for nl80211 or radiotap, though.
> >
> > This seems completely wrong, since Clause 18 says:
> >
> > The OFDM system also provides a “half-clocked” operation using
> > 10 MHz channel spacings with data communications capabilities of
> > 3, 4.5, 6, 9, 12, 18, 24, and 27 Mb/s. The support of
> > transmitting and receiving at data rates of 3, 6, and 12 Mb/s is
> > mandatory when using 10 MHz channel spacing. The half-clocked
> > operation doubles symbol times and clear channel assessment
> > (CCA) times when using 10 MHz channel spacing. The regulatory
> > requirements and information regarding use of this OFDM PHY are
> > in Annex D and Annex E.
> >
> > IOW, it treats the rates as actually the rate they should be. Besides,
> > what's so hard about rounding up? (8.4.2.4)
> >
> > and bits 6 to 0 are set to the data rate, if necessary rounded
> > up to the next 500kb/s, in units of 500 kb/s.
> >
> >
> > I also think you really need to handle this. If you just want a hack for
> > 5/10 MHz, you can put it into drivers' debugfs, if not, then it should
> > be done properly :-)
>
> I think net80211 from FreeBSD and madwifi do this. Ie, they advertise
> the half and quarter rate speeds as their real speeds at half/quarter
> rate.
Ah, OK.
>
> If anything, interoperability would be nice.
Yes interoperability would be nice of course - I'll re-work the patchset
to use the according half and quarter rates. Meanwhile, what do you guys think
about enabling HT too?
Cheers,
Simon
>
>
>
>
> Adrian
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH 0/8] Add support for 5 and 10 MHz channels
From: Johannes Berg @ 2013-05-10 9:34 UTC (permalink / raw)
To: Simon Wunderlich
Cc: Adrian Chadd, linux-wireless, Mathias Kretschmer,
Simon Wunderlich
In-Reply-To: <20130510093241.GA28714@pandem0nium>
On Fri, 2013-05-10 at 11:32 +0200, Simon Wunderlich wrote:
> Yes interoperability would be nice of course - I'll re-work the patchset
> to use the according half and quarter rates. Meanwhile, what do you guys think
> about enabling HT too?
I'd like to stick to the standard first. Enabling HT is nice for us, but
I'd like to see it done in a way that doesn't clash with a possible
future amendment doing it officially.
johannes
^ permalink raw reply
* [RFC 3/4] cfg80211: vastly simplify locking
From: Johannes Berg @ 2013-05-10 12:08 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368187689-29706-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Virtually all code paths in cfg80211 already (need to) hold
the RTNL. As such, there's little point in having another
four mutexes for various parts of the code, they just cause
lock ordering issues (and much of the time, the RTNL and a
few of the others need thus be held.)
Simplify all this by getting rid of the extra four mutexes
and just use the RTNL throughout. Only a few code changes
were needed to do this and we can get rid of a work struct
for bonus points.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/cfg80211.h | 5 +-
net/wireless/core.c | 169 +++++++++---------------------------------
net/wireless/core.h | 32 +-------
net/wireless/debugfs.c | 4 +-
net/wireless/ibss.c | 10 +--
net/wireless/mesh.c | 2 -
net/wireless/mlme.c | 12 +--
net/wireless/nl80211.c | 178 +++++++++------------------------------------
net/wireless/reg.c | 36 +++------
net/wireless/scan.c | 42 +++++------
net/wireless/sme.c | 26 +------
net/wireless/util.c | 11 ---
net/wireless/wext-compat.c | 22 +-----
net/wireless/wext-sme.c | 18 -----
14 files changed, 120 insertions(+), 447 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 26e9113..085e5f7 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1255,6 +1255,7 @@ struct cfg80211_ssid {
* @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted
+ * @notified: (internal) scan request was notified as done or aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
*/
struct cfg80211_scan_request {
@@ -1272,7 +1273,7 @@ struct cfg80211_scan_request {
/* internal */
struct wiphy *wiphy;
unsigned long scan_start;
- bool aborted;
+ bool aborted, notified;
bool no_cck;
/* keep last */
@@ -2872,8 +2873,6 @@ struct wireless_dev {
struct mutex mtx;
- struct work_struct cleanup_work;
-
bool use_4addr, p2p_started;
u8 address[ETH_ALEN] __aligned(sizeof(u16));
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 875d79a..3837326 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -36,12 +36,10 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("wireless configuration support");
MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
-/* RCU-protected (and cfg80211_mutex for writers) */
+/* RCU-protected (and RTNL for writers) */
LIST_HEAD(cfg80211_rdev_list);
int cfg80211_rdev_list_generation;
-DEFINE_MUTEX(cfg80211_mutex);
-
/* for debugfs */
static struct dentry *ieee80211_debugfs_dir;
@@ -53,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
"Disable 40MHz support in the 2.4GHz band");
-/* requires cfg80211_mutex to be held! */
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
{
struct cfg80211_registered_device *result = NULL, *rdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (rdev->wiphy_idx == wiphy_idx) {
@@ -77,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy)
return rdev->wiphy_idx;
}
-/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
{
struct cfg80211_registered_device *rdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
if (!rdev)
@@ -90,14 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy;
}
-/* requires cfg80211_mutex to be held */
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
{
struct cfg80211_registered_device *rdev2;
int wiphy_idx, taken = -1, result, digits;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
/* prohibit calling the thing phy%d when %d is not its number */
sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
@@ -195,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev)
{
- lockdep_assert_held(&rdev->devlist_mtx);
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
return;
@@ -235,8 +229,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
rtnl_lock();
- /* read-only iteration need not hold the devlist_mtx */
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (wdev->netdev) {
dev_close(wdev->netdev);
@@ -245,12 +237,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
/* otherwise, check iftype */
switch (wdev->iftype) {
case NL80211_IFTYPE_P2P_DEVICE:
- /* but this requires it */
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
break;
default:
break;
@@ -278,10 +265,7 @@ static void cfg80211_event_work(struct work_struct *work)
event_work);
rtnl_lock();
- cfg80211_lock_rdev(rdev);
-
cfg80211_process_rdev_events(rdev);
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -323,9 +307,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
/* give it a proper name */
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
- mutex_init(&rdev->mtx);
- mutex_init(&rdev->devlist_mtx);
- mutex_init(&rdev->sched_scan_mtx);
INIT_LIST_HEAD(&rdev->wdev_list);
INIT_LIST_HEAD(&rdev->beacon_registrations);
spin_lock_init(&rdev->beacon_registrations_lock);
@@ -573,11 +554,11 @@ int wiphy_register(struct wiphy *wiphy)
/* check and set up bitrates */
ieee80211_set_bitrate_flags(wiphy);
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
res = device_add(&rdev->wiphy.dev);
if (res) {
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
return res;
}
@@ -606,23 +587,19 @@ int wiphy_register(struct wiphy *wiphy)
}
cfg80211_debugfs_rdev_add(rdev);
- mutex_unlock(&cfg80211_mutex);
- /*
- * due to a locking dependency this has to be outside of the
- * cfg80211_mutex lock
- */
res = rfkill_register(rdev->rfkill);
if (res)
goto out_rm_dev;
- rtnl_lock();
rdev->wiphy.registered = true;
- rtnl_unlock();
- return 0;
+ res = 0;
+ goto out;
out_rm_dev:
device_del(&rdev->wiphy.dev);
+out:
+ rtnl_unlock();
return res;
}
EXPORT_SYMBOL(wiphy_register);
@@ -650,25 +627,19 @@ void wiphy_unregister(struct wiphy *wiphy)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- rtnl_lock();
- rdev->wiphy.registered = false;
- rtnl_unlock();
-
- rfkill_unregister(rdev->rfkill);
-
- /* protect the device list */
- mutex_lock(&cfg80211_mutex);
-
wait_event(rdev->dev_wait, ({
int __count;
- mutex_lock(&rdev->devlist_mtx);
+ rtnl_lock();
__count = rdev->opencount;
- mutex_unlock(&rdev->devlist_mtx);
+ rtnl_unlock();
__count == 0; }));
- mutex_lock(&rdev->devlist_mtx);
+ rtnl_lock();
+ rdev->wiphy.registered = false;
+
+ rfkill_unregister(rdev->rfkill);
+
BUG_ON(!list_empty(&rdev->wdev_list));
- mutex_unlock(&rdev->devlist_mtx);
/*
* First remove the hardware from everywhere, this makes
@@ -679,20 +650,6 @@ void wiphy_unregister(struct wiphy *wiphy)
synchronize_rcu();
/*
- * Try to grab rdev->mtx. If a command is still in progress,
- * hopefully the driver will refuse it since it's tearing
- * down the device already. We wait for this command to complete
- * before unlinking the item from the list.
- * Note: as codified by the BUG_ON above we cannot get here if
- * a virtual interface is still present. Hence, we can only get
- * to lock contention here if userspace issues a command that
- * identified the hardware by wiphy index.
- */
- cfg80211_lock_rdev(rdev);
- /* nothing */
- cfg80211_unlock_rdev(rdev);
-
- /*
* If this device got a regulatory hint tell core its
* free to listen now to a new shiny device regulatory hint
*/
@@ -701,7 +658,7 @@ void wiphy_unregister(struct wiphy *wiphy)
cfg80211_rdev_list_generation++;
device_del(&rdev->wiphy.dev);
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
flush_work(&rdev->scan_done_wk);
cancel_work_sync(&rdev->conn_work);
@@ -719,9 +676,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
struct cfg80211_internal_bss *scan, *tmp;
struct cfg80211_beacon_registration *reg, *treg;
rfkill_destroy(rdev->rfkill);
- mutex_destroy(&rdev->mtx);
- mutex_destroy(&rdev->devlist_mtx);
- mutex_destroy(&rdev->sched_scan_mtx);
list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
list_del(®->list);
kfree(reg);
@@ -746,36 +700,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
}
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
-static void wdev_cleanup_work(struct work_struct *work)
-{
- struct wireless_dev *wdev;
- struct cfg80211_registered_device *rdev;
-
- wdev = container_of(work, struct wireless_dev, cleanup_work);
- rdev = wiphy_to_dev(wdev->wiphy);
-
- mutex_lock(&rdev->sched_scan_mtx);
-
- if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
- rdev->scan_req->aborted = true;
- ___cfg80211_scan_done(rdev, true);
- }
-
- if (WARN_ON(rdev->sched_scan_req &&
- rdev->sched_scan_req->dev == wdev->netdev)) {
- __cfg80211_stop_sched_scan(rdev, false);
- }
-
- mutex_unlock(&rdev->sched_scan_mtx);
-
- mutex_lock(&rdev->devlist_mtx);
- rdev->opencount--;
- mutex_unlock(&rdev->devlist_mtx);
- wake_up(&rdev->dev_wait);
-
- dev_put(wdev->netdev);
-}
-
void cfg80211_unregister_wdev(struct wireless_dev *wdev)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
@@ -785,8 +709,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
if (WARN_ON(wdev->netdev))
return;
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
list_del_rcu(&wdev->list);
rdev->devlist_generation++;
@@ -798,8 +720,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
WARN_ON_ONCE(1);
break;
}
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
}
EXPORT_SYMBOL(cfg80211_unregister_wdev);
@@ -818,7 +738,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
}
void cfg80211_leave(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev)
+ struct wireless_dev *wdev)
{
struct net_device *dev = wdev->netdev;
@@ -828,9 +748,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
- mutex_lock(&rdev->sched_scan_mtx);
__cfg80211_stop_sched_scan(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
#ifdef CONFIG_CFG80211_WEXT
@@ -884,13 +802,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
* are added with nl80211.
*/
mutex_init(&wdev->mtx);
- INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
INIT_LIST_HEAD(&wdev->event_list);
spin_lock_init(&wdev->event_lock);
INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock);
- mutex_lock(&rdev->devlist_mtx);
wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++;
@@ -903,7 +819,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
}
wdev->netdev = dev;
wdev->sme_state = CFG80211_SME_IDLE;
- mutex_unlock(&rdev->devlist_mtx);
#ifdef CONFIG_CFG80211_WEXT
wdev->wext.default_key = -1;
wdev->wext.default_mgmt_key = -1;
@@ -929,26 +844,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
case NETDEV_DOWN:
cfg80211_update_iface_num(rdev, wdev->iftype, -1);
- dev_hold(dev);
- queue_work(cfg80211_wq, &wdev->cleanup_work);
+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+ if (WARN_ON(!rdev->scan_req->notified))
+ rdev->scan_req->aborted = true;
+ ___cfg80211_scan_done(rdev, true);
+ }
+
+ if (WARN_ON(rdev->sched_scan_req &&
+ rdev->sched_scan_req->dev == wdev->netdev)) {
+ __cfg80211_stop_sched_scan(rdev, false);
+ }
+
+ rdev->opencount--;
+ wake_up(&rdev->dev_wait);
break;
case NETDEV_UP:
- /*
- * If we have a really quick DOWN/UP succession we may
- * have this work still pending ... cancel it and see
- * if it was pending, in which case we need to account
- * for some of the work it would have done.
- */
- if (cancel_work_sync(&wdev->cleanup_work)) {
- mutex_lock(&rdev->devlist_mtx);
- rdev->opencount--;
- mutex_unlock(&rdev->devlist_mtx);
- dev_put(dev);
- }
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
switch (wdev->iftype) {
#ifdef CONFIG_CFG80211_WEXT
@@ -980,10 +891,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
}
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
rdev->opencount++;
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
/*
* Configure power management to the driver here so that its
@@ -1000,12 +908,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
case NETDEV_UNREGISTER:
/*
- * NB: cannot take rdev->mtx here because this may be
- * called within code protected by it when interfaces
- * are removed with nl80211.
- */
- mutex_lock(&rdev->devlist_mtx);
- /*
* It is possible to get NETDEV_UNREGISTER
* multiple times. To detect that, check
* that the interface is still on the list
@@ -1021,7 +923,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
kfree(wdev->wext.keys);
#endif
}
- mutex_unlock(&rdev->devlist_mtx);
/*
* synchronise (so that we won't find this netdev
* from other code any more) and then clear the list
@@ -1041,9 +942,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
return notifier_from_errno(-EOPNOTSUPP);
if (rfkill_blocked(rdev->rfkill))
return notifier_from_errno(-ERFKILL);
- mutex_lock(&rdev->devlist_mtx);
ret = cfg80211_can_add_interface(rdev, wdev->iftype);
- mutex_unlock(&rdev->devlist_mtx);
if (ret)
return notifier_from_errno(ret);
break;
@@ -1061,12 +960,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)
struct cfg80211_registered_device *rdev;
rtnl_lock();
- mutex_lock(&cfg80211_mutex);
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (net_eq(wiphy_net(&rdev->wiphy), net))
WARN_ON(cfg80211_switch_netns(rdev, &init_net));
}
- mutex_unlock(&cfg80211_mutex);
rtnl_unlock();
}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 95b2907..d21a0fc 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -5,7 +5,6 @@
*/
#ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H
-#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/rbtree.h>
@@ -23,11 +22,6 @@
struct cfg80211_registered_device {
const struct cfg80211_ops *ops;
struct list_head list;
- /* we hold this mutex during any call so that
- * we cannot do multiple calls at once, and also
- * to avoid the deregister call to proceed while
- * any call is in progress */
- struct mutex mtx;
/* rfkill support */
struct rfkill_ops rfkill_ops;
@@ -49,9 +43,7 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */
int wiphy_idx;
- /* associated wireless interfaces */
- struct mutex devlist_mtx;
- /* protected by devlist_mtx or RCU */
+ /* associated wireless interfaces, protected by rtnl or RCU */
struct list_head wdev_list;
int devlist_generation, wdev_id;
int opencount; /* also protected by devlist_mtx */
@@ -75,8 +67,6 @@ struct cfg80211_registered_device {
struct work_struct scan_done_wk;
struct work_struct sched_scan_results_wk;
- struct mutex sched_scan_mtx;
-
#ifdef CONFIG_NL80211_TESTMODE
struct genl_info *testmode_info;
#endif
@@ -120,15 +110,9 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
}
extern struct workqueue_struct *cfg80211_wq;
-extern struct mutex cfg80211_mutex;
extern struct list_head cfg80211_rdev_list;
extern int cfg80211_rdev_list_generation;
-static inline void assert_cfg80211_lock(void)
-{
- lockdep_assert_held(&cfg80211_mutex);
-}
-
struct cfg80211_internal_bss {
struct list_head list;
struct list_head hidden_list;
@@ -161,23 +145,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
int get_wiphy_idx(struct wiphy *wiphy);
-/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
struct net *net);
-static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)
-{
- mutex_lock(&rdev->mtx);
-}
-
-static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)
-{
- BUG_ON(IS_ERR(rdev) || !rdev);
- mutex_unlock(&rdev->mtx);
-}
-
static inline void wdev_lock(struct wireless_dev *wdev)
__acquires(wdev)
{
@@ -192,7 +164,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
mutex_unlock(&wdev->mtx);
}
-#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
+#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 920cabe..90d0500 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file,
if (!buf)
return -ENOMEM;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[band];
@@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file,
buf, buf_size, offset);
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index d80e471..5449c5a 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(wdev);
err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
wdev->wext.ibss.channel_fixed = false;
}
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
memcpy(wdev->wext.ibss.ssid, ssid, len);
wdev->wext.ibss.ssid_len = len;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
} else
wdev->wext.ibss.bssid = NULL;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 0bb93f3..6c216ad 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -185,11 +185,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = __cfg80211_join_mesh(rdev, dev, setup, conf);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 0c7b7dd..2f9d20c 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -314,14 +314,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
{
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len,
key, key_len, key_idx,
sae_data, sae_data_len);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -425,12 +425,12 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(wdev);
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
ssid, ssid_len, req);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -848,7 +848,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
dfs_update_channels_wk);
wiphy = &rdev->wiphy;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
sband = wiphy->bands[bandid];
if (!sband)
@@ -881,7 +881,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
check_again = true;
}
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
/* reschedule if there are other channels waiting to be cleared again */
if (check_again)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9cdcd9e..74cef32 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -59,7 +59,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
int wiphy_idx = -1;
int ifidx = -1;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
if (!have_ifidx && !have_wdev_id)
return ERR_PTR(-EINVAL);
@@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
continue;
- mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (have_ifidx && wdev->netdev &&
wdev->netdev->ifindex == ifidx) {
@@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
break;
}
}
- mutex_unlock(&rdev->devlist_mtx);
if (result)
break;
@@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
struct cfg80211_registered_device *rdev = NULL, *tmp;
struct net_device *netdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
if (!attrs[NL80211_ATTR_WIPHY] &&
!attrs[NL80211_ATTR_IFINDEX] &&
@@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
if (tmp) {
/* make sure wdev exists */
- mutex_lock(&tmp->devlist_mtx);
list_for_each_entry(wdev, &tmp->wdev_list, list) {
if (wdev->identifier != (u32)wdev_id)
continue;
found = true;
break;
}
- mutex_unlock(&tmp->devlist_mtx);
if (!found)
tmp = NULL;
@@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
/*
* This function returns a pointer to the driver
* that the genl_info item that is passed refers to.
- * If successful, it returns non-NULL and also locks
- * the driver's mutex!
- *
- * This means that you need to call cfg80211_unlock_rdev()
- * before being allowed to acquire &cfg80211_mutex!
- *
- * This is necessary because we need to lock the global
- * mutex to get an item off the list safely, and then
- * we lock the rdev mutex so it doesn't go away under us.
- *
- * We don't want to keep cfg80211_mutex locked
- * for all the time in order to allow requests on
- * other interfaces to go through at the same time.
*
* The result of this can be a PTR_ERR and hence must
* be checked with IS_ERR() for errors.
@@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
static struct cfg80211_registered_device *
cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
-
- mutex_lock(&cfg80211_mutex);
- rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
-
- /* if it is not an error we grab the lock on
- * it to assure it won't be going away while
- * we operate on it */
- if (!IS_ERR(rdev))
- mutex_lock(&rdev->mtx);
-
- mutex_unlock(&cfg80211_mutex);
-
- return rdev;
+ return __cfg80211_rdev_from_attrs(netns, info->attrs);
}
/* policy for the attributes */
@@ -455,7 +425,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
int err;
rtnl_lock();
- mutex_lock(&cfg80211_mutex);
if (!cb->args[0]) {
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
@@ -484,14 +453,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
*rdev = wiphy_to_dev(wiphy);
*wdev = NULL;
- mutex_lock(&(*rdev)->devlist_mtx);
list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
if (tmp->identifier == cb->args[1]) {
*wdev = tmp;
break;
}
}
- mutex_unlock(&(*rdev)->devlist_mtx);
if (!*wdev) {
err = -ENODEV;
@@ -499,19 +466,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
}
}
- cfg80211_lock_rdev(*rdev);
-
- mutex_unlock(&cfg80211_mutex);
return 0;
out_unlock:
- mutex_unlock(&cfg80211_mutex);
rtnl_unlock();
return err;
}
static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
{
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -1567,7 +1529,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
struct nlattr **tb = nl80211_fam.attrbuf;
int res;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
tb, nl80211_fam.maxattr, nl80211_policy);
if (res == 0) {
@@ -1581,10 +1543,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
- if (!netdev) {
- mutex_unlock(&cfg80211_mutex);
+ if (!netdev)
return -ENODEV;
- }
if (netdev->ieee80211_ptr) {
dev = wiphy_to_dev(
netdev->ieee80211_ptr->wiphy);
@@ -1628,7 +1588,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
!skb->len &&
cb->min_dump_alloc < 4096) {
cb->min_dump_alloc = 4096;
- mutex_unlock(&cfg80211_mutex);
return 1;
}
idx--;
@@ -1637,7 +1596,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
} while (cb->args[1] > 0);
break;
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
cb->args[0] = idx;
@@ -1792,7 +1751,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
if (result)
return result;
- mutex_lock(&rdev->devlist_mtx);
switch (iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
@@ -1816,7 +1774,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
default:
result = -EINVAL;
}
- mutex_unlock(&rdev->devlist_mtx);
return result;
}
@@ -1865,6 +1822,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u32 frag_threshold = 0, rts_threshold = 0;
u8 coverage_class = 0;
+ ASSERT_RTNL();
+
/*
* Try to find the wiphy and netdev. Normally this
* function shouldn't need the netdev, but this is
@@ -1874,31 +1833,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
* also passed a netdev to set_wiphy, so that it is
* possible to let that go to the right netdev!
*/
- mutex_lock(&cfg80211_mutex);
if (info->attrs[NL80211_ATTR_IFINDEX]) {
int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(genl_info_net(info), ifindex);
- if (netdev && netdev->ieee80211_ptr) {
+ if (netdev && netdev->ieee80211_ptr)
rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
+ else
netdev = NULL;
}
if (!netdev) {
rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
info->attrs);
- if (IS_ERR(rdev)) {
- mutex_unlock(&cfg80211_mutex);
+ if (IS_ERR(rdev))
return PTR_ERR(rdev);
- }
wdev = NULL;
netdev = NULL;
result = 0;
-
- mutex_lock(&rdev->mtx);
} else
wdev = netdev->ieee80211_ptr;
@@ -1911,8 +1864,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = cfg80211_dev_rename(
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
- mutex_unlock(&cfg80211_mutex);
-
if (result)
goto bad_res;
@@ -2119,7 +2070,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
bad_res:
- mutex_unlock(&rdev->mtx);
if (netdev)
dev_put(netdev);
return result;
@@ -2217,7 +2167,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
continue;
@@ -2227,7 +2177,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
}
if_idx = 0;
- mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (if_idx < if_start) {
if_idx++;
@@ -2236,17 +2185,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev) < 0) {
- mutex_unlock(&rdev->devlist_mtx);
goto out;
}
if_idx++;
}
- mutex_unlock(&rdev->devlist_mtx);
wp_idx++;
}
out:
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
cb->args[0] = wp_idx;
cb->args[1] = if_idx;
@@ -2479,11 +2426,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock);
- mutex_lock(&rdev->devlist_mtx);
wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++;
- mutex_unlock(&rdev->devlist_mtx);
break;
default:
break;
@@ -2992,8 +2937,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev;
bool ret = false;
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO)
@@ -3007,8 +2950,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
break;
}
- mutex_unlock(&rdev->devlist_mtx);
-
return ret;
}
@@ -3170,13 +3111,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
params.radar_required = true;
}
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
params.chandef.chan,
CHAN_MODE_SHARED,
radar_detect_width);
- mutex_unlock(&rdev->devlist_mtx);
-
if (err)
return err;
@@ -4899,18 +4837,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
void *hdr = NULL;
struct nlattr *nl_reg_rules;
unsigned int i;
- int err = -EINVAL;
-
- mutex_lock(&cfg80211_mutex);
if (!cfg80211_regdomain)
- goto out;
+ return -EINVAL;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg) {
- err = -ENOBUFS;
- goto out;
- }
+ if (!msg)
+ return -ENOBUFS;
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
NL80211_CMD_GET_REG);
@@ -4969,8 +4902,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
nla_nest_end(msg, nl_reg_rules);
genlmsg_end(msg, hdr);
- err = genlmsg_reply(msg, info);
- goto out;
+ return genlmsg_reply(msg, info);
nla_put_failure_rcu:
rcu_read_unlock();
@@ -4978,10 +4910,7 @@ nla_put_failure:
genlmsg_cancel(msg, hdr);
put_failure:
nlmsg_free(msg);
- err = -EMSGSIZE;
-out:
- mutex_unlock(&cfg80211_mutex);
- return err;
+ return -EMSGSIZE;
}
static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
@@ -5047,12 +4976,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
}
}
- mutex_lock(&cfg80211_mutex);
-
r = set_regdom(rd);
/* set_regdom took ownership */
rd = NULL;
- mutex_unlock(&cfg80211_mutex);
bad_reg:
kfree(rd);
@@ -5102,7 +5028,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->scan)
return -EOPNOTSUPP;
- mutex_lock(&rdev->sched_scan_mtx);
if (rdev->scan_req) {
err = -EBUSY;
goto unlock;
@@ -5288,7 +5213,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
}
unlock:
- mutex_unlock(&rdev->sched_scan_mtx);
return err;
}
@@ -5360,8 +5284,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
if (ie_len > wiphy->max_sched_scan_ie_len)
return -EINVAL;
- mutex_lock(&rdev->sched_scan_mtx);
-
if (rdev->sched_scan_req) {
err = -EINPROGRESS;
goto out;
@@ -5529,7 +5451,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
out_free:
kfree(request);
out:
- mutex_unlock(&rdev->sched_scan_mtx);
return err;
}
@@ -5537,17 +5458,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- int err;
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
!rdev->ops->sched_scan_stop)
return -EOPNOTSUPP;
- mutex_lock(&rdev->sched_scan_mtx);
- err = __cfg80211_stop_sched_scan(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
-
- return err;
+ return __cfg80211_stop_sched_scan(rdev, false);
}
static int nl80211_start_radar_detection(struct sk_buff *skb,
@@ -5579,12 +5495,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (!rdev->ops->start_radar_detection)
return -EOPNOTSUPP;
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
chandef.chan, CHAN_MODE_SHARED,
BIT(chandef.width));
if (err)
- goto err_locked;
+ return err;
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
if (!err) {
@@ -5592,9 +5507,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
wdev->cac_started = true;
wdev->cac_start_time = jiffies;
}
-err_locked:
- mutex_unlock(&rdev->devlist_mtx);
-
return err;
}
@@ -6457,6 +6369,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
void *data = NULL;
int data_len = 0;
+ rtnl_lock();
+
if (cb->args[0]) {
/*
* 0 is a valid index, but not valid for args[0],
@@ -6468,18 +6382,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
nl80211_fam.attrbuf, nl80211_fam.maxattr,
nl80211_policy);
if (err)
- return err;
+ goto out_err;
- mutex_lock(&cfg80211_mutex);
rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
nl80211_fam.attrbuf);
if (IS_ERR(rdev)) {
- mutex_unlock(&cfg80211_mutex);
- return PTR_ERR(rdev);
+ err = PTR_ERR(rdev);
+ goto out_err;
}
phy_idx = rdev->wiphy_idx;
rdev = NULL;
- mutex_unlock(&cfg80211_mutex);
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
cb->args[1] =
@@ -6491,14 +6403,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
data_len = nla_len((void *)cb->args[1]);
}
- mutex_lock(&cfg80211_mutex);
rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
if (!rdev) {
- mutex_unlock(&cfg80211_mutex);
- return -ENOENT;
+ err = -ENOENT;
+ goto out_err;
}
- cfg80211_lock_rdev(rdev);
- mutex_unlock(&cfg80211_mutex);
if (!rdev->ops->testmode_dump) {
err = -EOPNOTSUPP;
@@ -6539,7 +6448,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
/* see above */
cb->args[0] = phy_idx + 1;
out_err:
- cfg80211_unlock_rdev(rdev);
+ rtnl_unlock();
return err;
}
@@ -8172,9 +8081,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (wdev->p2p_started)
return 0;
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_add_interface(rdev, wdev->iftype);
- mutex_unlock(&rdev->devlist_mtx);
if (err)
return err;
@@ -8183,9 +8090,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
return err;
wdev->p2p_started = true;
- mutex_lock(&rdev->devlist_mtx);
rdev->opencount++;
- mutex_unlock(&rdev->devlist_mtx);
return 0;
}
@@ -8201,11 +8106,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->stop_p2p_device)
return -EOPNOTSUPP;
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
return 0;
}
@@ -8348,11 +8249,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
info->user_ptr[0] = rdev;
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
info->attrs);
if (IS_ERR(wdev)) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return PTR_ERR(wdev);
@@ -8363,7 +8264,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
if (!dev) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -EINVAL;
@@ -8377,7 +8277,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
if (dev) {
if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
!netif_running(dev)) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -ENETDOWN;
@@ -8386,17 +8285,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
dev_hold(dev);
} else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
if (!wdev->p2p_started) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -ENETDOWN;
}
}
- cfg80211_lock_rdev(rdev);
-
- mutex_unlock(&cfg80211_mutex);
-
info->user_ptr[0] = rdev;
}
@@ -8406,8 +8300,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
- if (info->user_ptr[0])
- cfg80211_unlock_rdev(info->user_ptr[0]);
if (info->user_ptr[1]) {
if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
struct wireless_dev *wdev = info->user_ptr[1];
@@ -8429,7 +8321,8 @@ static struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_wiphy,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_WIPHY,
@@ -8444,7 +8337,8 @@ static struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_interface,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WDEV,
+ .internal_flags = NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_INTERFACE,
@@ -8603,6 +8497,7 @@ static struct genl_ops nl80211_ops[] = {
.cmd = NL80211_CMD_GET_REG,
.doit = nl80211_get_reg,
.policy = nl80211_policy,
+ .internal_flags = NL80211_FLAG_NEED_RTNL,
/* can be retrieved by unprivileged users */
},
{
@@ -8610,6 +8505,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_reg,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_REQ_SET_REG,
@@ -9065,8 +8961,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
struct nlattr *nest;
int i;
- lockdep_assert_held(&rdev->sched_scan_mtx);
-
if (WARN_ON(!req))
return 0;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e713051..5ceadbb 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -387,7 +387,7 @@ static void reg_regdb_search(struct work_struct *work)
const struct ieee80211_regdomain *curdom, *regdom = NULL;
int i;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
mutex_lock(®_regdb_search_mutex);
while (!list_empty(®_regdb_search_list)) {
@@ -412,7 +412,7 @@ static void reg_regdb_search(struct work_struct *work)
if (!IS_ERR_OR_NULL(regdom))
set_regdom(regdom);
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
}
static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
@@ -1235,7 +1235,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
struct cfg80211_registered_device *rdev;
struct wiphy *wiphy;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
wiphy = &rdev->wiphy;
@@ -1580,21 +1580,19 @@ static void reg_process_pending_hints(void)
{
struct regulatory_request *reg_request, *lr;
- mutex_lock(&cfg80211_mutex);
- mutex_lock(®_mutex);
lr = get_last_request();
/* When last_request->processed becomes true this will be rescheduled */
if (lr && !lr->processed) {
REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");
- goto out;
+ return;
}
spin_lock(®_requests_lock);
if (list_empty(®_requests_list)) {
spin_unlock(®_requests_lock);
- goto out;
+ return;
}
reg_request = list_first_entry(®_requests_list,
@@ -1605,10 +1603,6 @@ static void reg_process_pending_hints(void)
spin_unlock(®_requests_lock);
reg_process_hint(reg_request, reg_request->initiator);
-
-out:
- mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
}
/* Processes beacon hints -- this has nothing to do with country IEs */
@@ -1617,9 +1611,6 @@ static void reg_process_pending_beacon_hints(void)
struct cfg80211_registered_device *rdev;
struct reg_beacon *pending_beacon, *tmp;
- mutex_lock(&cfg80211_mutex);
- mutex_lock(®_mutex);
-
/* This goes through the _pending_ beacon list */
spin_lock_bh(®_pending_beacons_lock);
@@ -1636,14 +1627,16 @@ static void reg_process_pending_beacon_hints(void)
}
spin_unlock_bh(®_pending_beacons_lock);
- mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
}
static void reg_todo(struct work_struct *work)
{
+ rtnl_lock();
+ mutex_lock(®_mutex);
reg_process_pending_hints();
reg_process_pending_beacon_hints();
+ mutex_unlock(®_mutex);
+ rtnl_unlock();
}
static void queue_regulatory_request(struct regulatory_request *request)
@@ -1727,10 +1720,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
}
EXPORT_SYMBOL(regulatory_hint);
-/*
- * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
- * therefore cannot iterate over the rdev list here.
- */
void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
const u8 *country_ie, u8 country_ie_len)
{
@@ -1762,7 +1751,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
/*
* We will run this only upon a successful connection on cfg80211.
* We leave conflict resolution to the workqueue, where can hold
- * cfg80211_mutex.
+ * the RTNL.
*/
if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
lr->wiphy_idx != WIPHY_IDX_INVALID)
@@ -1868,7 +1857,8 @@ static void restore_regulatory_settings(bool reset_user)
LIST_HEAD(tmp_reg_req_list);
struct cfg80211_registered_device *rdev;
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
mutex_lock(®_mutex);
reset_regdomains(true, &world_regdom);
@@ -1925,7 +1915,6 @@ static void restore_regulatory_settings(bool reset_user)
spin_unlock(®_requests_lock);
mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
REG_DBG_PRINT("Kicking the queue\n");
@@ -2307,7 +2296,6 @@ void wiphy_regulatory_register(struct wiphy *wiphy)
mutex_unlock(®_mutex);
}
-/* Caller must hold cfg80211_mutex */
void wiphy_regulatory_deregister(struct wiphy *wiphy)
{
struct wiphy *request_wiphy = NULL;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 2ce44a7..dd01b58 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
union iwreq_data wrqu;
#endif
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
request = rdev->scan_req;
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device,
scan_done_wk);
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
___cfg80211_scan_done(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
@@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
request->aborted = aborted;
+ request->notified = true;
queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
}
EXPORT_SYMBOL(cfg80211_scan_done);
@@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
request = rdev->sched_scan_req;
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
/* we don't have sched_scan_req anymore if the scan is stopping */
if (request) {
@@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
nl80211_send_sched_scan_results(rdev, request->dev);
}
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
void cfg80211_sched_scan_results(struct wiphy *wiphy)
@@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
trace_cfg80211_sched_scan_stopped(wiphy);
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
__cfg80211_stop_sched_scan(rdev, true);
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
@@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
{
struct net_device *dev;
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
if (!rdev->sched_scan_req)
return -ENOENT;
@@ -1043,21 +1044,19 @@ EXPORT_SYMBOL(cfg80211_unlink_bss);
static struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
{
- struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
dev = dev_get_by_index(net, ifindex);
if (!dev)
- goto out;
- if (dev->ieee80211_ptr) {
+ return ERR_PTR(-ENODEV);
+ if (dev->ieee80211_ptr)
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
+ else
rdev = ERR_PTR(-ENODEV);
dev_put(dev);
- out:
- mutex_unlock(&cfg80211_mutex);
return rdev;
}
@@ -1083,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev,
if (IS_ERR(rdev))
return PTR_ERR(rdev);
- mutex_lock(&rdev->sched_scan_mtx);
if (rdev->scan_req) {
err = -EBUSY;
goto out;
@@ -1190,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
dev_hold(dev);
}
out:
- mutex_unlock(&rdev->sched_scan_mtx);
kfree(creq);
- cfg80211_unlock_rdev(rdev);
return err;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
@@ -1491,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev,
if (IS_ERR(rdev))
return PTR_ERR(rdev);
- if (rdev->scan_req) {
- res = -EAGAIN;
- goto out;
- }
+ if (rdev->scan_req)
+ return -EAGAIN;
res = ieee80211_scan_results(rdev, info, extra, data->length);
data->length = 0;
@@ -1503,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev,
res = 0;
}
- out:
- cfg80211_unlock_rdev(rdev);
return res;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a9dc5c7..4a6d7af 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -43,35 +43,29 @@ static bool cfg80211_is_all_idle(void)
struct wireless_dev *wdev;
bool is_all_idle = true;
- mutex_lock(&cfg80211_mutex);
-
/*
* All devices must be idle as otherwise if you are actively
* scanning some new beacon hints could be learned and would
* count as new regulatory hints.
*/
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
- cfg80211_lock_rdev(rdev);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE)
is_all_idle = false;
wdev_unlock(wdev);
}
- cfg80211_unlock_rdev(rdev);
}
- mutex_unlock(&cfg80211_mutex);
-
return is_all_idle;
}
static void disconnect_work(struct work_struct *work)
{
- if (!cfg80211_is_all_idle())
- return;
-
- regulatory_hint_disconnect();
+ rtnl_lock();
+ if (cfg80211_is_all_idle())
+ regulatory_hint_disconnect();
+ rtnl_unlock();
}
static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
@@ -85,7 +79,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
ASSERT_RTNL();
ASSERT_RDEV_LOCK(rdev);
ASSERT_WDEV_LOCK(wdev);
- lockdep_assert_held(&rdev->sched_scan_mtx);
if (rdev->scan_req)
return -EBUSY;
@@ -226,9 +219,6 @@ void cfg80211_conn_work(struct work_struct *work)
u8 bssid_buf[ETH_ALEN], *bssid = NULL;
rtnl_lock();
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
@@ -253,9 +243,6 @@ void cfg80211_conn_work(struct work_struct *work)
wdev_unlock(wdev);
}
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -928,14 +915,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
{
int err;
- mutex_lock(&rdev->devlist_mtx);
- /* might request scan - scan_mtx -> wdev_mtx dependency */
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index bb52486..0be3f0d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -785,12 +785,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
ASSERT_RTNL();
ASSERT_RDEV_LOCK(rdev);
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list)
cfg80211_process_wdev_events(wdev);
-
- mutex_unlock(&rdev->devlist_mtx);
}
int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
@@ -822,10 +818,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
return -EBUSY;
if (ntype != otype && netif_running(dev)) {
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
ntype);
- mutex_unlock(&rdev->devlist_mtx);
if (err)
return err;
@@ -1187,8 +1181,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
if (!beacon_int)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (!wdev->beacon_interval)
continue;
@@ -1198,8 +1190,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
}
}
- mutex_unlock(&rdev->devlist_mtx);
-
return res;
}
@@ -1223,7 +1213,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
int i, j;
ASSERT_RTNL();
- lockdep_assert_held(&rdev->devlist_mtx);
if (WARN_ON(hweight32(radar_detect) > 1))
return -EINVAL;
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index d997d0f..e7c6e86 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -72,7 +72,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
struct cfg80211_registered_device *rdev;
struct vif_params vifparams;
enum nl80211_iftype type;
- int ret;
rdev = wiphy_to_dev(wdev->wiphy);
@@ -98,11 +97,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
memset(&vifparams, 0, sizeof(vifparams));
- cfg80211_lock_rdev(rdev);
- ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
- cfg80211_unlock_rdev(rdev);
-
- return ret;
+ return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
@@ -579,13 +574,10 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
{
int err;
- /* devlist mutex needed for possible IBSS re-join */
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
remove, tx_key, idx, params);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -787,7 +779,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
struct cfg80211_chan_def chandef = {
.width = NL80211_CHAN_WIDTH_20_NOHT,
};
- int freq, err;
+ int freq;
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -804,10 +796,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chandef.chan)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_set_monitor_channel(rdev, &chandef);
- mutex_unlock(&rdev->devlist_mtx);
- return err;
+ return cfg80211_set_monitor_channel(rdev, &chandef);
case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
if (freq < 0)
@@ -818,10 +807,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chandef.chan)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
- mutex_unlock(&rdev->devlist_mtx);
- return err;
+ return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
default:
return -EOPNOTSUPP;
}
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index e79cb5c..aeefd68 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -87,9 +87,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
return -EINVAL;
}
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -136,9 +133,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
@@ -190,9 +184,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
if (len > 0 && ssid[len - 1] == '\0')
len--;
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
err = 0;
@@ -226,9 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
@@ -287,9 +275,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
bssid = NULL;
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -318,9 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
--
1.8.0
^ permalink raw reply related
* [RFC 0/4] cfg80211/mac80211: simplify locking
From: Johannes Berg @ 2013-05-10 12:08 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb
I got a little fed up with all the locking, and decided to simplify.
This should still work, but I've only done some very simple tests.
I'm hoping it'll fix some of the weird corner cases that Ben and
others have found, which may be due to different locks in different
cases and things racing against each other ... I'm not convinced it
really will though, but hey, who knows :)
johannes
^ permalink raw reply
* [RFC 1/4] cfg80211: move cfg80211_get_dev_from_ifindex under wext
From: Johannes Berg @ 2013-05-10 12:08 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368187689-29706-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
The function is only used and needed by the wext code
for scanning, so move it there.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/wireless/core.c | 21 ---------------------
net/wireless/core.h | 4 ----
net/wireless/scan.c | 21 +++++++++++++++++++++
3 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 68f0c96..4e0b52f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -90,27 +90,6 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy;
}
-struct cfg80211_registered_device *
-cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
-{
- struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
- struct net_device *dev;
-
- mutex_lock(&cfg80211_mutex);
- dev = dev_get_by_index(net, ifindex);
- if (!dev)
- goto out;
- if (dev->ieee80211_ptr) {
- rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
- rdev = ERR_PTR(-ENODEV);
- dev_put(dev);
- out:
- mutex_unlock(&cfg80211_mutex);
- return rdev;
-}
-
/* requires cfg80211_mutex to be held */
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index fd35dae..95b2907 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -164,10 +164,6 @@ int get_wiphy_idx(struct wiphy *wiphy);
/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
-/* identical to cfg80211_get_dev_from_info but only operate on ifindex */
-extern struct cfg80211_registered_device *
-cfg80211_get_dev_from_ifindex(struct net *net, int ifindex);
-
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
struct net *net);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index fd99ea4..2ce44a7 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1040,6 +1040,27 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
EXPORT_SYMBOL(cfg80211_unlink_bss);
#ifdef CONFIG_CFG80211_WEXT
+static struct cfg80211_registered_device *
+cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
+{
+ struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
+ struct net_device *dev;
+
+ mutex_lock(&cfg80211_mutex);
+ dev = dev_get_by_index(net, ifindex);
+ if (!dev)
+ goto out;
+ if (dev->ieee80211_ptr) {
+ rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
+ mutex_lock(&rdev->mtx);
+ } else
+ rdev = ERR_PTR(-ENODEV);
+ dev_put(dev);
+ out:
+ mutex_unlock(&cfg80211_mutex);
+ return rdev;
+}
+
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
--
1.8.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox