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 | |
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>
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/mac80211.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 3 | ||||
-rw-r--r-- | include/net/mac80211.h | 21 | ||||
-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 |
10 files changed, 58 insertions, 21 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 323e4a33fcac..c7cd2dffa5cd 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -1137,7 +1137,8 @@ done: | |||
1137 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | 1137 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, |
1138 | struct ieee80211_vif *vif, | 1138 | struct ieee80211_vif *vif, |
1139 | struct ieee80211_channel *channel, | 1139 | struct ieee80211_channel *channel, |
1140 | int duration) | 1140 | int duration, |
1141 | enum ieee80211_roc_type type) | ||
1141 | { | 1142 | { |
1142 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1143 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1143 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | 1144 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index e8264e11b12d..23460f4a4c75 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -1081,7 +1081,8 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
1081 | static int iwl_mvm_roc(struct ieee80211_hw *hw, | 1081 | static int iwl_mvm_roc(struct ieee80211_hw *hw, |
1082 | struct ieee80211_vif *vif, | 1082 | struct ieee80211_vif *vif, |
1083 | struct ieee80211_channel *channel, | 1083 | struct ieee80211_channel *channel, |
1084 | int duration) | 1084 | int duration, |
1085 | enum ieee80211_roc_type type) | ||
1085 | { | 1086 | { |
1086 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1087 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1087 | struct cfg80211_chan_def chandef; | 1088 | struct cfg80211_chan_def chandef; |
@@ -1092,8 +1093,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
1092 | return -EINVAL; | 1093 | return -EINVAL; |
1093 | } | 1094 | } |
1094 | 1095 | ||
1095 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d)\n", channel->hw_value, | 1096 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, |
1096 | duration); | 1097 | duration, type); |
1097 | 1098 | ||
1098 | mutex_lock(&mvm->mutex); | 1099 | mutex_lock(&mvm->mutex); |
1099 | 1100 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index cffdf4fbf161..7490c4fc7177 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1535,7 +1535,8 @@ static void hw_roc_done(struct work_struct *work) | |||
1535 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, | 1535 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, |
1536 | struct ieee80211_vif *vif, | 1536 | struct ieee80211_vif *vif, |
1537 | struct ieee80211_channel *chan, | 1537 | struct ieee80211_channel *chan, |
1538 | int duration) | 1538 | int duration, |
1539 | enum ieee80211_roc_type type) | ||
1539 | { | 1540 | { |
1540 | struct mac80211_hwsim_data *hwsim = hw->priv; | 1541 | struct mac80211_hwsim_data *hwsim = hw->priv; |
1541 | 1542 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 2c2ff3e1f849..d7e306333f6c 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -4956,7 +4956,8 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop) | |||
4956 | static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, | 4956 | static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, |
4957 | struct ieee80211_vif *vif, | 4957 | struct ieee80211_vif *vif, |
4958 | struct ieee80211_channel *chan, | 4958 | struct ieee80211_channel *chan, |
4959 | int duration) | 4959 | int duration, |
4960 | enum ieee80211_roc_type type) | ||
4960 | { | 4961 | { |
4961 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 4962 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
4962 | struct wl1271 *wl = hw->priv; | 4963 | struct wl1271 *wl = hw->priv; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f7eba1300d82..9b0d342c0675 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -2135,6 +2135,24 @@ enum ieee80211_rate_control_changed { | |||
2135 | }; | 2135 | }; |
2136 | 2136 | ||
2137 | /** | 2137 | /** |
2138 | * enum ieee80211_roc_type - remain on channel type | ||
2139 | * | ||
2140 | * With the support for multi channel contexts and multi channel operations, | ||
2141 | * remain on channel operations might be limited/deferred/aborted by other | ||
2142 | * flows/operations which have higher priority (and vise versa). | ||
2143 | * Specifying the ROC type can be used by devices to prioritize the ROC | ||
2144 | * operations compared to other operations/flows. | ||
2145 | * | ||
2146 | * @IEEE80211_ROC_TYPE_NORMAL: There are no special requirements for this ROC. | ||
2147 | * @IEEE80211_ROC_TYPE_MGMT_TX: The remain on channel request is required | ||
2148 | * for sending managment frames offchannel. | ||
2149 | */ | ||
2150 | enum ieee80211_roc_type { | ||
2151 | IEEE80211_ROC_TYPE_NORMAL = 0, | ||
2152 | IEEE80211_ROC_TYPE_MGMT_TX, | ||
2153 | }; | ||
2154 | |||
2155 | /** | ||
2138 | * struct ieee80211_ops - callbacks from mac80211 to the driver | 2156 | * struct ieee80211_ops - callbacks from mac80211 to the driver |
2139 | * | 2157 | * |
2140 | * This structure contains various callbacks that the driver may | 2158 | * This structure contains various callbacks that the driver may |
@@ -2687,7 +2705,8 @@ struct ieee80211_ops { | |||
2687 | int (*remain_on_channel)(struct ieee80211_hw *hw, | 2705 | int (*remain_on_channel)(struct ieee80211_hw *hw, |
2688 | struct ieee80211_vif *vif, | 2706 | struct ieee80211_vif *vif, |
2689 | struct ieee80211_channel *chan, | 2707 | struct ieee80211_channel *chan, |
2690 | int duration); | 2708 | int duration, |
2709 | enum ieee80211_roc_type type); | ||
2691 | int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); | 2710 | int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); |
2692 | int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); | 2711 | int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); |
2693 | void (*get_ringparam)(struct ieee80211_hw *hw, | 2712 | void (*get_ringparam)(struct ieee80211_hw *hw, |
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 | ||