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>
This commit is contained in:
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -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:
|
||||
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -1042,15 +1042,17 @@ 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(
|
||||
@@ -1058,12 +1060,13 @@ TRACE_EVENT(drv_remain_on_channel,
|
||||
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
|
||||
)
|
||||
);
|
||||
|
||||
|
Reference in New Issue
Block a user