* [PATCH 1/2] mac80211: add offload channel switch support
@ 2010-05-06 3:34 wey-yi.w.guy
2010-05-06 3:34 ` [PATCH 2/2] mac80211: check channel switch mode for future frames transmit wey-yi.w.guy
2010-05-06 7:44 ` [PATCH 1/2] mac80211: add offload channel switch support Johannes Berg
0 siblings, 2 replies; 4+ messages in thread
From: wey-yi.w.guy @ 2010-05-06 3:34 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Wey-Yi Guy
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Adding support to offload the channel switch operation to driver if
driver can support the function.
The original approach, mac80211 utilize the mac_config callback function
and set the CHANNEL_CHANGE flag which is difficult to separate the true
channel switch request from all the other channel changes condition;
with this offload approach, driver has more control on how to handle the
channel switch request from AP, also can provide more accurate timing
calculation
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
include/net/mac80211.h | 32 ++++++++++++++++++++++++++
net/mac80211/driver-ops.h | 11 +++++++++
net/mac80211/driver-trace.h | 49 +++++++++++++++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 3 +-
net/mac80211/mlme.c | 53 +++++++++++++++++++++++++++++++++++++++---
5 files changed, 143 insertions(+), 5 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2879c8e..dc5ae23 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -708,6 +708,26 @@ struct ieee80211_conf {
};
/**
+ * struct ieee80211_channel_switch - holds the channel switch data
+ *
+ * The information provided in this structure is required for channel switch
+ * operation.
+ *
+ * @timestamp: value in microseconds of the 64-bit Time Synchronization
+ * Function (TSF) timer when the channel switch ie received.
+ * @block_tx: set to true if no more future frames transmission within the BSS
+ * until the scheduled channel switch
+ * @channel: pointer to ieee80211_channel contain then new channel information
+ * @count: specified the number of TBTT's until the channel switch event.
+ */
+struct ieee80211_channel_switch {
+ u64 timestamp;
+ bool block_tx;
+ struct ieee80211_channel *channel;
+ u8 count;
+};
+
+/**
* struct ieee80211_vif - per-interface data
*
* Data in this structure is continually present for driver
@@ -1694,6 +1714,8 @@ struct ieee80211_ops {
int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
#endif
void (*flush)(struct ieee80211_hw *hw, bool drop);
+ void (*channel_switch)(struct ieee80211_hw *hw,
+ struct ieee80211_channel_switch *ch_switch);
};
/**
@@ -2444,6 +2466,16 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
enum nl80211_cqm_rssi_threshold_event rssi_event,
gfp_t gfp);
+/**
+ * ieee80211_chswitch_done - Complete channel switch process
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @is_seccess: make the channel switch successful or not
+ *
+ * Complete the channel switch post-process: set the new operational channel
+ * and wake up the suspended queues.
+ */
+void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool is_success);
+
/* Rate control API */
/**
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 997008e..5662bb5 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -373,4 +373,15 @@ static inline void drv_flush(struct ieee80211_local *local, bool drop)
if (local->ops->flush)
local->ops->flush(&local->hw, drop);
}
+
+static inline void drv_channel_switch(struct ieee80211_local *local,
+ struct ieee80211_channel_switch *ch_switch)
+{
+ might_sleep();
+
+ local->ops->channel_switch(&local->hw, ch_switch);
+
+ trace_drv_channel_switch(local, ch_switch);
+}
+
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index ce734b5..cd1ae9f 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -774,6 +774,34 @@ TRACE_EVENT(drv_flush,
)
);
+TRACE_EVENT(drv_channel_switch,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_channel_switch *ch_switch),
+
+ TP_ARGS(local, ch_switch),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u64, timestamp)
+ __field(bool, block_tx)
+ __field(u16, freq)
+ __field(u8, count)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->timestamp = ch_switch->timestamp;
+ __entry->block_tx = ch_switch->block_tx;
+ __entry->freq = ch_switch->channel->center_freq;
+ __entry->count = ch_switch->count;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " new freq:%u count:%d",
+ LOCAL_PR_ARG, __entry->freq, __entry->count
+ )
+);
+
/*
* Tracing for API calls that drivers call.
*/
@@ -992,6 +1020,27 @@ TRACE_EVENT(api_sta_block_awake,
)
);
+TRACE_EVENT(api_chswitch_done,
+ TP_PROTO(struct ieee80211_sub_if_data *sdata, bool is_success),
+
+ TP_ARGS(sdata, is_success),
+
+ TP_STRUCT__entry(
+ VIF_ENTRY
+ __field(bool, is_success)
+ ),
+
+ TP_fast_assign(
+ VIF_ASSIGN;
+ __entry->is_success = is_success;
+ ),
+
+ TP_printk(
+ VIF_PR_FMT " chswitch:%d",
+ VIF_PR_ARG, __entry->is_success
+ )
+);
+
/*
* Tracing for internal functions
* (which may also be called in response to driver calls)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4e73660..be9dda9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -999,7 +999,8 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
unsigned long data, void *dummy);
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel_sw_ie *sw_elem,
- struct ieee80211_bss *bss);
+ struct ieee80211_bss *bss,
+ u64 timestamp);
void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 358226f..f50d73f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -340,7 +340,11 @@ static void ieee80211_chswitch_work(struct work_struct *work)
goto out;
sdata->local->oper_channel = sdata->local->csa_channel;
- ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);
+ if (!sdata->local->ops->channel_switch) {
+ /* call "hw_config" only if doing sw channel switch */
+ ieee80211_hw_config(sdata->local,
+ IEEE80211_CONF_CHANGE_CHANNEL);
+ }
/* XXX: shouldn't really modify cfg80211-owned data! */
ifmgd->associated->channel = sdata->local->oper_channel;
@@ -352,6 +356,22 @@ static void ieee80211_chswitch_work(struct work_struct *work)
mutex_unlock(&ifmgd->mtx);
}
+void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool is_success)
+{
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_if_managed *ifmgd;
+
+ sdata = vif_to_sdata(vif);
+ ifmgd = &sdata->u.mgd;
+
+ trace_api_chswitch_done(sdata, is_success);
+ if (!is_success)
+ sdata->local->csa_channel = sdata->local->oper_channel;
+
+ ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
+}
+EXPORT_SYMBOL(ieee80211_chswitch_done);
+
static void ieee80211_chswitch_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
@@ -368,7 +388,8 @@ static void ieee80211_chswitch_timer(unsigned long data)
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel_sw_ie *sw_elem,
- struct ieee80211_bss *bss)
+ struct ieee80211_bss *bss,
+ u64 timestamp)
{
struct cfg80211_bss *cbss =
container_of((void *)bss, struct cfg80211_bss, priv);
@@ -396,6 +417,23 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
sdata->local->csa_channel = new_ch;
+ if (sdata->local->ops->channel_switch) {
+ /* use driver's channel switch callback */
+ struct ieee80211_channel_switch ch_switch;
+ memset(&ch_switch, 0, sizeof(ch_switch));
+ ch_switch.timestamp = timestamp;
+ if (sw_elem->mode) {
+ ch_switch.block_tx = true;
+ ieee80211_stop_queues_by_reason(&sdata->local->hw,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
+ }
+ ch_switch.channel = new_ch;
+ ch_switch.count = sw_elem->count;
+ ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
+ drv_channel_switch(sdata->local, &ch_switch);
+ return;
+ }
+ /* mac80211 handle channel switch */
if (sw_elem->count <= 1) {
ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
} else {
@@ -1279,6 +1317,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_bss *bss;
struct ieee80211_channel *channel;
bool need_ps = false;
+ u64 timestamp;
if (sdata->u.mgd.associated) {
bss = (void *)sdata->u.mgd.associated->priv;
@@ -1315,7 +1354,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
ETH_ALEN) == 0)) {
struct ieee80211_channel_sw_ie *sw_elem =
(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
- ieee80211_sta_process_chanswitch(sdata, sw_elem, bss);
+ if (beacon)
+ timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+ else
+ timestamp = le64_to_cpu(mgmt->u.probe_resp.timestamp);
+ ieee80211_sta_process_chanswitch(sdata, sw_elem,
+ bss, timestamp);
}
}
@@ -1647,7 +1691,8 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_process_chanswitch(sdata,
&mgmt->u.action.u.chan_switch.sw_elem,
- (void *)ifmgd->associated->priv);
+ (void *)ifmgd->associated->priv,
+ rx_status->mactime);
break;
}
mutex_unlock(&ifmgd->mtx);
--
1.5.6.3
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] mac80211: check channel switch mode for future frames transmit
2010-05-06 3:34 [PATCH 1/2] mac80211: add offload channel switch support wey-yi.w.guy
@ 2010-05-06 3:34 ` wey-yi.w.guy
2010-05-06 7:44 ` [PATCH 1/2] mac80211: add offload channel switch support Johannes Berg
1 sibling, 0 replies; 4+ messages in thread
From: wey-yi.w.guy @ 2010-05-06 3:34 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Wey-Yi Guy
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Check the mode in channel switch ie for either 0 or 1 on transmission.
A channel switch mode set to 1 means that the STA in a BSS to which the
frame containing the element is addressed shall transmit no further
frames within the BSS until the scheduled channel switch.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
net/mac80211/mlme.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f50d73f..ef98cac 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -437,7 +437,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
if (sw_elem->count <= 1) {
ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
} else {
- ieee80211_stop_queues_by_reason(&sdata->local->hw,
+ if (sw_elem->mode)
+ ieee80211_stop_queues_by_reason(&sdata->local->hw,
IEEE80211_QUEUE_STOP_REASON_CSA);
ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
mod_timer(&ifmgd->chswitch_timer,
--
1.5.6.3
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 1/2] mac80211: add offload channel switch support
2010-05-06 3:34 [PATCH 1/2] mac80211: add offload channel switch support wey-yi.w.guy
2010-05-06 3:34 ` [PATCH 2/2] mac80211: check channel switch mode for future frames transmit wey-yi.w.guy
@ 2010-05-06 7:44 ` Johannes Berg
2010-05-06 14:09 ` Guy, Wey-Yi W
1 sibling, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2010-05-06 7:44 UTC (permalink / raw)
To: wey-yi.w.guy; +Cc: linux-wireless
Sorry, just thought of something.
On Wed, 2010-05-05 at 20:34 -0700, wey-yi.w.guy@intel.com wrote:
> + * @timestamp: value in microseconds of the 64-bit Time Synchronization
> + * Function (TSF) timer when the channel switch ie received.
This is not accurate now but see below.
> + if (beacon)
> + timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
> + else
> + timestamp = le64_to_cpu(mgmt->u.probe_resp.timestamp);
> + ieee80211_sta_process_chanswitch(sdata, sw_elem,
> + bss, timestamp);
> }
> }
>
> @@ -1647,7 +1691,8 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
>
> ieee80211_sta_process_chanswitch(sdata,
> &mgmt->u.action.u.chan_switch.sw_elem,
> - (void *)ifmgd->associated->priv);
> + (void *)ifmgd->associated->priv,
> + rx_status->mactime);
For some reason I didn't notice the action frame handling before. Maybe
it would be more consistent to keep using rx_status->mactime even for
beacons? I apologise, this is totally my fault since I suggested using
the beacon time before, but that has a slightly different value relative
to the frame... Hmm. Maybe it would be better after all to require
drivers to provide mactime at least for mgmt frames (beacons + actions)
when they want to implement this callback.
Anyone else have ideas?
johannes
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH 1/2] mac80211: add offload channel switch support
2010-05-06 7:44 ` [PATCH 1/2] mac80211: add offload channel switch support Johannes Berg
@ 2010-05-06 14:09 ` Guy, Wey-Yi W
0 siblings, 0 replies; 4+ messages in thread
From: Guy, Wey-Yi W @ 2010-05-06 14:09 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
SGkgSm9oYW5uZXMsDQoNCi0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQpGcm9tOiBKb2hhbm5l
cyBCZXJnIFttYWlsdG86am9oYW5uZXNAc2lwc29sdXRpb25zLm5ldF0gDQpTZW50OiBUaHVyc2Rh
eSwgTWF5IDA2LCAyMDEwIDEyOjQ1IEFNDQpUbzogR3V5LCBXZXktWWkgVw0KQ2M6IGxpbnV4LXdp
cmVsZXNzQHZnZXIua2VybmVsLm9yZw0KU3ViamVjdDogUmU6IFtQQVRDSCAxLzJdIG1hYzgwMjEx
OiBhZGQgb2ZmbG9hZCBjaGFubmVsIHN3aXRjaCBzdXBwb3J0DQoNClNvcnJ5LCBqdXN0IHRob3Vn
aHQgb2Ygc29tZXRoaW5nLg0KDQpPbiBXZWQsIDIwMTAtMDUtMDUgYXQgMjA6MzQgLTA3MDAsIHdl
eS15aS53Lmd1eUBpbnRlbC5jb20gd3JvdGU6DQoNCj4gKyAqIEB0aW1lc3RhbXA6IHZhbHVlIGlu
IG1pY3Jvc2Vjb25kcyBvZiB0aGUgNjQtYml0IFRpbWUgU3luY2hyb25pemF0aW9uDQo+ICsgKglG
dW5jdGlvbiAoVFNGKSB0aW1lciB3aGVuIHRoZSBjaGFubmVsIHN3aXRjaCBpZSByZWNlaXZlZC4N
Cg0KVGhpcyBpcyBub3QgYWNjdXJhdGUgbm93IGJ1dCBzZWUgYmVsb3cuDQoNCj4gKwkJaWYgKGJl
YWNvbikNCj4gKwkJCXRpbWVzdGFtcCA9IGxlNjRfdG9fY3B1KG1nbXQtPnUuYmVhY29uLnRpbWVz
dGFtcCk7DQo+ICsJCWVsc2UNCj4gKwkJCXRpbWVzdGFtcCA9IGxlNjRfdG9fY3B1KG1nbXQtPnUu
cHJvYmVfcmVzcC50aW1lc3RhbXApOw0KPiArCQlpZWVlODAyMTFfc3RhX3Byb2Nlc3NfY2hhbnN3
aXRjaChzZGF0YSwgc3dfZWxlbSwNCj4gKwkJCQkJCSBic3MsIHRpbWVzdGFtcCk7DQo+ICAJfQ0K
PiAgfQ0KPiAgDQo+IEBAIC0xNjQ3LDcgKzE2OTEsOCBAQCBzdGF0aWMgdm9pZCBpZWVlODAyMTFf
c3RhX3J4X3F1ZXVlZF9tZ210KHN0cnVjdCBpZWVlODAyMTFfc3ViX2lmX2RhdGEgKnNkYXRhLA0K
PiAgDQo+ICAJCQlpZWVlODAyMTFfc3RhX3Byb2Nlc3NfY2hhbnN3aXRjaChzZGF0YSwNCj4gIAkJ
CQkJJm1nbXQtPnUuYWN0aW9uLnUuY2hhbl9zd2l0Y2guc3dfZWxlbSwNCj4gLQkJCQkJKHZvaWQg
KilpZm1nZC0+YXNzb2NpYXRlZC0+cHJpdik7DQo+ICsJCQkJCSh2b2lkICopaWZtZ2QtPmFzc29j
aWF0ZWQtPnByaXYsDQo+ICsJCQkJCXJ4X3N0YXR1cy0+bWFjdGltZSk7DQoNCkZvciBzb21lIHJl
YXNvbiBJIGRpZG4ndCBub3RpY2UgdGhlIGFjdGlvbiBmcmFtZSBoYW5kbGluZyBiZWZvcmUuIE1h
eWJlDQppdCB3b3VsZCBiZSBtb3JlIGNvbnNpc3RlbnQgdG8ga2VlcCB1c2luZyByeF9zdGF0dXMt
Pm1hY3RpbWUgZXZlbiBmb3INCmJlYWNvbnM/IEkgYXBvbG9naXNlLCB0aGlzIGlzIHRvdGFsbHkg
bXkgZmF1bHQgc2luY2UgSSBzdWdnZXN0ZWQgdXNpbmcNCnRoZSBiZWFjb24gdGltZSBiZWZvcmUs
IGJ1dCB0aGF0IGhhcyBhIHNsaWdodGx5IGRpZmZlcmVudCB2YWx1ZSByZWxhdGl2ZQ0KdG8gdGhl
IGZyYW1lLi4uIEhtbS4gTWF5YmUgaXQgd291bGQgYmUgYmV0dGVyIGFmdGVyIGFsbCB0byByZXF1
aXJlDQpkcml2ZXJzIHRvIHByb3ZpZGUgbWFjdGltZSBhdCBsZWFzdCBmb3IgbWdtdCBmcmFtZXMg
KGJlYWNvbnMgKyBhY3Rpb25zKQ0Kd2hlbiB0aGV5IHdhbnQgdG8gaW1wbGVtZW50IHRoaXMgY2Fs
bGJhY2suDQoNCkFueW9uZSBlbHNlIGhhdmUgaWRlYXM/DQoNCkl0IG1ha2VzIG1vcmUgc2Vuc2Ug
dG8gdXNlIG1hY3RpbWUsIHNvIGRyaXZlciBkbyBub3QgaGF2ZSB0byBwZWVrIGludG8gdGhlIGZy
YW1lIGJvZHkuIE5vdCBhIHByb2JsZW0sIEkgY2FuIG1ha2UgdGhlIGNoYW5nZXMgYW5kIHJlLXN1
Ym1pdC4NCg0KVGhhbmtzDQpXZXkNCg0K
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-05-06 14:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-06 3:34 [PATCH 1/2] mac80211: add offload channel switch support wey-yi.w.guy
2010-05-06 3:34 ` [PATCH 2/2] mac80211: check channel switch mode for future frames transmit wey-yi.w.guy
2010-05-06 7:44 ` [PATCH 1/2] mac80211: add offload channel switch support Johannes Berg
2010-05-06 14:09 ` Guy, Wey-Yi W
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox