netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/2] mac80211: add support for ht_caps mcs rxmask override
@ 2016-02-05 15:41 Cedric DEBARGE
  2016-02-05 15:41 ` [RFC 1/2] cfg80211: " Cedric DEBARGE
       [not found] ` <cover.1454685673.git.cedric.debarge-eYuUwLwYA0BQFI55V6+gNQ@public.gmane.org>
  0 siblings, 2 replies; 3+ messages in thread
From: Cedric DEBARGE @ 2016-02-05 15:41 UTC (permalink / raw)
  To: johannes
  Cc: davem, linux-wireless, linux-api, linux-kernel, netdev,
	Cedric DEBARGE

This patchset allows the ht_caps mcs rxmask to be defined on the fly.
It applies the given rxmask to all available bands.

This is actually limited to radio cards without internal rc.

Cedric DEBARGE (2):
  cfg80211: add support for ht_caps mcs rxmask override
  nl80211: add nl attribute to set ht_caps mcs rxmask override

 include/net/cfg80211.h       |  7 ++++++
 include/uapi/linux/nl80211.h |  5 +++++
 net/mac80211/cfg.c           | 48 +++++++++++++++++++++++++++++++++++++++
 net/mac80211/main.c          | 53 +++++++++++++++++++++++++++++++++++++-------
 net/wireless/nl80211.c       | 18 +++++++++++++++
 net/wireless/rdev-ops.h      | 11 +++++++++
 net/wireless/trace.h         | 15 +++++++++++++
 7 files changed, 149 insertions(+), 8 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [RFC 1/2] cfg80211: add support for ht_caps mcs rxmask override
  2016-02-05 15:41 [RFC 0/2] mac80211: add support for ht_caps mcs rxmask override Cedric DEBARGE
@ 2016-02-05 15:41 ` Cedric DEBARGE
       [not found] ` <cover.1454685673.git.cedric.debarge-eYuUwLwYA0BQFI55V6+gNQ@public.gmane.org>
  1 sibling, 0 replies; 3+ messages in thread
From: Cedric DEBARGE @ 2016-02-05 15:41 UTC (permalink / raw)
  To: johannes
  Cc: davem, linux-wireless, linux-api, linux-kernel, netdev,
	Cedric DEBARGE

Allows the ht_caps mcs rxmask to be defined on the fly.
In this implementation, the given rxmask is applied to
every band available.
This is only applicable for radio cards without internal rc.

Signed-off-by: Cedric Debarge <cedric.debarge@acksys.fr>
---
 include/net/cfg80211.h |  7 +++++++
 net/mac80211/cfg.c     | 48 +++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/main.c    | 53 ++++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 100 insertions(+), 8 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9e1b24c..257404b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2500,6 +2500,8 @@ struct cfg80211_qos_map {
  *	and returning to the base channel for communication with the AP.
  * @tdls_cancel_channel_switch: Stop channel-switching with a TDLS peer. Both
  *	peers must be on the base channel when the call completes.
+ *
+ * @set_htcap_rxmask: Override hardware capabilities for ht_caps mcs rxmask.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2765,6 +2767,8 @@ struct cfg80211_ops {
 	void	(*tdls_cancel_channel_switch)(struct wiphy *wiphy,
 					      struct net_device *dev,
 					      const u8 *addr);
+
+	int (*set_htcap_rxmask)(struct wiphy *wiphy, uint8_t *rxmask);
 };
 
 /*
@@ -3121,6 +3125,8 @@ struct wiphy_vendor_command {
  *	wiphy is theirs, e.g. in global notifiers
  * @bands: information about bands/channels supported by this device
  *
+ * @init_bands: save of the originals information about bands.
+ *
  * @mgmt_stypes: bitmasks of frame subtypes that can be subscribed to or
  *	transmitted through nl80211, points to an array indexed by interface
  *	type
@@ -3266,6 +3272,7 @@ struct wiphy {
 	const void *privid;
 
 	struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
+	struct ieee80211_supported_band *init_bands[IEEE80211_NUM_BANDS];
 
 	/* Lets us get back the wiphy on the callback */
 	void (*reg_notifier)(struct wiphy *wiphy,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 66d22de..daa415b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3350,6 +3350,53 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
 	return -ENOENT;
 }
 
+static int ieee80211_set_htcap_rxmask(struct wiphy *wiphy, uint8_t *rxmask)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_supported_band *iband;
+	int blank = 1;
+	int empty;
+	int i;
+
+	if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
+		return -EINVAL;
+
+	mutex_lock(&local->iflist_mtx);
+	empty = list_empty(&local->interfaces);
+	mutex_unlock(&local->iflist_mtx);
+
+	if (!empty)
+		return -EBUSY;
+
+	for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
+		if (rxmask[i]) {
+			blank = 0;
+			break;
+		}
+
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+		int j;
+
+		sband = wiphy->bands[i];
+		iband = wiphy->init_bands[i];
+
+		if (!iband)
+			continue;
+
+		for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++) {
+			if (blank)
+				sband->ht_cap.mcs.rx_mask[j] =
+						iband->ht_cap.mcs.rx_mask[j];
+			else
+				sband->ht_cap.mcs.rx_mask[j] = rxmask[j] &
+						iband->ht_cap.mcs.rx_mask[j];
+		}
+	}
+
+	return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -3435,4 +3482,5 @@ const struct cfg80211_ops mac80211_config_ops = {
 	.set_ap_chanwidth = ieee80211_set_ap_chanwidth,
 	.add_tx_ts = ieee80211_add_tx_ts,
 	.del_tx_ts = ieee80211_del_tx_ts,
+	.set_htcap_rxmask = ieee80211_set_htcap_rxmask,
 };
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6bcf0fa..138f1e4 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -789,15 +789,37 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 	return 0;
 }
 
+static int ieee80211_alloc_init_bands(struct wiphy *wiphy)
+{
+	int i;
+
+	memset(wiphy->init_bands, 0, IEEE80211_NUM_BANDS);
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+		if (!wiphy->bands[i])
+			continue;
+
+		wiphy->init_bands[i] = kzalloc(sizeof(*wiphy->init_bands[i]),
+					       GFP_KERNEL);
+		if (!wiphy->init_bands[i])
+			return -ENOMEM;
+
+		memcpy(wiphy->init_bands[i], wiphy->bands[i],
+		       sizeof(struct ieee80211_supported_band));
+	}
+
+	return 0;
+}
+
 int ieee80211_register_hw(struct ieee80211_hw *hw)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
-	int result, i;
-	enum ieee80211_band band;
+	struct cfg80211_chan_def dflt_chandef = {};
+	netdev_features_t feature_whitelist;
 	int channels, max_bitrates;
+	enum ieee80211_band band;
 	bool supp_ht, supp_vht;
-	netdev_features_t feature_whitelist;
-	struct cfg80211_chan_def dflt_chandef = {};
+	int result = 0;
+	int i;
 
 	if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
 	    (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
@@ -857,6 +879,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
 	local->rx_chains = 1;
 
+	if (ieee80211_alloc_init_bands(hw->wiphy)) {
+		result = -ENOMEM;
+		goto fail_sband_init;
+	}
+
 	/*
 	 * generic code guarantees at least one band,
 	 * set this very early because much code assumes
@@ -919,14 +946,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
 		for (j = 0; j < c->n_limits; j++)
 			if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
-			    c->limits[j].max > 1)
-				return -EINVAL;
+			    c->limits[j].max > 1) {
+				result = -EINVAL;
+				goto fail_sband_init;
+			}
 	}
 
 	local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
 				      sizeof(void *) * channels, GFP_KERNEL);
-	if (!local->int_scan_req)
-		return -ENOMEM;
+	if (!local->int_scan_req) {
+		result = -ENOMEM;
+		goto fail_sband_init;
+	}
 
 	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 		if (!local->hw.wiphy->bands[band])
@@ -1120,6 +1151,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	if (local->wiphy_ciphers_allocated)
 		kfree(local->hw.wiphy->cipher_suites);
 	kfree(local->int_scan_req);
+ fail_sband_init:
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+		kfree(hw->wiphy->init_bands[i]);
 	return result;
 }
 EXPORT_SYMBOL(ieee80211_register_hw);
@@ -1127,6 +1161,7 @@ EXPORT_SYMBOL(ieee80211_register_hw);
 void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
+	int i;
 
 	tasklet_kill(&local->tx_pending_tasklet);
 	tasklet_kill(&local->tasklet);
@@ -1170,6 +1205,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 	ieee80211_wep_free(local);
 	ieee80211_led_exit(local);
 	kfree(local->int_scan_req);
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+		kfree(hw->wiphy->init_bands[i]);
 }
 EXPORT_SYMBOL(ieee80211_unregister_hw);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC 2/2] nl80211: add nl attribute to set ht_caps mcs rxmask override
       [not found] ` <cover.1454685673.git.cedric.debarge-eYuUwLwYA0BQFI55V6+gNQ@public.gmane.org>
@ 2016-02-05 15:42   ` Cedric DEBARGE
  0 siblings, 0 replies; 3+ messages in thread
From: Cedric DEBARGE @ 2016-02-05 15:42 UTC (permalink / raw)
  To: johannes-cdvu00un1VgdHxzADdlk8Q
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, Cedric DEBARGE

This adds the NL80211_ATTR_WIPHY_HTCAP_RXMASK attribute to
NL80211_CMD_SET_WIPHY in order for the user to specify the ht_caps mcs
rxmask.

Signed-off-by: Cedric Debarge <cedric.debarge-eYuUwLwYA0BQFI55V6+gNQ@public.gmane.org>
---
 include/uapi/linux/nl80211.h |  5 +++++
 net/wireless/nl80211.c       | 18 ++++++++++++++++++
 net/wireless/rdev-ops.h      | 11 +++++++++++
 net/wireless/trace.h         | 15 +++++++++++++++
 4 files changed, 49 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7758969..50a53d8 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1794,6 +1794,9 @@ enum nl80211_commands {
  *	connecting to a PCP, and in %NL80211_CMD_START_AP to start
  *	a PCP instead of AP. Relevant for DMG networks only.
  *
+ * @NL80211_ATTR_WIPHY_HTCAP_RXMASK: Override hardware capabilities for ht_caps
+ *	mcs rxmask.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2170,6 +2173,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_PBSS,
 
+	NL80211_ATTR_WIPHY_HTCAP_RXMASK,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 268cb49..ef5ec8b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -402,6 +402,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
 	[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
 	[NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
+	[NL80211_ATTR_WIPHY_HTCAP_RXMASK] = { .type = NLA_BINARY,
+					      .len = IEEE80211_HT_MCS_MASK_LEN
+	},
 };
 
 /* policy for the key attributes */
@@ -2243,6 +2246,21 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 			return result;
 	}
 
