From e9f935e3e8dc0bddd0df6d148165d95925422502 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sun, 25 Sep 2011 14:53:30 +0530 Subject: nl80211/cfg80211: Add support to disable CCK rate for management frame Add a new nl80211 attribute to specify whether to send the management frames in CCK rate or not. As of now the wpa_supplicant is disabling CCK rate at P2P init itself. So this patch helps to send P2P probe request/probe response/action frames being sent at non CCK rate in 2GHz without disabling 11b rates. This attribute is used with NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_FRAME commands to disable CCK rate for management frame transmission. Cc: Jouni Malinen Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b57ddf941e59..9cba0104e291 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1869,7 +1869,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, - const u8 *buf, size_t len, u64 *cookie) + const u8 *buf, size_t len, bool no_cck, + u64 *cookie) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; -- cgit v1.2.3 From aad14ceb45f5ff12da2ab5b37a596e6f81566515 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sun, 25 Sep 2011 14:53:31 +0530 Subject: mac80211: Send the management frame at requested rate Whenever the scan request or tx_mgmt is requesting not to use CCK rate for managemet frames through NL80211_ATTR_TX_NO_CCK_RATE attribute, then mac80211 should select appropriate least non-CCK rate. This could help to send P2P probes and P2P action frames at non 11b rates without diabling 11b rates globally. Cc: Jouni Malinen Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++++ net/mac80211/cfg.c | 3 +++ net/mac80211/ieee80211_i.h | 2 +- net/mac80211/mlme.c | 2 +- net/mac80211/rate.c | 29 ++++++++++++++++++++++++++++- net/mac80211/scan.c | 3 ++- net/mac80211/util.c | 8 ++++++-- net/mac80211/work.c | 2 +- 8 files changed, 46 insertions(+), 7 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 90dfcc99b466..1e83afae3c64 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -363,6 +363,9 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP * testing. It will be sent out with incorrect Michael MIC key to allow * TKIP countermeasures to be tested. + * @IEEE80211_TX_CTL_NO_CCK_RATE: This frame will be sent at non CCK rate. + * This flag is actually used for management frame especially for P2P + * frames not being sent at CCK rate in 2GHz band. * * Note: If you have to add new flags to the enumeration, then don't * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. @@ -393,6 +396,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25), IEEE80211_TX_INTFL_TKIP_MIC_FAILURE = BIT(26), + IEEE80211_TX_CTL_NO_CCK_RATE = BIT(27), }; #define IEEE80211_TX_CTL_STBC_SHIFT 23 diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9cba0104e291..56c35041ba97 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1897,6 +1897,9 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, flags |= IEEE80211_TX_CTL_TX_OFFCHAN; } + if (no_cck) + flags |= IEEE80211_TX_CTL_NO_CCK_RATE; + if (is_offchan && !offchan) return -EBUSY; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 21186e280ceb..4822d69930e2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1324,7 +1324,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - u32 ratemask, bool directed); + u32 ratemask, bool directed, bool no_cck); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, const size_t supp_rates_len, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1a59fb6630d4..cc80d320c922 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1239,7 +1239,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) } else { ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, - (u32) -1, true); + (u32) -1, true, false); } ifmgd->probe_send_count++; diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3d5a2cb835c4..f61244c0e0a2 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -233,6 +233,27 @@ static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, /* could not find a basic rate; use original selection */ } +static inline s8 +rate_lowest_non_cck_index(struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta) +{ + int i; + + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *srate = &sband->bitrates[i]; + if ((srate->bitrate == 10) || (srate->bitrate == 20) || + (srate->bitrate == 55) || (srate->bitrate == 110)) + continue; + + if (rate_supported(sta, sband->band, i)) + return i; + } + + /* No matching rate found */ + return 0; +} + + bool rate_control_send_low(struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) @@ -242,7 +263,13 @@ bool rate_control_send_low(struct ieee80211_sta *sta, int mcast_rate; if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { - info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); + if ((sband->band != IEEE80211_BAND_2GHZ) || + !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) + info->control.rates[0].idx = + rate_lowest_index(txrc->sband, sta); + else + info->control.rates[0].idx = + rate_lowest_non_cck_index(txrc->sband, sta); info->control.rates[0].count = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 1 : txrc->hw->max_rate_tries; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 6f09eca01112..830e60f65779 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -660,7 +660,8 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, local->scan_req->ssids[i].ssid, local->scan_req->ssids[i].ssid_len, local->scan_req->ie, local->scan_req->ie_len, - local->scan_req->rates[band], false); + local->scan_req->rates[band], false, + local->scan_req->no_cck); /* * After sending probe requests, wait for probe responses diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 4b1466d5b6a1..ead345db7127 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -899,14 +899,18 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - u32 ratemask, bool directed) + u32 ratemask, bool directed, bool no_cck) { struct sk_buff *skb; skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, ie, ie_len, directed); - if (skb) + if (skb) { + if (no_cck) + IEEE80211_SKB_CB(skb)->flags |= + IEEE80211_TX_CTL_NO_CCK_RATE; ieee80211_tx_skb(sdata, skb); + } } u32 ieee80211_sta_get_rates(struct ieee80211_local *local, diff --git a/net/mac80211/work.c b/net/mac80211/work.c index bac34394c05e..af374fab1a12 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -458,7 +458,7 @@ ieee80211_direct_probe(struct ieee80211_work *wk) */ ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, wk->probe_auth.ssid_len, NULL, 0, - (u32) -1, true); + (u32) -1, true, false); wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; run_again(local, wk->timeout); -- cgit v1.2.3 From f70f01c2ebbe31fbd8a96be3b45c5620dac45b96 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 25 Sep 2011 20:06:53 +0300 Subject: cfg80211/mac80211: add netdev param to set_txq_params() tx params are currently configured per hw, although they should be configured per interface. Signed-off-by: Eliad Peller Signed-off-by: John W. Linville --- include/net/cfg80211.h | 2 +- net/mac80211/cfg.c | 1 + net/wireless/nl80211.c | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'net/mac80211/cfg.c') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index c1dd56b7cce5..31d823a3092b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1486,7 +1486,7 @@ struct cfg80211_ops { int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params); - int (*set_txq_params)(struct wiphy *wiphy, + int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_txq_params *params); int (*set_channel)(struct wiphy *wiphy, struct net_device *dev, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 56c35041ba97..726fb8819b43 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1271,6 +1271,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, } static int ieee80211_set_txq_params(struct wiphy *wiphy, + struct net_device *dev, struct ieee80211_txq_params *params) { struct ieee80211_local *local = wiphy_priv(wiphy); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 48c1bf1a142d..74d16192fbf0 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1236,6 +1236,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; } + if (!netdev) { + result = -EINVAL; + goto bad_res; + } + nla_for_each_nested(nl_txq_params, info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], rem_txq_params) { @@ -1248,6 +1253,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; result = rdev->ops->set_txq_params(&rdev->wiphy, + netdev, &txq_params); if (result) goto bad_res; -- cgit v1.2.3 From f6f3def323e5d60cc2a5659533dce547c0aac5fc Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 25 Sep 2011 20:06:54 +0300 Subject: mac80211: save tx params per sdata save and configure tx param per sdata, rather than per hardware. Signed-off-by: Eliad Peller Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 5 +++-- net/mac80211/driver-ops.h | 5 +++-- net/mac80211/driver-trace.h | 14 ++++++++++---- net/mac80211/ieee80211_i.h | 3 ++- net/mac80211/mlme.c | 4 ++-- net/mac80211/util.c | 15 +++++++++++---- 6 files changed, 31 insertions(+), 15 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 726fb8819b43..8fef3cddbc4f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1275,6 +1275,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, struct ieee80211_txq_params *params) { struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_tx_queue_params p; if (!local->ops->conf_tx) @@ -1295,8 +1296,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, if (params->queue >= local->hw.queues) return -EINVAL; - local->tx_conf[params->queue] = p; - if (drv_conf_tx(local, params->queue, &p)) { + sdata->tx_conf[params->queue] = p; + if (drv_conf_tx(local, sdata, params->queue, &p)) { wiphy_debug(local->hw.wiphy, "failed to set TX queue parameters for queue %d\n", params->queue); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 5e5d97389bc9..4f845c0845ee 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -413,14 +413,15 @@ static inline void drv_sta_remove(struct ieee80211_local *local, trace_drv_return_void(local); } -static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, +static inline int drv_conf_tx(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, u16 queue, const struct ieee80211_tx_queue_params *params) { int ret = -EOPNOTSUPP; might_sleep(); - trace_drv_conf_tx(local, queue, params); + trace_drv_conf_tx(local, sdata, queue, params); if (local->ops->conf_tx) ret = local->ops->conf_tx(&local->hw, queue, params); trace_drv_return_int(local, ret); diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 07d94ff55798..a46b279bbbe4 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -697,32 +697,38 @@ TRACE_EVENT(drv_sta_remove, ); TRACE_EVENT(drv_conf_tx, - TP_PROTO(struct ieee80211_local *local, u16 queue, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + u16 queue, const struct ieee80211_tx_queue_params *params), - TP_ARGS(local, queue, params), + TP_ARGS(local, sdata, queue, params), TP_STRUCT__entry( LOCAL_ENTRY + VIF_ENTRY __field(u16, queue) __field(u16, txop) __field(u16, cw_min) __field(u16, cw_max) __field(u8, aifs) + __field(bool, uapsd) ), TP_fast_assign( LOCAL_ASSIGN; + VIF_ASSIGN; __entry->queue = queue; __entry->txop = params->txop; __entry->cw_max = params->cw_max; __entry->cw_min = params->cw_min; __entry->aifs = params->aifs; + __entry->uapsd = params->uapsd; ), TP_printk( - LOCAL_PR_FMT " queue:%d", - LOCAL_PR_ARG, __entry->queue + LOCAL_PR_FMT VIF_PR_FMT " queue:%d", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->queue ) ); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4822d69930e2..5cadcbbc9a57 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -609,6 +609,8 @@ struct ieee80211_sub_if_data { __be16 control_port_protocol; bool control_port_no_encrypt; + struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; + struct work_struct work; struct sk_buff_head skb_queue; @@ -751,7 +753,6 @@ struct ieee80211_local { struct workqueue_struct *workqueue; unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; - struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ spinlock_t queue_stop_reason_lock; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cc80d320c922..cd37a4e3c0d7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -936,8 +936,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, params.aifs, params.cw_min, params.cw_max, params.txop, params.uapsd); #endif - local->tx_conf[queue] = params; - if (drv_conf_tx(local, queue, ¶ms)) + sdata->tx_conf[queue] = params; + if (drv_conf_tx(local, sdata, queue, ¶ms)) wiphy_debug(local->hw.wiphy, "failed to set TX queue parameters for queue %d\n", queue); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ead345db7127..2c9dc360dc6d 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -632,8 +632,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) qparam.uapsd = false; - local->tx_conf[queue] = qparam; - drv_conf_tx(local, queue, &qparam); + sdata->tx_conf[queue] = qparam; + drv_conf_tx(local, sdata, queue, &qparam); } /* after reinitialize QoS TX queues setting to default, @@ -1044,8 +1044,15 @@ int ieee80211_reconfig(struct ieee80211_local *local) mutex_unlock(&local->sta_mtx); /* reconfigure tx conf */ - for (i = 0; i < hw->queues; i++) - drv_conf_tx(local, i, &local->tx_conf[i]); + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || + sdata->vif.type == NL80211_IFTYPE_MONITOR || + !ieee80211_sdata_running(sdata)) + continue; + + for (i = 0; i < hw->queues; i++) + drv_conf_tx(local, sdata, i, &sdata->tx_conf[i]); + } /* reconfigure hardware */ ieee80211_hw_config(local, ~0); -- cgit v1.2.3