aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlan Peer <ilan.peer@intel.com>2013-02-12 02:34:13 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-06 10:35:49 -0500
commitd339d5ca8eee34f3c70386cf2545edc53e546a13 (patch)
tree30587aa1e41343adcf10b0716e54964410d86edf
parentf62fab735e99af2190eba03f565adaca5c002882 (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.c3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c7
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c3
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c3
-rw-r--r--include/net/mac80211.h21
-rw-r--r--net/mac80211/cfg.c21
-rw-r--r--net/mac80211/driver-ops.h7
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/offchannel.c2
-rw-r--r--net/mac80211/trace.h11
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:
1137static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, 1137static 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,
1081static int iwl_mvm_roc(struct ieee80211_hw *hw, 1081static 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)
1535static int mac80211_hwsim_roc(struct ieee80211_hw *hw, 1535static 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)
4956static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, 4956static 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 */
2150enum 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,
787static inline int drv_remain_on_channel(struct ieee80211_local *local, 787static 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