* [PATCH 1/7] cfg80211: export cfg80211_chandef_dfs_required
From: Simon Wunderlich @ 2013-08-02 15:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1375457886-7275-1-git-send-email-siwu@hrz.tu-chemnitz.de>
It will be used later by the IBSS CSA implementation of mac80211.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
include/net/cfg80211.h | 9 +++++++++
net/wireless/chan.c | 1 +
net/wireless/core.h | 8 --------
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 6da5a6b..14c914f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -437,6 +437,15 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
u32 prohibited_flags);
/**
+ * cfg80211_chandef_dfs_required - checks if radar detection is required
+ * @wiphy: the wiphy to validate against
+ * @chandef: the channel definition to check
+ * Return: 1 if radar detection is required, 0 if it is not, < 0 on error
+ */
+int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *c);
+
+/**
* ieee80211_chandef_rate_flags - returns rate flags for a channel
*
* In some channel types, not all rates may be used - for example CCK
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 50f6195..16f3c3a 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -328,6 +328,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2,
width);
}
+EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 9ad43c6..8ed2094 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -382,14 +382,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
enum cfg80211_chan_mode chanmode,
u8 radar_detect);
-/**
- * cfg80211_chandef_dfs_required - checks if radar detection is required
- * @wiphy: the wiphy to validate against
- * @chandef: the channel definition to check
- * Return: 1 if radar detection is required, 0 if it is not, < 0 on error
- */
-int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
- const struct cfg80211_chan_def *c);
void cfg80211_set_dfs_state(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef,
--
1.7.10.4
^ permalink raw reply related
* [PATCH 7/7] nl80211: enable IBSS support for channel switch announcements
From: Simon Wunderlich @ 2013-08-02 15:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1375457886-7275-1-git-send-email-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>
---
net/wireless/nl80211.c | 49 +++++++++++++++++++++++++++++++++---------------
1 file changed, 34 insertions(+), 15 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f7cb121..6d3d788 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5632,15 +5632,26 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
u8 radar_detect_width = 0;
int err;
+ bool need_new_beacon = false;
if (!rdev->ops->channel_switch ||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
return -EOPNOTSUPP;
- /* may add IBSS support later */
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ switch (dev->ieee80211_ptr->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ need_new_beacon = true;
+
+ /* useless if AP is not running */
+ if (!wdev->beacon_interval)
+ return -EINVAL;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ break;
+ default:
return -EOPNOTSUPP;
+ }
memset(¶ms, 0, sizeof(params));
@@ -5649,15 +5660,16 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
/* only important for AP, IBSS and mesh create IEs internally */
- if (!info->attrs[NL80211_ATTR_CSA_IES])
- return -EINVAL;
-
- /* useless if AP is not running */
- if (!wdev->beacon_interval)
+ if (need_new_beacon &&
+ (!info->attrs[NL80211_ATTR_CSA_IES] ||
+ !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON]))
return -EINVAL;
params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
+ if (!need_new_beacon)
+ goto skip_beacons;
+
err = nl80211_parse_beacon(info->attrs, ¶ms.beacon_after);
if (err)
return err;
@@ -5697,6 +5709,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+skip_beacons:
err = nl80211_parse_chandef(rdev, info, ¶ms.chandef);
if (err)
return err;
@@ -5704,12 +5717,17 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef))
return -EINVAL;
- err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef);
- if (err < 0) {
- return err;
- } else if (err) {
- radar_detect_width = BIT(params.chandef.width);
- params.radar_required = true;
+ /* DFS channels are only supported for AP/P2P GO ... for now. */
+ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
+ dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
+ err = cfg80211_chandef_dfs_required(wdev->wiphy,
+ ¶ms.chandef);
+ if (err < 0) {
+ return err;
+ } else if (err) {
+ radar_detect_width = BIT(params.chandef.width);
+ params.radar_required = true;
+ }
}
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
@@ -10725,7 +10743,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
wdev_lock(wdev);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
- wdev->iftype != NL80211_IFTYPE_P2P_GO))
+ wdev->iftype != NL80211_IFTYPE_P2P_GO &&
+ wdev->iftype != NL80211_IFTYPE_ADHOC))
goto out;
wdev->channel = chandef->chan;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 6/7] mac80211: send a CSA action frame when changing channel
From: Simon Wunderlich @ 2013-08-02 15:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1375457886-7275-1-git-send-email-siwu@hrz.tu-chemnitz.de>
IBSS members may not immediately be able to send out their beacon when
performing CSA, therefore also send a CSA action frame.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
net/mac80211/ibss.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 4a10e00..2bd86a2 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -405,6 +405,61 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
tsf, false);
}
+static int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_csa_settings *csa_settings)
+{
+ struct sk_buff *skb;
+ struct ieee80211_mgmt *mgmt;
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+ struct ieee80211_local *local = sdata->local;
+ int freq;
+ int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) +
+ sizeof(mgmt->u.action.u.chan_switch);
+ u8 *pos;
+
+ skb = dev_alloc_skb(local->tx_headroom + hdr_len +
+ 5 + /* channel switch announcement element */
+ 3); /* secondary channel offset element */
+ if (!skb)
+ return -1;
+
+ skb_reserve(skb, local->tx_headroom);
+ mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len);
+ memset(mgmt, 0, hdr_len);
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION);
+
+ eth_broadcast_addr(mgmt->da);
+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
+ mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
+ mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
+ pos = skb_put(skb, 5);
+ *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */
+ *pos++ = 3; /* IE length */
+ *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */
+ freq = csa_settings->chandef.chan->center_freq;
+ *pos++ = ieee80211_frequency_to_channel(freq); /* channel */
+ *pos++ = csa_settings->count; /* count */
+
+ if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) {
+ enum nl80211_channel_type ch_type;
+
+ skb_put(skb, 3);
+ *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
+ *pos++ = 1; /* IE length */
+ ch_type = cfg80211_get_chandef_type(&csa_settings->chandef);
+ if (ch_type == NL80211_CHAN_HT40PLUS)
+ *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ else
+ *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ }
+
+ ieee80211_tx_skb(sdata, skb);
+ return 0;
+}
+
+
/* must hold sdata lock */
int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
struct cfg80211_csa_settings *csa_settings)
@@ -458,6 +513,12 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
if (old_presp)
kfree_rcu(old_presp, rcu_head);
+ /* it might not send the beacon for a while. send an action frame
+ * immediately to announce the channel switch.
+ */
+ if (csa_settings)
+ ieee80211_send_action_csa(sdata, csa_settings);
+
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
out:
return ret;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/7] mac80211: split off channel switch parsing function
From: Simon Wunderlich @ 2013-08-02 15:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1375457886-7275-1-git-send-email-siwu@hrz.tu-chemnitz.de>
The channel switch parsing function can be re-used for the IBSS code,
put the common part into an extra function.
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 | 22 +++++++
net/mac80211/mlme.c | 136 ++++++++++++++++++++++++--------------------
2 files changed, 97 insertions(+), 61 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e94c840..1275bde 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1333,6 +1333,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
+int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_csa_settings *csa_settings);
+int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata);
/* mesh code */
void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata);
@@ -1560,6 +1563,25 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc);
+
+/**
+ * ieee80211_parse_ch_switch_ie - parses channel switch IEs
+ * @sdata: the sdata of the interface which has received the frame
+ * @elems: parsed 802.11 elements received with the frame
+ * @beacon: indicates if the frame was a beacon or probe response
+ * @current_band: indicates the current band
+ * @sta_flags: contains information about own capabilities and restrictions
+ * @count: to be filled with the counter until the switch (on success only)
+ * @mode: to be filled with CSA mode (on success only)
+ * @new_chandef: to be filled with destination chandef (on success only)
+ * Return: 0 on success, <0 on error and >0 if there is nothing to parse.
+ */
+int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
+ struct ieee802_11_elems *elems, bool beacon,
+ enum ieee80211_band current_band,
+ u32 sta_flags, u8 *count, u8 *mode,
+ struct cfg80211_chan_def *new_chandef);
+
static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
bool action,
struct ieee802_11_elems *elems)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 45a87ee..60554c8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -981,54 +981,35 @@ static void ieee80211_chswitch_timer(unsigned long data)
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
}
-static void
-ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
- u64 timestamp, struct ieee802_11_elems *elems,
- bool beacon)
+int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
+ struct ieee802_11_elems *elems, bool beacon,
+ enum ieee80211_band current_band,
+ u32 sta_flags, u8 *count, u8 *mode,
+ struct cfg80211_chan_def *new_chandef)
{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct cfg80211_bss *cbss = ifmgd->associated;
- struct ieee80211_bss *bss;
- struct ieee80211_chanctx *chanctx;
enum ieee80211_band new_band;
int new_freq;
u8 new_chan_no;
- u8 count;
- u8 mode;
struct ieee80211_channel *new_chan;
- struct cfg80211_chan_def new_chandef = {};
struct cfg80211_chan_def new_vht_chandef = {};
const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
const struct ieee80211_ht_operation *ht_oper;
int secondary_channel_offset = -1;
- sdata_assert_lock(sdata);
-
- if (!cbss)
- return;
-
- if (local->scanning)
- return;
-
- /* disregard subsequent announcements if we are already processing */
- if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
- return;
-
sec_chan_offs = elems->sec_chan_offs;
wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
ht_oper = elems->ht_operation;
- if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
- IEEE80211_STA_DISABLE_40MHZ)) {
+ if (sta_flags & (IEEE80211_STA_DISABLE_HT |
+ IEEE80211_STA_DISABLE_40MHZ)) {
sec_chan_offs = NULL;
wide_bw_chansw_ie = NULL;
/* only used for bandwidth here */
ht_oper = NULL;
}
- if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
+ if (sta_flags & IEEE80211_STA_DISABLE_VHT)
wide_bw_chansw_ie = NULL;
if (elems->ext_chansw_ie) {
@@ -1038,33 +1019,28 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
sdata_info(sdata,
"cannot understand ECSA IE operating class %d, disconnecting\n",
elems->ext_chansw_ie->new_operating_class);
- ieee80211_queue_work(&local->hw,
- &ifmgd->csa_connection_drop_work);
+ return -EINVAL;
}
new_chan_no = elems->ext_chansw_ie->new_ch_num;
- count = elems->ext_chansw_ie->count;
- mode = elems->ext_chansw_ie->mode;
+ *count = elems->ext_chansw_ie->count;
+ *mode = elems->ext_chansw_ie->mode;
} else if (elems->ch_switch_ie) {
- new_band = cbss->channel->band;
+ new_band = current_band;
new_chan_no = elems->ch_switch_ie->new_ch_num;
- count = elems->ch_switch_ie->count;
- mode = elems->ch_switch_ie->mode;
+ *count = elems->ch_switch_ie->count;
+ *mode = elems->ch_switch_ie->mode;
} else {
/* nothing here we understand */
- return;
+ return 1;
}
- bss = (void *)cbss->priv;
-
new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) {
sdata_info(sdata,
- "AP %pM switches to unsupported channel (%d MHz), disconnecting\n",
- ifmgd->associated->bssid, new_freq);
- ieee80211_queue_work(&local->hw,
- &ifmgd->csa_connection_drop_work);
- return;
+ "network switches to unsupported channel (%d MHz), disconnecting\n",
+ new_freq);
+ return -EINVAL;
}
if (!beacon && sec_chan_offs) {
@@ -1072,7 +1048,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
} else if (beacon && ht_oper) {
secondary_channel_offset =
ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
- } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
+ } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) {
/*
* If it's not a beacon, HT is enabled and the IE not present,
* it's 20 MHz, 802.11-2012 8.5.2.6:
@@ -1088,25 +1064,25 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
default:
/* secondary_channel_offset was present but is invalid */
case IEEE80211_HT_PARAM_CHA_SEC_NONE:
- cfg80211_chandef_create(&new_chandef, new_chan,
+ cfg80211_chandef_create(new_chandef, new_chan,
NL80211_CHAN_HT20);
break;
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- cfg80211_chandef_create(&new_chandef, new_chan,
+ cfg80211_chandef_create(new_chandef, new_chan,
NL80211_CHAN_HT40PLUS);
break;
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
- cfg80211_chandef_create(&new_chandef, new_chan,
+ cfg80211_chandef_create(new_chandef, new_chan,
NL80211_CHAN_HT40MINUS);
break;
case -1:
- cfg80211_chandef_create(&new_chandef, new_chan,
+ cfg80211_chandef_create(new_chandef, new_chan,
NL80211_CHAN_NO_HT);
/* keep width for 5/10 MHz channels */
switch (sdata->vif.bss_conf.chandef.width) {
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
- new_chandef.width = sdata->vif.bss_conf.chandef.width;
+ new_chandef->width = sdata->vif.bss_conf.chandef.width;
break;
default:
break;
@@ -1142,13 +1118,13 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
break;
}
- if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ &&
+ if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ &&
new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80)
chandef_downgrade(&new_vht_chandef);
- if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ &&
+ if (sta_flags & IEEE80211_STA_DISABLE_160MHZ &&
new_vht_chandef.width == NL80211_CHAN_WIDTH_160)
chandef_downgrade(&new_vht_chandef);
- if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ &&
+ if (sta_flags & IEEE80211_STA_DISABLE_40MHZ &&
new_vht_chandef.width > NL80211_CHAN_WIDTH_20)
chandef_downgrade(&new_vht_chandef);
}
@@ -1156,23 +1132,61 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
/* if VHT data is there validate & use it */
if (new_vht_chandef.chan) {
if (!cfg80211_chandef_compatible(&new_vht_chandef,
- &new_chandef)) {
+ new_chandef)) {
sdata_info(sdata,
- "AP %pM CSA has inconsistent channel data, disconnecting\n",
- ifmgd->associated->bssid);
- ieee80211_queue_work(&local->hw,
- &ifmgd->csa_connection_drop_work);
- return;
+ "network CSA has inconsistent channel data, disconnecting\n");
+ return -EINVAL;
}
- new_chandef = new_vht_chandef;
+ *new_chandef = new_vht_chandef;
}
+ return 0;
+}
+
+static void
+ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
+ u64 timestamp, struct ieee802_11_elems *elems,
+ bool beacon)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct cfg80211_bss *cbss = ifmgd->associated;
+ struct ieee80211_chanctx *chanctx;
+ enum ieee80211_band current_band;
+ u8 count;
+ u8 mode;
+ struct cfg80211_chan_def new_chandef = {};
+ int res;
+
+ sdata_assert_lock(sdata);
+
+ if (!cbss)
+ return;
+
+ if (local->scanning)
+ return;
+
+ /* disregard subsequent announcements if we are already processing */
+ if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
+ return;
+
+ current_band = cbss->channel->band;
+ res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band,
+ ifmgd->flags, &count, &mode,
+ &new_chandef);
+ if (res < 0)
+ ieee80211_queue_work(&local->hw,
+ &ifmgd->csa_connection_drop_work);
+ if (res)
+ return;
+
if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef,
IEEE80211_CHAN_DISABLED)) {
sdata_info(sdata,
- "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
- ifmgd->associated->bssid, new_freq,
- new_chandef.width, new_chandef.center_freq1,
+ "network switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
+ new_chandef.chan->center_freq,
+ new_chandef.width,
+ new_chandef.center_freq1,
new_chandef.center_freq2);
ieee80211_queue_work(&local->hw,
&ifmgd->csa_connection_drop_work);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 4/7] mac80211: move ibss presp generation in own function
From: Simon Wunderlich @ 2013-08-02 15:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1375457886-7275-1-git-send-email-siwu@hrz.tu-chemnitz.de>
Channel Switch will later require to generate beacons without setting
them immediately. Therefore split the presp generation in an own
function. Splitting the original very long function might be a good idea
anyway.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
---
net/mac80211/ibss.c | 185 ++++++++++++++++++++++++++++++---------------------
1 file changed, 109 insertions(+), 76 deletions(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index e08387c..29f1a7b 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -34,13 +34,12 @@
#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
-
-static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
- const u8 *bssid, const int beacon_int,
- struct ieee80211_channel *chan,
- const u32 basic_rates,
- const u16 capability, u64 tsf,
- bool creator)
+static struct beacon_data *
+ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
+ const int beacon_int, const u32 basic_rates,
+ const u16 capability, u64 tsf,
+ struct cfg80211_chan_def *chandef,
+ bool *have_higher_than_11mbit)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
@@ -48,70 +47,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt;
u8 *pos;
struct ieee80211_supported_band *sband;
- struct cfg80211_bss *bss;
- u32 bss_change, rate_flags, rates = 0, rates_added = 0;
- struct cfg80211_chan_def chandef;
- enum nl80211_bss_scan_width scan_width;
- bool have_higher_than_11mbit = false;
+ u32 rate_flags, rates = 0, rates_added = 0;
struct beacon_data *presp;
int frame_len;
int shift;
- sdata_assert_lock(sdata);
-
- /* Reset own TSF to allow time synchronization work. */
- drv_reset_tsf(local, sdata);
-
- if (!ether_addr_equal(ifibss->bssid, bssid))
- sta_info_flush(sdata);
-
- /* if merging, indicate to driver that we leave the old IBSS */
- if (sdata->vif.bss_conf.ibss_joined) {
- sdata->vif.bss_conf.ibss_joined = false;
- sdata->vif.bss_conf.ibss_creator = false;
- sdata->vif.bss_conf.enable_beacon = false;
- netif_carrier_off(sdata->dev);
- ieee80211_bss_info_change_notify(sdata,
- BSS_CHANGED_IBSS |
- BSS_CHANGED_BEACON_ENABLED);
- }
-
- presp = rcu_dereference_protected(ifibss->presp,
- lockdep_is_held(&sdata->wdev.mtx));
- rcu_assign_pointer(ifibss->presp, NULL);
- if (presp)
- kfree_rcu(presp, rcu_head);
-
- sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
-
- chandef = ifibss->chandef;
- if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
- if (chandef.width == NL80211_CHAN_WIDTH_5 ||
- chandef.width == NL80211_CHAN_WIDTH_10 ||
- chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
- chandef.width == NL80211_CHAN_WIDTH_20) {
- sdata_info(sdata,
- "Failed to join IBSS, beacons forbidden\n");
- return;
- }
- chandef.width = NL80211_CHAN_WIDTH_20;
- chandef.center_freq1 = chan->center_freq;
- }
-
- ieee80211_vif_release_channel(sdata);
- if (ieee80211_vif_use_channel(sdata, &chandef,
- ifibss->fixed_channel ?
- IEEE80211_CHANCTX_SHARED :
- IEEE80211_CHANCTX_EXCLUSIVE)) {
- sdata_info(sdata, "Failed to join IBSS, no channel context\n");
- return;
- }
-
- memcpy(ifibss->bssid, bssid, ETH_ALEN);
-
- sband = local->hw.wiphy->bands[chan->band];
- shift = ieee80211_vif_get_shift(&sdata->vif);
-
/* Build IBSS probe response */
frame_len = sizeof(struct ieee80211_hdr_3addr) +
12 /* struct ieee80211_mgmt.u.beacon */ +
@@ -125,7 +65,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
ifibss->ie_len;
presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
if (!presp)
- return;
+ return NULL;
presp->head = (void *)(presp + 1);
@@ -146,12 +86,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
memcpy(pos, ifibss->ssid, ifibss->ssid_len);
pos += ifibss->ssid_len;
- rate_flags = ieee80211_chandef_rate_flags(&chandef);
+ sband = local->hw.wiphy->bands[chandef->chan->band];
+ rate_flags = ieee80211_chandef_rate_flags(chandef);
+ shift = ieee80211_chandef_get_shift(chandef);
+ rates_n = 0;
+ if (have_higher_than_11mbit)
+ *have_higher_than_11mbit = false;
+
for (i = 0; i < sband->n_bitrates; i++) {
if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
continue;
- if (sband->bitrates[i].bitrate > 110)
- have_higher_than_11mbit = true;
+ if (sband->bitrates[i].bitrate > 110 &&
+ have_higher_than_11mbit)
+ *have_higher_than_11mbit = true;
rates |= BIT(i);
rates_n++;
@@ -178,7 +125,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
if (sband->band == IEEE80211_BAND_2GHZ) {
*pos++ = WLAN_EID_DS_PARAMS;
*pos++ = 1;
- *pos++ = ieee80211_frequency_to_channel(chan->center_freq);
+ *pos++ = ieee80211_frequency_to_channel(
+ chandef->chan->center_freq);
}
*pos++ = WLAN_EID_IBSS_PARAMS;
@@ -210,9 +158,9 @@ 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 &&
+ 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) {
struct ieee80211_sta_ht_cap ht_cap;
@@ -226,7 +174,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
* keep them at 0
*/
pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
- &chandef, 0);
+ chandef, 0);
}
if (local->hw.queues >= IEEE80211_NUM_ACS) {
@@ -243,9 +191,94 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
presp->head_len = pos - presp->head;
if (WARN_ON(presp->head_len > frame_len))
+ goto error;
+
+ return presp;
+error:
+ kfree(presp);
+ return NULL;
+}
+
+static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
+ const u8 *bssid, const int beacon_int,
+ struct ieee80211_channel *chan,
+ const u32 basic_rates,
+ const u16 capability, u64 tsf,
+ bool creator)
+{
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_mgmt *mgmt;
+ struct cfg80211_bss *bss;
+ u32 bss_change;
+ struct cfg80211_chan_def chandef;
+ struct beacon_data *presp;
+ enum nl80211_bss_scan_width scan_width;
+ bool have_higher_than_11mbit;
+
+ sdata_assert_lock(sdata);
+
+ /* Reset own TSF to allow time synchronization work. */
+ drv_reset_tsf(local, sdata);
+
+ if (!ether_addr_equal(ifibss->bssid, bssid))
+ sta_info_flush(sdata);
+
+ /* if merging, indicate to driver that we leave the old IBSS */
+ if (sdata->vif.bss_conf.ibss_joined) {
+ sdata->vif.bss_conf.ibss_joined = false;
+ sdata->vif.bss_conf.ibss_creator = false;
+ sdata->vif.bss_conf.enable_beacon = false;
+ netif_carrier_off(sdata->dev);
+ ieee80211_bss_info_change_notify(sdata,
+ BSS_CHANGED_IBSS |
+ BSS_CHANGED_BEACON_ENABLED);
+ }
+
+ presp = rcu_dereference_protected(ifibss->presp,
+ lockdep_is_held(&sdata->wdev.mtx));
+ rcu_assign_pointer(ifibss->presp, NULL);
+ if (presp)
+ kfree_rcu(presp, rcu_head);
+
+ sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+
+ chandef = ifibss->chandef;
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
+ if (chandef.width == NL80211_CHAN_WIDTH_5 ||
+ chandef.width == NL80211_CHAN_WIDTH_10 ||
+ chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+ chandef.width == NL80211_CHAN_WIDTH_20) {
+ sdata_info(sdata,
+ "Failed to join IBSS, beacons forbidden\n");
+ return;
+ }
+ chandef.width = NL80211_CHAN_WIDTH_20;
+ chandef.center_freq1 = chan->center_freq;
+ }
+
+ ieee80211_vif_release_channel(sdata);
+ if (ieee80211_vif_use_channel(sdata, &chandef,
+ ifibss->fixed_channel ?
+ IEEE80211_CHANCTX_SHARED :
+ IEEE80211_CHANCTX_EXCLUSIVE)) {
+ sdata_info(sdata, "Failed to join IBSS, no channel context\n");
+ return;
+ }
+
+ memcpy(ifibss->bssid, bssid, ETH_ALEN);
+
+ sband = local->hw.wiphy->bands[chan->band];
+
+ presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates,
+ capability, tsf, &chandef,
+ &have_higher_than_11mbit);
+ if (!presp)
return;
rcu_assign_pointer(ifibss->presp, presp);
+ mgmt = (void *)presp->head;
sdata->vif.bss_conf.enable_beacon = true;
sdata->vif.bss_conf.beacon_int = beacon_int;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/7] add IBSS channel switch announcement support
From: Simon Wunderlich @ 2013-08-02 15:37 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
This patchset adds channel switch support for IBSS mode. This is required for
later DFS support in IBSS. It builds on top of the previously submitted AP DFS
patchset.
The rough design is:
* Userspace may request to change channel using the already introduced
NL80211_CMD_CHANNEL_SWITCH command. Unlike AP mode, it does not contain
IEs or offset for CSA elements, because this is to be generated by the kernel.
* Also other stations may request a channel change by sending (E)CSA within
beacons or action frames. This is parsed and further handled as if it would
have come from userspace.
* When performing a channel switch, an action frame is sent, because beaconing
is distributed among IBSS peers and might be lost early. Furthermore,
channel switch announcement IEs are added to the beacon/probe response.
* When a channel switch could was not understood, it disconnects from the
IBSS and tries to re-connect.
Discussion points:
* When disconnecting from the IBSS because a channel switch announcement was
bogus or not understood, we might reconnect to the same BSS again - on the
old channel, because the other stas are still there, and stay there.
Although it is "accepted behaviour" in IEEE 802.11 that not all station
could make it, we should consider ignoring beacons/presp if they include CSAs
when scanning for networks to prevent this problem.
As always, any comments are appreciated.
Cheers,
Simon
Simon Wunderlich (7):
cfg80211: export cfg80211_chandef_dfs_required
mac80211: fix ieee80211_sta_process_chanswitch for 5/10 MHz channels
mac80211: split off channel switch parsing function
mac80211: move ibss presp generation in own function
mac80211: add support for CSA in IBSS mode
mac80211: send a CSA action frame when changing channel
nl80211: enable IBSS support for channel switch announcements
include/net/cfg80211.h | 9 +
net/mac80211/cfg.c | 84 ++++--
net/mac80211/ibss.c | 715 +++++++++++++++++++++++++++++++++++---------
net/mac80211/ieee80211_i.h | 24 ++
net/mac80211/iface.c | 4 +
net/mac80211/mlme.c | 143 +++++----
net/mac80211/rx.c | 36 ++-
net/mac80211/tx.c | 34 ++-
net/wireless/chan.c | 1 +
net/wireless/core.h | 8 -
net/wireless/nl80211.c | 49 ++-
11 files changed, 853 insertions(+), 254 deletions(-)
--
1.7.10.4
^ permalink raw reply
* [PATCH 2/7] mac80211: fix ieee80211_sta_process_chanswitch for 5/10 MHz channels
From: Simon Wunderlich @ 2013-08-02 15:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1375457886-7275-1-git-send-email-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>
---
net/mac80211/mlme.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 211246b..45a87ee 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1102,6 +1102,15 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
case -1:
cfg80211_chandef_create(&new_chandef, new_chan,
NL80211_CHAN_NO_HT);
+ /* keep width for 5/10 MHz channels */
+ switch (sdata->vif.bss_conf.chandef.width) {
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
+ new_chandef.width = sdata->vif.bss_conf.chandef.width;
+ break;
+ default:
+ break;
+ }
break;
}
--
1.7.10.4
^ permalink raw reply related
* Re: changing dev->needed_headroom/needed_tailroom?
From: Eric Dumazet @ 2013-08-02 13:11 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Johannes Berg, netdev, linux-wireless
In-Reply-To: <1375433758.24371.20.camel@deadeye.wl.decadent.org.uk>
On Fri, 2013-08-02 at 10:55 +0200, Ben Hutchings wrote:
> I don't think this is safe when the interface is running (even if
> carrier is off). Some functions may read dev->needed_headroom twice and
> rely on getting the same value each time.
It should be no problem. Remaining unsafe places should be fixed.
We already had this discussion in the past, and some patches were
issued. Check commit ae641949df01b85117845bec45328eab6d6fada1
("net: Remove all uses of LL_ALLOCATED_SPACE")
^ permalink raw reply
* Re: [RFC 1/3] nl/cfg80211: add chan_time for scan request
From: Johannes Berg @ 2013-08-02 13:01 UTC (permalink / raw)
To: Michal Kazior; +Cc: linux-wireless, ath10k
In-Reply-To: <CA+BoTQ=XNeYL1KLGQ4gRCZ03a9XsAWde4O7_T-dqKndLLKeX_g@mail.gmail.com>
> > That's what I'm worried about - the implicit semantic change here.
>
> I think I understand your point now.
>
> I'm thinking of using series of passive scans for ACS now, so perhaps
> the whole chan_time stuff is unnecessary. What are your thoughts about
> it?
Well, still then you're relying on the fact that passive channels scans
will stick to each channel for ~110ms or so. This is true today, but
it's not really specified.
I don't think that using the scan command would be a big deal, but maybe
this 'measurement' behaviour should be explicitly enabled? Maybe other
devices even have to do something special to collect the data.
johannes
^ permalink raw reply
* Re: [RFC 1/3] nl/cfg80211: add chan_time for scan request
From: Sunil Dutt @ 2013-08-02 12:56 UTC (permalink / raw)
To: linux-wireless, ath10k
In-Reply-To: <CACA4iOrZSARKFVFx1E2QPyH=xZzQp+VoyPu_tuFWgBR3tQwOmw@mail.gmail.com>
Hi Johannes and Michal ,
In this context I would also like to mention that there are also some
use cases ( Ex WiFi Positioning) , where good performance shall
result from using signals from as many Access Points as possible, a
fixed dwell / chan time in the host driver shall result in the poor
discovery efficiency of the Access Points,negatively impacting WiFi
positioning performance.
I would say such applications shall benefit by configuring a chan (dwell)_time.
Also,an attribute corresponding to the mode of the scan ( active /
passive ) , along with chan_time would benefit such applications with
more configurable options. Isn't it ?
Please correct me .
Regards,
Sunil
On Fri, Aug 2, 2013 at 6:00 PM, Sunil Dutt <usdutt@gmail.com> wrote:
> Hi Johannes and Michal ,
> In this context I would also like to mention that there are also some use
> cases ( Ex WiFi Positioning) , where good performance shall result from
> using signals from as many Access Points as possible, a fixed dwell / chan
> time in the host driver shall result in the poor discovery efficiency of the
> Access Points,negatively impacting WiFi positioning performance.
>
> I would say such applications shall benefit by configuring a chan
> (dwell)_time.
> Also,an attribute corresponding to the mode of the scan ( active / passive )
> , along with chan_time would benefit such applications with more
> configurable options. Isn't it ?
> Please correct me .
>
> Regards,
> Sunil
>
>
>
>
> On Fri, Aug 2, 2013 at 4:55 PM, Johannes Berg <johannes@sipsolutions.net>
> wrote:
>>
>> On Thu, 2013-08-01 at 11:14 +0200, Michal Kazior wrote:
>>
>> > > This seems a bit iffy - you don't differentiate between active/passive
>> > > scans?
>> >
>> > Is there a reason this should be differentiated?
>>
>> Well they don't usually have the same timing, passive channel dwell time
>> usually needs to be longer than on active channels.
>>
>> > > This also interferes a bit with some other scan optimisations that
>> > > could
>> > > be done at a low firmware level, so I think we should be careful and
>> > > actually say that this is really more intended for measurement use
>> > > cases
>> > > and not for normal scans?
>> > >
>> > > Or maybe we should have a separate measurement command with similar
>> > > semantics? This all doesn't seem very clear to me yet :)
>> >
>> > Motivation behind this patchset is to simplify ACS implementation and
>> > depend on scan. This also allows easier fallback from survey-based ACS
>> > to BSS-based one.
>>
>> Sure, I understand.
>>
>> > Other use cases are a side-effect so perhaps clarifying the intent in
>> > the docs is enough.
>>
>> I'm just saying that this is a fundamentally different usage than actual
>> scanning. Let's say for the sake of the argument I find a way to scan
>> channels quicker and implement that in my device (hw_scan). I don't
>> think this is too far-fetched, imagine I have an 80MHz capable device
>> and can send probe request 4x transmissions on all the subchannels, if
>> somehow I manage to separate the receive then I could scan 4x as
>> quickly. I don't think this particular thing is possible but I could
>> imagine scan optimisations like it.
>>
>> Now this comes along - and suddenly the API requires that you stay on
>> each specified channel for the given period of time. Any such
>> "non-traditional" scan optimisations would have to be given up, so in a
>> sense this fundamentally alters the semantics of the scan primitive,
>> where before it was "give me the list of networks (with these SSIDs) on
>> these channels" it now becomes "go to each channel, stay there for this
>> amount of time and ..."
>>
>> That's what I'm worried about - the implicit semantic change here.
>>
>> johannes
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-wireless"
>> in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
^ permalink raw reply
* Re: [RFC 1/3] nl/cfg80211: add chan_time for scan request
From: Michal Kazior @ 2013-08-02 11:52 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, ath10k
In-Reply-To: <1375442751.18144.7.camel@jlt4.sipsolutions.net>
On 2 August 2013 13:25, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Thu, 2013-08-01 at 11:14 +0200, Michal Kazior wrote:
>
>> > This seems a bit iffy - you don't differentiate between active/passive
>> > scans?
>>
>> Is there a reason this should be differentiated?
>
> Well they don't usually have the same timing, passive channel dwell time
> usually needs to be longer than on active channels.
>
>> > This also interferes a bit with some other scan optimisations that could
>> > be done at a low firmware level, so I think we should be careful and
>> > actually say that this is really more intended for measurement use cases
>> > and not for normal scans?
>> >
>> > Or maybe we should have a separate measurement command with similar
>> > semantics? This all doesn't seem very clear to me yet :)
>>
>> Motivation behind this patchset is to simplify ACS implementation and
>> depend on scan. This also allows easier fallback from survey-based ACS
>> to BSS-based one.
>
> Sure, I understand.
>
>> Other use cases are a side-effect so perhaps clarifying the intent in
>> the docs is enough.
>
> I'm just saying that this is a fundamentally different usage than actual
> scanning. Let's say for the sake of the argument I find a way to scan
> channels quicker and implement that in my device (hw_scan). I don't
> think this is too far-fetched, imagine I have an 80MHz capable device
> and can send probe request 4x transmissions on all the subchannels, if
> somehow I manage to separate the receive then I could scan 4x as
> quickly. I don't think this particular thing is possible but I could
> imagine scan optimisations like it.
>
> Now this comes along - and suddenly the API requires that you stay on
> each specified channel for the given period of time. Any such
> "non-traditional" scan optimisations would have to be given up, so in a
> sense this fundamentally alters the semantics of the scan primitive,
> where before it was "give me the list of networks (with these SSIDs) on
> these channels" it now becomes "go to each channel, stay there for this
> amount of time and ..."
>
> That's what I'm worried about - the implicit semantic change here.
I think I understand your point now.
I'm thinking of using series of passive scans for ACS now, so perhaps
the whole chan_time stuff is unnecessary. What are your thoughts about
it?
Pozdrawiam / Best regards,
Michał Kazior.
^ permalink raw reply
* Re: [RFC 1/3] nl/cfg80211: add chan_time for scan request
From: Johannes Berg @ 2013-08-02 11:25 UTC (permalink / raw)
To: Michal Kazior; +Cc: linux-wireless, ath10k
In-Reply-To: <CA+BoTQm+rWRRpp6XQ_-YHMBfH0Q4ecZ3z-6TV3cvFZ=8uXWsQA@mail.gmail.com>
On Thu, 2013-08-01 at 11:14 +0200, Michal Kazior wrote:
> > This seems a bit iffy - you don't differentiate between active/passive
> > scans?
>
> Is there a reason this should be differentiated?
Well they don't usually have the same timing, passive channel dwell time
usually needs to be longer than on active channels.
> > This also interferes a bit with some other scan optimisations that could
> > be done at a low firmware level, so I think we should be careful and
> > actually say that this is really more intended for measurement use cases
> > and not for normal scans?
> >
> > Or maybe we should have a separate measurement command with similar
> > semantics? This all doesn't seem very clear to me yet :)
>
> Motivation behind this patchset is to simplify ACS implementation and
> depend on scan. This also allows easier fallback from survey-based ACS
> to BSS-based one.
Sure, I understand.
> Other use cases are a side-effect so perhaps clarifying the intent in
> the docs is enough.
I'm just saying that this is a fundamentally different usage than actual
scanning. Let's say for the sake of the argument I find a way to scan
channels quicker and implement that in my device (hw_scan). I don't
think this is too far-fetched, imagine I have an 80MHz capable device
and can send probe request 4x transmissions on all the subchannels, if
somehow I manage to separate the receive then I could scan 4x as
quickly. I don't think this particular thing is possible but I could
imagine scan optimisations like it.
Now this comes along - and suddenly the API requires that you stay on
each specified channel for the given period of time. Any such
"non-traditional" scan optimisations would have to be given up, so in a
sense this fundamentally alters the semantics of the scan primitive,
where before it was "give me the list of networks (with these SSIDs) on
these channels" it now becomes "go to each channel, stay there for this
amount of time and ..."
That's what I'm worried about - the implicit semantic change here.
johannes
^ permalink raw reply
* Re: [PATCH 3.11] nl80211: fix another nl80211_fam.attrbuf race
From: Ben Hutchings @ 2013-08-02 9:32 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Johannes Berg
In-Reply-To: <1375216722-31194-1-git-send-email-johannes@sipsolutions.net>
[-- Attachment #1: Type: text/plain, Size: 855 bytes --]
On Tue, 2013-07-30 at 22:38 +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> This is similar to the race Linus had reported, but in this case
> it's an older bug: nl80211_prepare_wdev_dump() uses the wiphy
> index in cb->args[0] as it is and thus parses the message over
> and over again instead of just once because 0 is the first valid
> wiphy index. Similar code in nl80211_testmode_dump() correctly
> offsets the wiphy_index by 1, do that here as well.
>
> Cc: stable@vger.kernel.org
> Reported-by: Ben Hutchings <ben@decadent.org.uk>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
[...]
With this patch applied, I haven't seen another crash after another day
and a bit in the same wifi environment.
Ben.
--
Ben Hutchings
This sentence contradicts itself - no actually it doesn't.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
* Re: [PATCH 3.10 0/3] Enable 7000 device family on 3.10
From: Greg KH @ 2013-08-02 9:02 UTC (permalink / raw)
To: Emmanuel Grumbach; +Cc: stable, linux-wireless
In-Reply-To: <1373888700-3040-1-git-send-email-emmanuel.grumbach@intel.com>
On Mon, Jul 15, 2013 at 02:44:57PM +0300, Emmanuel Grumbach wrote:
> This small patch series enables 7260 and 3160 devices on 3.10
> kernel. Three patches are already in linux.git (3.11-rc1).
> One patch is 3.10 specific and disables configuration that is not
> supported in 3.10.
I need the git commit id of these patches in Linus's tree before I can
apply them. Please resend them with that information.
thanks,
greg k-h
^ permalink raw reply
* Re: changing dev->needed_headroom/needed_tailroom?
From: Ben Hutchings @ 2013-08-02 8:55 UTC (permalink / raw)
To: Johannes Berg; +Cc: netdev, linux-wireless
In-Reply-To: <1374850210.8248.59.camel@jlt4.sipsolutions.net>
On Fri, 2013-07-26 at 16:50 +0200, Johannes Berg wrote:
> Does it seem reasonable to change dev->needed_headroom and
> dev->needed_tailroom on the fly?
>
> We currently set needed_headroom to the max of what we need, but we
> could do better like making it depend on the interface type (e.g. only
> asking for mesh space on mesh interfaces). This would be done only when
> the interface isn't connected, I can't promise it would be down but the
> carrier would be off.
[...]
I don't think this is safe when the interface is running (even if
carrier is off). Some functions may read dev->needed_headroom twice and
rely on getting the same value each time.
Also, stacked devices would need to adjust their own needed_headroom
accordingly.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Question about iwl_pcie_rxq_inc_wr_ptr
From: Stanislaw Gruszka @ 2013-08-02 8:42 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
I would like to ask if below change is safe (I'm considering to do
that change on iwlegacy):
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 567e67a..1ebdb83 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -183,7 +183,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q)
} else {
/* Device expects a multiple of 8 */
q->write_actual = (q->write & ~0x7);
- iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR,
+ iwl_write32(trans, FH_RSCSR_CHNL0_WPTR,
q->write_actual);
}
}
This register seems to be only read by firmware, so maybe we can modify
it without grab nic access. We are doing that on
iwl_pcie_txq_inc_wr_ptr().
Stanislaw
^ permalink raw reply related
* Re: [PATCH v2] ath10k: fix device teardown
From: Kalle Valo @ 2013-08-02 8:00 UTC (permalink / raw)
To: Michal Kazior; +Cc: ath10k, linux-wireless
In-Reply-To: <CA+BoTQktaDtp=fc3C_u4geA6vK72B1X4QnsD_GqrzU9NXEmBrA@mail.gmail.com>
Michal Kazior <michal.kazior@tieto.com> writes:
> On 2 August 2013 09:41, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
>> Michal Kazior <michal.kazior@tieto.com> writes:
>>
>>> @@ -1742,6 +1761,12 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
>>> {
>>> int ret;
>>>
>>> + ret = ath10k_pci_start_intr(ar);
>>> + if (ret) {
>>> + ath10k_err("could not start interrupt handling (%d)\n", ret);
>>> + goto err;
>>> + }
>>
>> So now we call start_intr() during power_up(), which means that we do
>> the request_irq() calls during every interface up event. Does that cause
>> any meaningful overhead?
>
> I don't think so.
Good.
>> For me it looks better to do all resource allocation in
>> ath10k_pci_probe(), like request_irq(), and free the resources in
>> ath10k_pci_remove(). But then we would need to immeadiately call
>> disable_irq() and then enable_irq() from power_up() so I'm not sure if
>> that's any better.
>
> Not only that. Since disable/enable_irq must be balanced we'd need
> some way to track whether we have irqs enabled/disabled - either with
> an extra bool variable, additional ath10k_states or new pci-specific
> states.
>
> The patch assumes disable_irq is followed by free_irq (which it is)
> and possibly request_irq later on.
Yeah, your v2 sounds much better. And if there's overhead or something
else we can always change this later.
I'll wait for comments from others and if I don't get any, I'll apply
this.
--
Kalle Valo
^ permalink raw reply
* [PATCH v2] ath10k: add SoC power save option to PCI features map
From: Bartosz Markowski @ 2013-08-02 7:58 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Bartosz Markowski
Unify the PCI options location.
By default the SoC PS option is disabled to boost the
performance and due to poor stability on early HW revisions.
In future we can remove the module parameter and turn on/off
the PS for given hardware.
This change also makes the pci module parameter for SoC PS static.
Signed-off-by: Bartosz Markowski <bartosz.markowski@tieto.com>
---
drivers/net/wireless/ath/ath10k/pci.c | 21 +++++++++++++--------
drivers/net/wireless/ath/ath10k/pci.h | 11 +++++++----
2 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index d95439b..b351e23 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -32,7 +32,7 @@
#include "ce.h"
#include "pci.h"
-unsigned int ath10k_target_ps;
+static unsigned int ath10k_target_ps;
module_param(ath10k_target_ps, uint, 0644);
MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option");
@@ -1740,6 +1740,7 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
static int ath10k_pci_hif_power_up(struct ath10k *ar)
{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
/*
@@ -1758,13 +1759,9 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
if (ret)
goto err;
- if (ath10k_target_ps) {
- ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
- } else {
+ if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
/* Force AWAKE forever */
- ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n");
ath10k_do_pci_wake(ar);
- }
ret = ath10k_pci_ce_init(ar);
if (ret)
@@ -1785,7 +1782,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
err_ce:
ath10k_pci_ce_deinit(ar);
err_ps:
- if (!ath10k_target_ps)
+ if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
ath10k_do_pci_sleep(ar);
err:
return ret;
@@ -1793,8 +1790,10 @@ err:
static void ath10k_pci_hif_power_down(struct ath10k *ar)
{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
ath10k_pci_ce_deinit(ar);
- if (!ath10k_target_ps)
+ if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
ath10k_do_pci_sleep(ar);
}
@@ -2244,6 +2243,9 @@ static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
case ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND:
ath10k_dbg(ATH10K_DBG_PCI, "QCA988X_1.0 workaround enabled\n");
break;
+ case ATH10K_PCI_FEATURE_SOC_POWER_SAVE:
+ ath10k_dbg(ATH10K_DBG_PCI, "QCA98XX SoC power save enabled\n");
+ break;
}
}
}
@@ -2279,6 +2281,9 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_ar_pci;
}
+ if (ath10k_target_ps)
+ set_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features);
+
ath10k_pci_dump_features(ar_pci);
ar = ath10k_core_create(ar_pci, ar_pci->dev, &ath10k_pci_hif_ops);
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index d3a2e6c..871bb33 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -153,6 +153,7 @@ struct service_to_pipe {
enum ath10k_pci_features {
ATH10K_PCI_FEATURE_MSI_X = 0,
ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND = 1,
+ ATH10K_PCI_FEATURE_SOC_POWER_SAVE = 2,
/* keep last */
ATH10K_PCI_FEATURE_COUNT
@@ -335,20 +336,22 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
return ioread32(ar_pci->mem + offset);
}
-extern unsigned int ath10k_target_ps;
-
void ath10k_do_pci_wake(struct ath10k *ar);
void ath10k_do_pci_sleep(struct ath10k *ar);
static inline void ath10k_pci_wake(struct ath10k *ar)
{
- if (ath10k_target_ps)
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+ if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
ath10k_do_pci_wake(ar);
}
static inline void ath10k_pci_sleep(struct ath10k *ar)
{
- if (ath10k_target_ps)
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+ if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
ath10k_do_pci_sleep(ar);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH] ath10k: remove un ar_pci->cacheline_sz field
From: Kalle Valo @ 2013-08-02 7:56 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless
cacheline_sz is not used anywhere and can be removed.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/pci.c | 2 --
drivers/net/wireless/ath/ath10k/pci.h | 1 -
2 files changed, 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index d95439b..6f44d3a 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -2361,8 +2361,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
spin_lock_init(&ar_pci->ce_lock);
- ar_pci->cacheline_sz = dma_get_cache_alignment();
-
ret = ath10k_pci_start_intr(ar);
if (ret) {
ath10k_err("could not start interrupt handling (%d)\n", ret);
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index d3a2e6c..bfd60a5 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -189,7 +189,6 @@ struct ath10k_pci {
struct device *dev;
struct ath10k *ar;
void __iomem *mem;
- int cacheline_sz;
DECLARE_BITMAP(features, ATH10K_PCI_FEATURE_COUNT);
^ permalink raw reply related
* Re: [PATCH v2] ath10k: fix device teardown
From: Michal Kazior @ 2013-08-02 7:51 UTC (permalink / raw)
To: Kalle Valo; +Cc: ath10k, linux-wireless
In-Reply-To: <87bo5gpmij.fsf@kamboji.qca.qualcomm.com>
On 2 August 2013 09:41, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior@tieto.com> writes:
>
>> This fixes interrupt-related issue when no
>> interfaces were running thus the device was
>> considered powered down.
>>
>> The power_down() function isn't really powering
>> down the device. It simply assumed it won't
>> interrupt. This wasn't true in some cases and
>> could lead to paging failures upon FW indication
>> interrupt (i.e. FW crash) because some structures
>> aren't allocated in that device state.
>>
>> One reason for that was that ar_pci->started
>> wasn't reset. The other is interrupts should've
>> been masked when teardown starts.
>>
>> The patch reorganized interrupt setup and makes
>> sure ar_pci->started is reset accordingly.
>>
>> Reported-by: Ben Greear <greearb@candelatech.com>
>> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
>> ---
>> v2:
>> * updated commit message
>> * added Reported-By: Ben
>> * added disable_irq() in hif_stop()
>> * added ar_pci->started resetting
>> * removed ar_pci->intr_started
>
> Thanks, this looks much better now.
>
> But I still have one question:
>
>> @@ -1742,6 +1761,12 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
>> {
>> int ret;
>>
>> + ret = ath10k_pci_start_intr(ar);
>> + if (ret) {
>> + ath10k_err("could not start interrupt handling (%d)\n", ret);
>> + goto err;
>> + }
>
> So now we call start_intr() during power_up(), which means that we do
> the request_irq() calls during every interface up event. Does that cause
> any meaningful overhead?
I don't think so.
> For me it looks better to do all resource allocation in
> ath10k_pci_probe(), like request_irq(), and free the resources in
> ath10k_pci_remove(). But then we would need to immeadiately call
> disable_irq() and then enable_irq() from power_up() so I'm not sure if
> that's any better.
Not only that. Since disable/enable_irq must be balanced we'd need
some way to track whether we have irqs enabled/disabled - either with
an extra bool variable, additional ath10k_states or new pci-specific
states.
The patch assumes disable_irq is followed by free_irq (which it is)
and possibly request_irq later on.
Pozdrawiam / Best regards,
Michał Kazior.
^ permalink raw reply
* Re: Skb and ieee80211 headers
From: Mathieu Devos @ 2013-08-02 7:49 UTC (permalink / raw)
To: Arend van Spriel; +Cc: linux-wireless
In-Reply-To: <CAE_+Soydmjwp=gXxc74R3BGczbU7OKF2U3hehBi3kqGaEv_pwg@mail.gmail.com>
Hi,
An update is in order here I believe (and an apology because I
resorted to asking my questions on IRC and not sticking to the mailing
list, for that: sorry).
Let's start things off quickly with my main goal with this: the code
that I'm trying to write is supposed to be an adapter for a new type
of internet (RINA), this is in function of my master thesis (I'm new
to Linux Kernel itself). So what exactly does this mean? I'd like to
be able to hook packets (skb) in the kernel with an LKM and just use
one layer (datalink layer) with the hardware layer being handled by
the drivers and the hardware itself. Everything on top of that should
be RINA specific code.
The specifics about the master thesis is that this all should be done
on android, thus using the wireless stack. I believed that in an
skbuff you had the formed 802.3 header through drivers but you still
also had the original 802.11 header, this however, is now proven
wrong, the 802.11 header is thrown out after the drivers are done with
it thus it's impossible for me to map RINA to the 802.11 header. After
resuming testing with this news I'm still left with a couple of
questions however:
- Can I still use the added functionality of 802.11 as compared to
802.3 by talking directly to the device and setting it's fields? I'm
thinking of using "struct wireless_device" and/or "struct wiphy" and
the functions that come with it.
- Is it possible to find a general form of skb frame with correctly
set headers? I have currently tested my code
(https://github.com/mathieudevos/kernelmodules/blob/master/ethernet_test.c)
and on one android device (galaxy S2 I9100, BCM4330 wireless chip) I
had my 802.3 header by at my skb->head. On my own htc one X (htc
endeavoru, wireless chip unknown still) I had my 802.3 header at my
skb->mac_header and on my notebook (wireless 5100 AGN) this header was
present on skb->data. Is it coincidence that these 3 are totally
different and is there a function (that perhaps calls the drivers) to
set these skb's in the correct prepared form? And if so, will this
break when I void the layers on top of the mac layer.
While I know that a part of this still needs to be researched, for
instance say it's possible to set certain fields of the device to use
added 802.11 functionality I won't be setting the channel manually,
that's still left to the driver, but other added functions might be
more useful for RINA.
What I'm hoping to achieve before really heading off into this new
linux adventure is to be able to properly receive an SKB that has the
same format on my devices and later down the road try to send set up
an SKB and send that one myself.
I'd like to finish with another apology for not sticking to the
mailing list, for that I'm truly sorry.
Kind regards,
Mathieu Devos
On Wed, Jul 31, 2013 at 5:11 PM, Mathieu Devos <mathieu.devos@ugent.be> wrote:
> This is my hook: it gets called after I set dev to wlan0. I used a
> guide for this and it seems to work for my notebook where I'm able to
> find the 802.3 header but still no 802.11.
>
> static int ptype_function(struct sk_buff *skb, struct net_device *dev,
> struct packet_type *ptype, struct net_device *dev2);
>
> static void throw_hook(struct net_device *dev){
> ptype.type = htons(ETH_P_ALL);
> ptype.func = &ptype_function;
> ptype.dev = dev;
> dev_add_pack(&ptype);
> printk(KERN_CRIT "Done setting up packet type");
> }
>
> All code can be found here:
> android: https://github.com/mathieudevos/kernelmodules/blob/master/ethernet_test.c
> notebook: https://github.com/mathieudevos/wifi_kernelmodules/blob/master/ethernet_test.c
>
> Kind regards,
> Mathieu Devos
>
> On Wed, Jul 31, 2013 at 5:04 PM, Arend van Spriel <arend@broadcom.com> wrote:
>> On 07/31/2013 03:45 PM, Mathieu Devos wrote:
>>>
>>> Alright,
>>>
>>> Seems like I have fixed some issues while added some others. Since I
>>> assume that when my hook gets activated the data pointer should be at
>>> the start of the 802.3 header I casted an ethhdr (8023) on top of that
>>> and it seems that on my notebook this is handled correctly (I can
>>> actually check on my own mac addr and see that these frames are
>>> for/from me).
>>
>>
>> How does your hook work? Are you intercepting packets?
>>
>> Regards,
>> Arend
>>
>>
>>> On Wed, Jul 31, 2013 at 2:55 PM, Arend van Spriel <arend@broadcom.com>
>>> wrote:
>>>>
>>>> On 07/31/2013 02:39 PM, Mathieu Devos wrote:
>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> The wireless chip is a Broadcast BCM4330 chip. After looking around a
>>>>> bit I found that this is a fullMAC and links to the driver on
>>>>> wireless.kernel: http://wireless.kernel.org/en/users/Drivers/brcm80211
>>>>> and also links directly to android itself:
>>>>> https://android.googlesource.com/platform/hardware/broadcom/wlan
>>>>
>>>>
>>>>
>>>> I suspected. The bcm4330 is indeed a fullmac device, which means the
>>>> 802.11
>>>> stack is running on the device. The driver on Android is located under:
>>>>
>>>>
>>>> https://android.googlesource.com/kernel/samsung/+/android-samsung-3.0-ics-mr1/drivers/net/wireless/bcmdhd/
>>>>
>>>> Not sure which android version you have.
>>>>
>>>> The brcm80211 on wireless.kernel.org is the upstream linux driver.
>>>>
>>>> Gr. AvS
>>>>
>>>>
>>>>> Still trying to learn a lot in this tightly packed world of protocol
>>>>> stacks, wireless and all the other poisons. Seems like I still have a
>>>>> long way to go. Thank you already for helping me out with these issues
>>>>> and taking the time to explain these things to me.
>>>>>
>>>>> Kind regards,
>>>>> Mathieu Devos
>>>>>
>>>>> On Wed, Jul 31, 2013 at 1:05 PM, Arend van Spriel <arend@broadcom.com>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> On 07/31/2013 12:28 PM, Mathieu Devos wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> It's an android smartphone (I 9100 - Samsung galaxy S2) so it does not
>>>>>>> have a normal ethernet 802.3 input even. I check before selecting the
>>>>>>> device that it's wireless (through ieee80211_ptr) and this properly
>>>>>>> returns the wlan0 device which should be on the 80211 standard.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> *sigh* Welcome in the world of protocol stacks, wireless, networking
>>>>>> (choose
>>>>>> your poison). Let me draw the picture.
>>>>>>
>>>>>> o user-space
>>>>>> |
>>>>>> ----------------------
>>>>>> | kernel
>>>>>> +-----------+
>>>>>> | NET | networking subsystem, ie. TCP/IP stack
>>>>>> +-----------+
>>>>>> | 802.3
>>>>>> +----------------+
>>>>>> | | driver |
>>>>>> | +------------+ |
>>>>>> | |802.11 stack| |
>>>>>> | +------------+ |
>>>>>> | | 802.11 |
>>>>>> +----------------+
>>>>>> |
>>>>>> o RF
>>>>>>
>>>>>> The device hooks up to the networking subsystem as an ethernet device
>>>>>> and
>>>>>> as
>>>>>> such it receives 802.3 packets. These are converted to 802.11 packets
>>>>>> by
>>>>>> the
>>>>>> 802.11 stack. Now depending on your device that happens in the device
>>>>>> driver
>>>>>> or on the device itself. Another option is that this is done by
>>>>>> mac80211
>>>>>> (kernel provided 802.11 stack), but that is probably not the case, but
>>>>>> to
>>>>>> be
>>>>>> sure I ask again: what wireless device do you have in your galaxy S2?
>>>>>>
>>>>>> Gr. AvS
>>>>>>
>>>>>>
>>>>>>> My goal is to get the ieee80211_header properly on the skb with this
>>>>>>> device, but some of the pointers and original data in the skb seem
>>>>>>> totally off. This leaves me clueless as to where to put this
>>>>>>> ieee80211_header.
>>>>>>> I've tried putting it right on skb->head (wrong I know, but I was
>>>>>>> getting desperate), on skb->mac_header (also wrong, no idea why
>>>>>>> though), I went back from skb->tail with len and even added ETH_HLEN
>>>>>>> to that as well because you can see that before my hook gets
>>>>>>> activated: skb_pull_inline(skb, ETH_HLEN);
>>>>>>> In the end I'm left with a header that is forced onto data but with a
>>>>>>> wrong origin pointer thus basically leaving me with all wrong data in
>>>>>>> the header.
>>>>>>>
>>>>>>> Kind regards,
>>>>>>> Mathieu Devos
>>>>>>>
>>>>>>> On Wed, Jul 31, 2013 at 12:08 PM, Arend van Spriel
>>>>>>> <arend@broadcom.com>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 07/31/2013 11:39 AM, Mathieu Devos wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I hope this is the right place to ask for a little bit of help as
>>>>>>>>> I'm
>>>>>>>>> currently beyond stuck on a challenge I'm trying to accomplish. I'm
>>>>>>>>> trying to write a "simple" LKM that properly uses a ieee80211 header
>>>>>>>>> to print information about the mac addresses (addr1->addr4) and
>>>>>>>>> later
>>>>>>>>> down the road try to send my own data.
>>>>>>>>>
>>>>>>>>> I only need to get L2 working, no need for TCP/IP, just a proper
>>>>>>>>> ieee80211 based on input from skb would be huge for me.
>>>>>>>>>
>>>>>>>>> So my issue: when placing the ieee80211 on my mac_header after I
>>>>>>>>> hook
>>>>>>>>> my skb from my wireless device (wlan0 on android - I9100)
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Not sure what you goal is, but what wireless device is that? You may
>>>>>>>> just
>>>>>>>> get 802.3 packets from the device.
>>>>>>>>
>>>>>>>> Gr. AvS
>>>>>>>>
>>>>>>>>
>>>>>>>>> I get a huge
>>>>>>>>> amount of zero's and random(?) numbers when trying to print the
>>>>>>>>> addresses. This leads me to the first conclusion that mac_header is
>>>>>>>>> placed wrong when using 80211. After that I saw a lot of people just
>>>>>>>>> using the skb->data pointer. Now this gives even weirder issues for
>>>>>>>>> me
>>>>>>>>> and actually totally crashes my kernel.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>
>>
>>
^ permalink raw reply
* Re: [PATCH] ath10k: add SoC power save option to PCI features map
From: Kalle Valo @ 2013-08-02 7:47 UTC (permalink / raw)
To: Bartosz Markowski; +Cc: ath10k, linux-wireless
In-Reply-To: <1375348187-18216-1-git-send-email-bartosz.markowski@tieto.com>
Bartosz Markowski <bartosz.markowski@tieto.com> writes:
> Unify the PCI options location.
>
> By default the SoC PS option is disabled to boost the
> performance and due to poor stability on early HW revisions.
> In future we can remove the module parameter and turn on/off
> the PS for given hardware.
>
> This change also makes the pci module parameter for SoC PS static.
>
> Signed-off-by: Bartosz Markowski <bartosz.markowski@tieto.com>
A minor nitpick:
> + if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
> + ath10k_do_pci_wake(ar); /* Force AWAKE forever */
if (foo)
/* comment */
function_call();
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v2] ath10k: fix device teardown
From: Kalle Valo @ 2013-08-02 7:41 UTC (permalink / raw)
To: Michal Kazior; +Cc: ath10k, linux-wireless
In-Reply-To: <1375427747-9539-1-git-send-email-michal.kazior@tieto.com>
Michal Kazior <michal.kazior@tieto.com> writes:
> This fixes interrupt-related issue when no
> interfaces were running thus the device was
> considered powered down.
>
> The power_down() function isn't really powering
> down the device. It simply assumed it won't
> interrupt. This wasn't true in some cases and
> could lead to paging failures upon FW indication
> interrupt (i.e. FW crash) because some structures
> aren't allocated in that device state.
>
> One reason for that was that ar_pci->started
> wasn't reset. The other is interrupts should've
> been masked when teardown starts.
>
> The patch reorganized interrupt setup and makes
> sure ar_pci->started is reset accordingly.
>
> Reported-by: Ben Greear <greearb@candelatech.com>
> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
> ---
> v2:
> * updated commit message
> * added Reported-By: Ben
> * added disable_irq() in hif_stop()
> * added ar_pci->started resetting
> * removed ar_pci->intr_started
Thanks, this looks much better now.
But I still have one question:
> @@ -1742,6 +1761,12 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
> {
> int ret;
>
> + ret = ath10k_pci_start_intr(ar);
> + if (ret) {
> + ath10k_err("could not start interrupt handling (%d)\n", ret);
> + goto err;
> + }
So now we call start_intr() during power_up(), which means that we do
the request_irq() calls during every interface up event. Does that cause
any meaningful overhead?
For me it looks better to do all resource allocation in
ath10k_pci_probe(), like request_irq(), and free the resources in
ath10k_pci_remove(). But then we would need to immeadiately call
disable_irq() and then enable_irq() from power_up() so I'm not sure if
that's any better.
--
Kalle Valo
^ permalink raw reply
* Re: [3.11 regression?] iwlwifi firmware takes two minutes to load
From: Johannes Berg @ 2013-08-02 7:38 UTC (permalink / raw)
To: Andy Lutomirski; +Cc: Linux Wireless List, Intel Linux Wireless
In-Reply-To: <CALCETrW6BrCFHjALQVexUy61=f5QXOjiHhvRNGqnN--iZei+RQ@mail.gmail.com>
On Thu, 2013-08-01 at 21:38 -0700, Andy Lutomirski wrote:
> At boot, I get:
> [ 12.537108] iwlwifi 0000:03:00.0: irq 51 for MSI/MSI-X
> ...
> [ 132.676781] iwlwifi 0000:03:00.0: loaded firmware version 9.221.4.1
> build 25532 op_mode iwldvm
>
> This sounds familiar, but wasn't it fixed awhile ago?
It wasn't exactly fixed and it's really more of a userspace problem - we
probably request firmware version 8, and then it takes 30 seconds to
time out for each of 8,7,6,5, after which the next request for 4 is
successful.
I don't know why your userspace isn't behaving differently though.
johannes
^ permalink raw reply
* [PATCH v2] ath10k: fix device teardown
From: Michal Kazior @ 2013-08-02 7:15 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1374129572-6079-1-git-send-email-michal.kazior@tieto.com>
This fixes interrupt-related issue when no
interfaces were running thus the device was
considered powered down.
The power_down() function isn't really powering
down the device. It simply assumed it won't
interrupt. This wasn't true in some cases and
could lead to paging failures upon FW indication
interrupt (i.e. FW crash) because some structures
aren't allocated in that device state.
One reason for that was that ar_pci->started
wasn't reset. The other is interrupts should've
been masked when teardown starts.
The patch reorganized interrupt setup and makes
sure ar_pci->started is reset accordingly.
Reported-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
v2:
* updated commit message
* added Reported-By: Ben
* added disable_irq() in hif_stop()
* added ar_pci->started resetting
* removed ar_pci->intr_started
drivers/net/wireless/ath/ath10k/pci.c | 41 ++++++++++++++++++++++++---------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index c71b488..690a8b4 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -56,6 +56,8 @@ static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info);
static void ath10k_pci_stop_ce(struct ath10k *ar);
static void ath10k_pci_device_reset(struct ath10k *ar);
static int ath10k_pci_reset_target(struct ath10k *ar);
+static int ath10k_pci_start_intr(struct ath10k *ar);
+static void ath10k_pci_stop_intr(struct ath10k *ar);
static const struct ce_attr host_ce_config_wlan[] = {
/* host->target HTC control and raw streams */
@@ -1254,10 +1256,25 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar)
}
}
+static void ath10k_pci_disable_irqs(struct ath10k *ar)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ int i;
+
+ for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
+ disable_irq(ar_pci->pdev->irq + i);
+}
+
static void ath10k_pci_hif_stop(struct ath10k *ar)
{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__);
+ /* Irqs are never explicitly re-enabled. They are implicitly re-enabled
+ * by ath10k_pci_start_intr(). */
+ ath10k_pci_disable_irqs(ar);
+
ath10k_pci_stop_ce(ar);
/* At this point, asynchronous threads are stopped, the target should
@@ -1267,6 +1284,8 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
ath10k_pci_process_ce(ar);
ath10k_pci_cleanup_ce(ar);
ath10k_pci_buffer_cleanup(ar);
+
+ ar_pci->started = 0;
}
static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
@@ -1742,6 +1761,12 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
{
int ret;
+ ret = ath10k_pci_start_intr(ar);
+ if (ret) {
+ ath10k_err("could not start interrupt handling (%d)\n", ret);
+ goto err;
+ }
+
/*
* Bring the target up cleanly.
*
@@ -1756,7 +1781,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
ret = ath10k_pci_reset_target(ar);
if (ret)
- goto err;
+ goto err_irq;
if (ath10k_target_ps) {
ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
@@ -1787,12 +1812,15 @@ err_ce:
err_ps:
if (!ath10k_target_ps)
ath10k_do_pci_sleep(ar);
+err_irq:
+ ath10k_pci_stop_intr(ar);
err:
return ret;
}
static void ath10k_pci_hif_power_down(struct ath10k *ar)
{
+ ath10k_pci_stop_intr(ar);
ath10k_pci_ce_deinit(ar);
if (!ath10k_target_ps)
ath10k_do_pci_sleep(ar);
@@ -2358,22 +2386,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
ar_pci->cacheline_sz = dma_get_cache_alignment();
- ret = ath10k_pci_start_intr(ar);
- if (ret) {
- ath10k_err("could not start interrupt handling (%d)\n", ret);
- goto err_iomap;
- }
-
ret = ath10k_core_register(ar);
if (ret) {
ath10k_err("could not register driver core (%d)\n", ret);
- goto err_intr;
+ goto err_iomap;
}
return 0;
-err_intr:
- ath10k_pci_stop_intr(ar);
err_iomap:
pci_iounmap(pdev, mem);
err_master:
@@ -2410,7 +2430,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
tasklet_kill(&ar_pci->msi_fw_err);
ath10k_core_unregister(ar);
- ath10k_pci_stop_intr(ar);
pci_set_drvdata(pdev, NULL);
pci_iounmap(pdev, ar_pci->mem);
--
1.7.9.5
^ 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