+	if (info->attrs[NL80211_ATTR_WIPHY_HTCAP_RXMASK]) {
+		u8 rxmask[IEEE80211_HT_MCS_MASK_LEN];
+
+		if (wdev)
+			return -EOPNOTSUPP;
+
+		memcpy(rxmask,
+		       nla_data(info->attrs[NL80211_ATTR_WIPHY_HTCAP_RXMASK]),
+		       IEEE80211_HT_MCS_MASK_LEN);
+
+		result = rdev_set_htcap_rxmask(rdev, rxmask);
+		if (result)
+			return result;
+	}
+
 	changed = 0;
 
 	if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 8ae0c04..488adb9 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1071,4 +1071,15 @@ rdev_set_coalesce(struct cfg80211_registered_device *rdev,
 	trace_rdev_return_int(&rdev->wiphy, ret);
 	return ret;
 }
+
+static inline int
+rdev_set_htcap_rxmask(struct cfg80211_registered_device *rdev, uint8_t *rxmask)
+{
+	int ret;
+
+	trace_rdev_set_htcap_rxmask(&rdev->wiphy, rxmask);
+	ret = rdev->ops->set_htcap_rxmask(&rdev->wiphy, rxmask);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
 #endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 09b242b..d7c8c3c 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2120,6 +2120,21 @@ TRACE_EVENT(rdev_tdls_cancel_channel_switch,
 		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr))
 );
 
+TRACE_EVENT(rdev_set_htcap_rxmask,
+	TP_PROTO(struct wiphy *wiphy, uint8_t *rxmask),
+	TP_ARGS(wiphy, rxmask),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		__array(uint8_t, rxmask, IEEE80211_HT_MCS_MASK_LEN)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		memcpy(__entry->rxmask, rxmask, IEEE80211_HT_MCS_MASK_LEN);
+	),
+	TP_printk(WIPHY_PR_FMT ", %*ph",
+		  WIPHY_PR_ARG, IEEE80211_HT_MCS_MASK_LEN, &__entry->rxmask[0])
+);
+
 /*************************************************************
  *	     cfg80211 exported functions traces		     *
  *************************************************************/
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-02-05 18:31 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-05 15:41 [RFC 0/2] mac80211: add support for ht_caps mcs rxmask override Cedric DEBARGE
2016-02-05 15:41 ` [RFC 1/2] cfg80211: " Cedric DEBARGE
     [not found] ` <cover.1454685673.git.cedric.debarge-eYuUwLwYA0BQFI55V6+gNQ@public.gmane.org>
2016-02-05 15:42   ` [RFC 2/2] nl80211: add nl attribute to set " Cedric DEBARGE

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).