diff options
author | Ilan Peer <ilan.peer@intel.com> | 2013-02-12 02:34:13 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-03-06 10:35:49 -0500 |
commit | d339d5ca8eee34f3c70386cf2545edc53e546a13 (patch) | |
tree | 30587aa1e41343adcf10b0716e54964410d86edf /net/mac80211 | |
parent | f62fab735e99af2190eba03f565adaca5c002882 (diff) |
mac80211: Allow drivers to differentiate between ROC types
Some devices can handle remain on channel requests differently
based on the request type/priority. Add support to
differentiate between different ROC types, i.e., indicate that
the ROC is required for sending managment frames.
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 21 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 7 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 2 | ||||
-rw-r--r-- | net/mac80211/trace.h | 11 |
5 files changed, 28 insertions, 14 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c115f82c037c..f9cbdc29946d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2410,7 +2410,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2410 | struct ieee80211_sub_if_data *sdata, | 2410 | struct ieee80211_sub_if_data *sdata, |
2411 | struct ieee80211_channel *channel, | 2411 | struct ieee80211_channel *channel, |
2412 | unsigned int duration, u64 *cookie, | 2412 | unsigned int duration, u64 *cookie, |
2413 | struct sk_buff *txskb) | 2413 | struct sk_buff *txskb, |
2414 | enum ieee80211_roc_type type) | ||
2414 | { | 2415 | { |
2415 | struct ieee80211_roc_work *roc, *tmp; | 2416 | struct ieee80211_roc_work *roc, *tmp; |
2416 | bool queued = false; | 2417 | bool queued = false; |
@@ -2429,6 +2430,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2429 | roc->duration = duration; | 2430 | roc->duration = duration; |
2430 | roc->req_duration = duration; | 2431 | roc->req_duration = duration; |
2431 | roc->frame = txskb; | 2432 | roc->frame = txskb; |
2433 | roc->type = type; | ||
2432 | roc->mgmt_tx_cookie = (unsigned long)txskb; | 2434 | roc->mgmt_tx_cookie = (unsigned long)txskb; |
2433 | roc->sdata = sdata; | 2435 | roc->sdata = sdata; |
2434 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); | 2436 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); |
@@ -2459,7 +2461,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2459 | if (!duration) | 2461 | if (!duration) |
2460 | duration = 10; | 2462 | duration = 10; |
2461 | 2463 | ||
2462 | ret = drv_remain_on_channel(local, sdata, channel, duration); | 2464 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); |
2463 | if (ret) { | 2465 | if (ret) { |
2464 | kfree(roc); | 2466 | kfree(roc); |
2465 | return ret; | 2467 | return ret; |
@@ -2478,10 +2480,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2478 | * | 2480 | * |
2479 | * If it hasn't started yet, just increase the duration | 2481 | * If it hasn't started yet, just increase the duration |
2480 | * and add the new one to the list of dependents. | 2482 | * and add the new one to the list of dependents. |
2483 | * If the type of the new ROC has higher priority, modify the | ||
2484 | * type of the previous one to match that of the new one. | ||
2481 | */ | 2485 | */ |
2482 | if (!tmp->started) { | 2486 | if (!tmp->started) { |
2483 | list_add_tail(&roc->list, &tmp->dependents); | 2487 | list_add_tail(&roc->list, &tmp->dependents); |
2484 | tmp->duration = max(tmp->duration, roc->duration); | 2488 | tmp->duration = max(tmp->duration, roc->duration); |
2489 | tmp->type = max(tmp->type, roc->type); | ||
2485 | queued = true; | 2490 | queued = true; |
2486 | break; | 2491 | break; |
2487 | } | 2492 | } |
@@ -2493,16 +2498,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2493 | /* | 2498 | /* |
2494 | * In the offloaded ROC case, if it hasn't begun, add | 2499 | * In the offloaded ROC case, if it hasn't begun, add |
2495 | * this new one to the dependent list to be handled | 2500 | * this new one to the dependent list to be handled |
2496 | * when the the master one begins. If it has begun, | 2501 | * when the master one begins. If it has begun, |
2497 | * check that there's still a minimum time left and | 2502 | * check that there's still a minimum time left and |
2498 | * if so, start this one, transmitting the frame, but | 2503 | * if so, start this one, transmitting the frame, but |
2499 | * add it to the list directly after this one with a | 2504 | * add it to the list directly after this one with |
2500 | * a reduced time so we'll ask the driver to execute | 2505 | * a reduced time so we'll ask the driver to execute |
2501 | * it right after finishing the previous one, in the | 2506 | * it right after finishing the previous one, in the |
2502 | * hope that it'll also be executed right afterwards, | 2507 | * hope that it'll also be executed right afterwards, |
2503 | * effectively extending the old one. | 2508 | * effectively extending the old one. |
2504 | * If there's no minimum time left, just add it to the | 2509 | * If there's no minimum time left, just add it to the |
2505 | * normal list. | 2510 | * normal list. |
2511 | * TODO: the ROC type is ignored here, assuming that it | ||
2512 | * is better to immediately use the current ROC. | ||
2506 | */ | 2513 | */ |
2507 | if (!tmp->hw_begun) { | 2514 | if (!tmp->hw_begun) { |
2508 | list_add_tail(&roc->list, &tmp->dependents); | 2515 | list_add_tail(&roc->list, &tmp->dependents); |
@@ -2596,7 +2603,8 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
2596 | 2603 | ||
2597 | mutex_lock(&local->mtx); | 2604 | mutex_lock(&local->mtx); |
2598 | ret = ieee80211_start_roc_work(local, sdata, chan, | 2605 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2599 | duration, cookie, NULL); | 2606 | duration, cookie, NULL, |
2607 | IEEE80211_ROC_TYPE_NORMAL); | ||
2600 | mutex_unlock(&local->mtx); | 2608 | mutex_unlock(&local->mtx); |
2601 | 2609 | ||
2602 | return ret; | 2610 | return ret; |
@@ -2829,7 +2837,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2829 | 2837 | ||
2830 | /* This will handle all kinds of coalescing and immediate TX */ | 2838 | /* This will handle all kinds of coalescing and immediate TX */ |
2831 | ret = ieee80211_start_roc_work(local, sdata, chan, | 2839 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2832 | wait, cookie, skb); | 2840 | wait, cookie, skb, |
2841 | IEEE80211_ROC_TYPE_MGMT_TX); | ||
2833 | if (ret) | 2842 | if (ret) |
2834 | kfree_skb(skb); | 2843 | kfree_skb(skb); |
2835 | out_unlock: | 2844 | out_unlock: |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index ee56d0779d8b..832acea4a5cb 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -787,15 +787,16 @@ static inline int drv_get_antenna(struct ieee80211_local *local, | |||
787 | static inline int drv_remain_on_channel(struct ieee80211_local *local, | 787 | static inline int drv_remain_on_channel(struct ieee80211_local *local, |
788 | struct ieee80211_sub_if_data *sdata, | 788 | struct ieee80211_sub_if_data *sdata, |
789 | struct ieee80211_channel *chan, | 789 | struct ieee80211_channel *chan, |
790 | unsigned int duration) | 790 | unsigned int duration, |
791 | enum ieee80211_roc_type type) | ||
791 | { | 792 | { |
792 | int ret; | 793 | int ret; |
793 | 794 | ||
794 | might_sleep(); | 795 | might_sleep(); |
795 | 796 | ||
796 | trace_drv_remain_on_channel(local, sdata, chan, duration); | 797 | trace_drv_remain_on_channel(local, sdata, chan, duration, type); |
797 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, | 798 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, |
798 | chan, duration); | 799 | chan, duration, type); |
799 | trace_drv_return_int(local, ret); | 800 | trace_drv_return_int(local, ret); |
800 | 801 | ||
801 | return ret; | 802 | return ret; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8da53a067306..2518f0429b87 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -315,6 +315,7 @@ struct ieee80211_roc_work { | |||
315 | u32 duration, req_duration; | 315 | u32 duration, req_duration; |
316 | struct sk_buff *frame; | 316 | struct sk_buff *frame; |
317 | u64 cookie, mgmt_tx_cookie; | 317 | u64 cookie, mgmt_tx_cookie; |
318 | enum ieee80211_roc_type type; | ||
318 | }; | 319 | }; |
319 | 320 | ||
320 | /* flags used in struct ieee80211_if_managed.flags */ | 321 | /* flags used in struct ieee80211_if_managed.flags */ |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index cc79b4a2e821..db547fceaeb9 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -277,7 +277,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
277 | duration = 10; | 277 | duration = 10; |
278 | 278 | ||
279 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, | 279 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, |
280 | duration); | 280 | duration, roc->type); |
281 | 281 | ||
282 | roc->started = true; | 282 | roc->started = true; |
283 | 283 | ||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 3d7cd2a0582f..e7db2b804e0c 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -1042,15 +1042,17 @@ TRACE_EVENT(drv_remain_on_channel, | |||
1042 | TP_PROTO(struct ieee80211_local *local, | 1042 | TP_PROTO(struct ieee80211_local *local, |
1043 | struct ieee80211_sub_if_data *sdata, | 1043 | struct ieee80211_sub_if_data *sdata, |
1044 | struct ieee80211_channel *chan, | 1044 | struct ieee80211_channel *chan, |
1045 | unsigned int duration), | 1045 | unsigned int duration, |
1046 | enum ieee80211_roc_type type), | ||
1046 | 1047 | ||
1047 | TP_ARGS(local, sdata, chan, duration), | 1048 | TP_ARGS(local, sdata, chan, duration, type), |
1048 | 1049 | ||
1049 | TP_STRUCT__entry( | 1050 | TP_STRUCT__entry( |
1050 | LOCAL_ENTRY | 1051 | LOCAL_ENTRY |
1051 | VIF_ENTRY | 1052 | VIF_ENTRY |
1052 | __field(int, center_freq) | 1053 | __field(int, center_freq) |
1053 | __field(unsigned int, duration) | 1054 | __field(unsigned int, duration) |
1055 | __field(u32, type) | ||
1054 | ), | 1056 | ), |
1055 | 1057 | ||
1056 | TP_fast_assign( | 1058 | TP_fast_assign( |
@@ -1058,12 +1060,13 @@ TRACE_EVENT(drv_remain_on_channel, | |||
1058 | VIF_ASSIGN; | 1060 | VIF_ASSIGN; |
1059 | __entry->center_freq = chan->center_freq; | 1061 | __entry->center_freq = chan->center_freq; |
1060 | __entry->duration = duration; | 1062 | __entry->duration = duration; |
1063 | __entry->type = type; | ||
1061 | ), | 1064 | ), |
1062 | 1065 | ||
1063 | TP_printk( | 1066 | TP_printk( |
1064 | LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms", | 1067 | LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms type=%d", |
1065 | LOCAL_PR_ARG, VIF_PR_ARG, | 1068 | LOCAL_PR_ARG, VIF_PR_ARG, |
1066 | __entry->center_freq, __entry->duration | 1069 | __entry->center_freq, __entry->duration, __entry->type |
1067 | ) | 1070 | ) |
1068 | ); | 1071 | ); |
1069 | 1072 | ||