Skip to content

Commit

Permalink
mac80211: Allow drivers to differentiate between ROC types
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ilan Peer authored and Johannes Berg committed Mar 6, 2013
1 parent f62fab7 commit d339d5c
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 21 deletions.
3 changes: 2 additions & 1 deletion drivers/net/wireless/iwlwifi/dvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,8 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *channel,
int duration)
int duration,
enum ieee80211_roc_type type)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
Expand Down
7 changes: 4 additions & 3 deletions drivers/net/wireless/iwlwifi/mvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,8 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
static int iwl_mvm_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *channel,
int duration)
int duration,
enum ieee80211_roc_type type)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct cfg80211_chan_def chandef;
Expand All @@ -1092,8 +1093,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
return -EINVAL;
}

IWL_DEBUG_MAC80211(mvm, "enter (%d, %d)\n", channel->hw_value,
duration);
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
duration, type);

mutex_lock(&mvm->mutex);

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/mac80211_hwsim.c
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,8 @@ static void hw_roc_done(struct work_struct *work)
static int mac80211_hwsim_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *chan,
int duration)
int duration,
enum ieee80211_roc_type type)
{
struct mac80211_hwsim_data *hwsim = hw->priv;

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/ti/wlcore/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4956,7 +4956,8 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop)
static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *chan,
int duration)
int duration,
enum ieee80211_roc_type type)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271 *wl = hw->priv;
Expand Down
21 changes: 20 additions & 1 deletion include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -2134,6 +2134,24 @@ enum ieee80211_rate_control_changed {
IEEE80211_RC_NSS_CHANGED = BIT(3),
};

/**
* enum ieee80211_roc_type - remain on channel type
*
* With the support for multi channel contexts and multi channel operations,
* remain on channel operations might be limited/deferred/aborted by other
* flows/operations which have higher priority (and vise versa).
* Specifying the ROC type can be used by devices to prioritize the ROC
* operations compared to other operations/flows.
*
* @IEEE80211_ROC_TYPE_NORMAL: There are no special requirements for this ROC.
* @IEEE80211_ROC_TYPE_MGMT_TX: The remain on channel request is required
* for sending managment frames offchannel.
*/
enum ieee80211_roc_type {
IEEE80211_ROC_TYPE_NORMAL = 0,
IEEE80211_ROC_TYPE_MGMT_TX,
};

/**
* struct ieee80211_ops - callbacks from mac80211 to the driver
*
Expand Down Expand Up @@ -2687,7 +2705,8 @@ struct ieee80211_ops {
int (*remain_on_channel)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *chan,
int duration);
int duration,
enum ieee80211_roc_type type);
int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
void (*get_ringparam)(struct ieee80211_hw *hw,
Expand Down
21 changes: 15 additions & 6 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2410,7 +2410,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel,
unsigned int duration, u64 *cookie,
struct sk_buff *txskb)
struct sk_buff *txskb,
enum ieee80211_roc_type type)
{
struct ieee80211_roc_work *roc, *tmp;
bool queued = false;
Expand All @@ -2429,6 +2430,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
roc->duration = duration;
roc->req_duration = duration;
roc->frame = txskb;
roc->type = type;
roc->mgmt_tx_cookie = (unsigned long)txskb;
roc->sdata = sdata;
INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
Expand Down Expand Up @@ -2459,7 +2461,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
if (!duration)
duration = 10;

ret = drv_remain_on_channel(local, sdata, channel, duration);
ret = drv_remain_on_channel(local, sdata, channel, duration, type);
if (ret) {
kfree(roc);
return ret;
Expand All @@ -2478,10 +2480,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
*
* If it hasn't started yet, just increase the duration
* and add the new one to the list of dependents.
* If the type of the new ROC has higher priority, modify the
* type of the previous one to match that of the new one.
*/
if (!tmp->started) {
list_add_tail(&roc->list, &tmp->dependents);
tmp->duration = max(tmp->duration, roc->duration);
tmp->type = max(tmp->type, roc->type);
queued = true;
break;
}
Expand All @@ -2493,16 +2498,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
/*
* In the offloaded ROC case, if it hasn't begun, add
* this new one to the dependent list to be handled
* when the the master one begins. If it has begun,
* when the master one begins. If it has begun,
* check that there's still a minimum time left and
* if so, start this one, transmitting the frame, but
* add it to the list directly after this one with a
* add it to the list directly after this one with
* a reduced time so we'll ask the driver to execute
* it right after finishing the previous one, in the
* hope that it'll also be executed right afterwards,
* effectively extending the old one.
* If there's no minimum time left, just add it to the
* normal list.
* TODO: the ROC type is ignored here, assuming that it
* is better to immediately use the current ROC.
*/
if (!tmp->hw_begun) {
list_add_tail(&roc->list, &tmp->dependents);
Expand Down Expand Up @@ -2596,7 +2603,8 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy,

mutex_lock(&local->mtx);
ret = ieee80211_start_roc_work(local, sdata, chan,
duration, cookie, NULL);
duration, cookie, NULL,
IEEE80211_ROC_TYPE_NORMAL);
mutex_unlock(&local->mtx);

return ret;
Expand Down Expand Up @@ -2829,7 +2837,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,

/* This will handle all kinds of coalescing and immediate TX */
ret = ieee80211_start_roc_work(local, sdata, chan,
wait, cookie, skb);
wait, cookie, skb,
IEEE80211_ROC_TYPE_MGMT_TX);
if (ret)
kfree_skb(skb);
out_unlock:
Expand Down
7 changes: 4 additions & 3 deletions net/mac80211/driver-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -787,15 +787,16 @@ static inline int drv_get_antenna(struct ieee80211_local *local,
static inline int drv_remain_on_channel(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *chan,
unsigned int duration)
unsigned int duration,
enum ieee80211_roc_type type)
{
int ret;

might_sleep();

trace_drv_remain_on_channel(local, sdata, chan, duration);
trace_drv_remain_on_channel(local, sdata, chan, duration, type);
ret = local->ops->remain_on_channel(&local->hw, &sdata->vif,
chan, duration);
chan, duration, type);
trace_drv_return_int(local, ret);

return ret;
Expand Down
1 change: 1 addition & 0 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ struct ieee80211_roc_work {
u32 duration, req_duration;
struct sk_buff *frame;
u64 cookie, mgmt_tx_cookie;
enum ieee80211_roc_type type;
};

/* flags used in struct ieee80211_if_managed.flags */
Expand Down
2 changes: 1 addition & 1 deletion net/mac80211/offchannel.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
duration = 10;

ret = drv_remain_on_channel(local, roc->sdata, roc->chan,
duration);
duration, roc->type);

roc->started = true;

Expand Down
11 changes: 7 additions & 4 deletions net/mac80211/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -1042,28 +1042,31 @@ TRACE_EVENT(drv_remain_on_channel,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *chan,
unsigned int duration),
unsigned int duration,
enum ieee80211_roc_type type),

TP_ARGS(local, sdata, chan, duration),
TP_ARGS(local, sdata, chan, duration, type),

TP_STRUCT__entry(
LOCAL_ENTRY
VIF_ENTRY
__field(int, center_freq)
__field(unsigned int, duration)
__field(u32, type)
),

TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
__entry->center_freq = chan->center_freq;
__entry->duration = duration;
__entry->type = type;
),

TP_printk(
LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms",
LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms type=%d",
LOCAL_PR_ARG, VIF_PR_ARG,
__entry->center_freq, __entry->duration
__entry->center_freq, __entry->duration, __entry->type
)
);

Expand Down

0 comments on commit d339d5c

Please sign in to comment.