All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/10] qtnfmac: regular portion of features and fixes
@ 2017-11-13 10:28 Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 01/10] qtnfmac: check that MAC exists in regulatory notifier Sergey Matyukevich
                   ` (9 more replies)
  0 siblings, 10 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

Hello Kalle and all,

Here is the next set of patches for qtnfmac driver. This set
enables the following features:
- radar detection and CAC support
- MAC-based ACL support
- make GET_STA_STATS format more flexible and future-proof
- inform wireless core about supported extended capabilities

Besides, several issues has been fixed. The most notable
among them are:
- fix RSSI data passed from qtnfmac to wireless core
- pass complete channel information between firmware and driver,
  including both primary channel and center frequency

The last fix enables proper operation channel report by iw tool
and fixes ACS mode in hostapd.

Regards,
Sergey

Igor Mitsyanko (6):
  qtnfmac: check that MAC exists in regulatory notifier
  qtnfmac: add support for radar detection and CAC
  qtnfmac: change default interface mode from AP to STA
  qtnfmac: check for passed channel being NULL in MGMT_TX
  qtnfmac: modify GET_STA_STATS cmd format for
  qtnfmac: keeping track of "generation" for STA info

Sergey Matyukevich (2):
  qtnfmac: pass complete channel data between driver and
  qtnfmac: fix rssi data passed to wireless core

Vasily Ulyanov (2):
  qtnfmac: fill wiphy's extended capabilities
  qtnfmac: support MAC address based access control

 cfg80211.c   |   63 ++++++++-
 commands.c   |  375 ++++++++++++++++++++++++++++++++++++++++++-----------------
 commands.h   |    5 
 core.c       |   13 --
 core.h       |    8 -
 event.c      |   76 ++++++++++-
 qlink.h      |  340 ++++++++++++++++++++++++++++++++++++++++-------------
 qlink_util.c |   78 +++++++-----
 qlink_util.h |    4 
 util.c       |    8 -
 util.h       |    4 
 11 files changed, 728 insertions(+), 246 deletions(-)

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

* [PATCH 01/10] qtnfmac: check that MAC exists in regulatory notifier
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware Sergey Matyukevich
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>

It is possible that regulatory notifier is called before MAC data
was allocated. We need to verify that MAC data exists before trying
to send a regulatory change event.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 7d6dc76c930a..eeffc7689455 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -802,6 +802,9 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
 			continue;
 
 		mac = bus->mac[mac_idx];
+		if (!mac)
+			continue;
+
 		wiphy = priv_to_wiphy(mac);
 
 		for (band = 0; band < NUM_NL80211_BANDS; ++band) {
-- 
2.11.0

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

* [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 01/10] qtnfmac: check that MAC exists in regulatory notifier Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-12-04 14:46   ` Kalle Valo
  2017-11-13 10:28 ` [PATCH 03/10] qtnfmac: add support for radar detection and CAC Sergey Matyukevich
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless
  Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov, Sergey Matyukevich

Center frequency is not enough to describe the channel in HT and VHT
modes. For 40MHz and 80MHz channels both primary channel and center
frequency should be specified in order to qualify channel completely.
This change adds primary channel info into qlink_chandef structure.

Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c  |  3 +-
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 14 +++---
 drivers/net/wireless/quantenna/qtnfmac/event.c     |  3 +-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h     | 57 ++++++++++++++++------
 .../net/wireless/quantenna/qtnfmac/qlink_util.c    | 48 ++++++++----------
 5 files changed, 74 insertions(+), 51 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index eeffc7689455..67a57c841c3f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -717,7 +717,8 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
 	}
 
 	if (!cfg80211_chandef_valid(chandef)) {
-		pr_err("%s: bad chan freq1=%u freq2=%u bw=%u\n", ndev->name,
+		pr_err("%s: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
+		       ndev->name, chandef->chan->center_freq,
 		       chandef->center_freq1, chandef->center_freq2,
 		       chandef->width);
 		ret = -ENODATA;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 8bc8dd637315..bed81f0cb1cd 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -247,7 +247,7 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
 		chtlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANDEF);
 		chtlv->hdr.len = cpu_to_le16(sizeof(*chtlv) -
 					     sizeof(chtlv->hdr));
-		qlink_chandef_cfg2q(&s->chandef, &chtlv->chan);
+		qlink_chandef_cfg2q(&s->chandef, &chtlv->chdef);
 	}
 
 	qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_HEAD,
@@ -1186,7 +1186,7 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
 	size_t tlv_len;
 	size_t tlv_dlen;
 	const struct qlink_tlv_hdr *tlv;
-	const struct qlink_tlv_channel *qchan;
+	const struct qlink_channel *qchan;
 	struct ieee80211_channel *chan;
 	unsigned int chidx = 0;
 	u32 qflags;
@@ -1232,7 +1232,7 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
 
 		switch (tlv_type) {
 		case QTN_TLV_ID_CHANNEL:
-			if (unlikely(tlv_len != sizeof(*qchan))) {
+			if (unlikely(tlv_dlen != sizeof(*qchan))) {
 				pr_err("invalid channel TLV len %zu\n",
 				       tlv_len);
 				goto error_ret;
@@ -1243,7 +1243,7 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
 				goto error_ret;
 			}
 
-			qchan = (const struct qlink_tlv_channel *)tlv;
+			qchan = (const struct qlink_channel *)tlv->val;
 			chan = &band->channels[chidx++];
 			qflags = le32_to_cpu(qchan->flags);
 
@@ -2037,8 +2037,8 @@ static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb,
 	qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
 	qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
 	qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - sizeof(qchan->hdr));
-	qchan->center_freq = cpu_to_le16(sc->center_freq);
-	qchan->hw_value = cpu_to_le16(sc->hw_value);
+	qchan->chan.center_freq = cpu_to_le16(sc->center_freq);
+	qchan->chan.hw_value = cpu_to_le16(sc->hw_value);
 
 	if (sc->flags & IEEE80211_CHAN_NO_IR)
 		flags |= QLINK_CHAN_NO_IR;
@@ -2046,7 +2046,7 @@ static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb,
 	if (sc->flags & IEEE80211_CHAN_RADAR)
 		flags |= QLINK_CHAN_RADAR;
 
-	qchan->flags = cpu_to_le32(flags);
+	qchan->chan.flags = cpu_to_le32(flags);
 }
 
 int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 4abc6d9ed560..a3a18d8469ae 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -369,7 +369,8 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
 	qlink_chandef_q2cfg(wiphy, &data->chan, &chandef);
 
 	if (!cfg80211_chandef_valid(&chandef)) {
-		pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n", mac->macid,
+		pr_err("MAC%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
+		       mac->macid, chandef.chan->center_freq,
 		       chandef.center_freq1, chandef.center_freq2,
 		       chandef.width);
 		return -EINVAL;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index a432fb001c41..534d11e4175a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -19,7 +19,7 @@
 
 #include <linux/ieee80211.h>
 
-#define QLINK_PROTO_VER		6
+#define QLINK_PROTO_VER		7
 
 #define QLINK_MACID_RSVD		0xFF
 #define QLINK_VIFID_RSVD		0xFF
@@ -122,17 +122,49 @@ enum qlink_channel_width {
 };
 
 /**
+ * struct qlink_channel - qlink control channel definition
+ *
+ * @hw_value: hardware-specific value for the channel
+ * @center_freq: center frequency in MHz
+ * @flags: channel flags from &enum qlink_channel_flags
+ * @band: band this channel belongs to
+ * @max_antenna_gain: maximum antenna gain in dBi
+ * @max_power: maximum transmission power (in dBm)
+ * @max_reg_power: maximum regulatory transmission power (in dBm)
+ * @dfs_state: current state of this channel.
+ *      Only relevant if radar is required on this channel.
+ * @beacon_found: helper to regulatory code to indicate when a beacon
+ *	has been found on this channel. Use regulatory_hint_found_beacon()
+ *	to enable this, this is useful only on 5 GHz band.
+ */
+struct qlink_channel {
+	__le16 hw_value;
+	__le16 center_freq;
+	__le32 flags;
+	u8 band;
+	u8 max_antenna_gain;
+	u8 max_power;
+	u8 max_reg_power;
+	__le32 dfs_cac_ms;
+	u8 dfs_state;
+	u8 beacon_found;
+	u8 rsvd[2];
+} __packed;
+
+/**
  * struct qlink_chandef - qlink channel definition
  *
+ * @chan: primary channel definition
  * @center_freq1: center frequency of first segment
  * @center_freq2: center frequency of second segment (80+80 only)
  * @width: channel width, one of @enum qlink_channel_width
  */
 struct qlink_chandef {
+	struct qlink_channel chan;
 	__le16 center_freq1;
 	__le16 center_freq2;
 	u8 width;
-	u8 rsvd[3];
+	u8 rsvd;
 } __packed;
 
 #define QLINK_MAX_NR_CIPHER_SUITES            5
@@ -1113,19 +1145,16 @@ enum qlink_dfs_state {
 	QLINK_DFS_AVAILABLE,
 };
 
+/**
+ * struct qlink_tlv_channel - data for QTN_TLV_ID_CHANNEL TLV
+ *
+ * Channel settings.
+ *
+ * @channel: ieee80211 channel settings.
+ */
 struct qlink_tlv_channel {
 	struct qlink_tlv_hdr hdr;
-	__le16 hw_value;
-	__le16 center_freq;
-	__le32 flags;
-	u8 band;
-	u8 max_antenna_gain;
-	u8 max_power;
-	u8 max_reg_power;
-	__le32 dfs_cac_ms;
-	u8 dfs_state;
-	u8 beacon_found;
-	u8 rsvd[2];
+	struct qlink_channel chan;
 } __packed;
 
 /**
@@ -1137,7 +1166,7 @@ struct qlink_tlv_channel {
  */
 struct qlink_tlv_chandef {
 	struct qlink_tlv_hdr hdr;
-	struct qlink_chandef chan;
+	struct qlink_chandef chdef;
 } __packed;
 
 enum qlink_ie_set_type {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index 61d999affb09..37b78f00e8e5 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -100,34 +100,6 @@ static enum nl80211_chan_width qlink_chanwidth_to_nl(u8 qlw)
 	}
 }
 
-void qlink_chandef_q2cfg(struct wiphy *wiphy,
-			 const struct qlink_chandef *qch,
-			 struct cfg80211_chan_def *chdef)
-{
-	chdef->center_freq1 = le16_to_cpu(qch->center_freq1);
-	chdef->center_freq2 = le16_to_cpu(qch->center_freq2);
-	chdef->width = qlink_chanwidth_to_nl(qch->width);
-
-	switch (chdef->width) {
-	case NL80211_CHAN_WIDTH_20_NOHT:
-	case NL80211_CHAN_WIDTH_20:
-	case NL80211_CHAN_WIDTH_5:
-	case NL80211_CHAN_WIDTH_10:
-		chdef->chan = ieee80211_get_channel(wiphy, chdef->center_freq1);
-		break;
-	case NL80211_CHAN_WIDTH_40:
-	case NL80211_CHAN_WIDTH_80:
-	case NL80211_CHAN_WIDTH_80P80:
-	case NL80211_CHAN_WIDTH_160:
-		chdef->chan = ieee80211_get_channel(wiphy,
-						    chdef->center_freq1 - 10);
-		break;
-	default:
-		chdef->chan = NULL;
-		break;
-	}
-}
-
 static u8 qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth)
 {
 	switch (nlwidth) {
@@ -152,9 +124,29 @@ static u8 qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth)
 	}
 }
 
+void qlink_chandef_q2cfg(struct wiphy *wiphy,
+			 const struct qlink_chandef *qch,
+			 struct cfg80211_chan_def *chdef)
+{
+	struct ieee80211_channel *chan;
+
+	chan = ieee80211_get_channel(wiphy, le16_to_cpu(qch->chan.center_freq));
+
+	chdef->chan = chan;
+	chdef->center_freq1 = le16_to_cpu(qch->center_freq1);
+	chdef->center_freq2 = le16_to_cpu(qch->center_freq2);
+	chdef->width = qlink_chanwidth_to_nl(qch->width);
+}
+
 void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef,
 			 struct qlink_chandef *qch)
 {
+	struct ieee80211_channel *chan = chdef->chan;
+
+	qch->chan.hw_value = cpu_to_le16(chan->hw_value);
+	qch->chan.center_freq = cpu_to_le16(chan->center_freq);
+	qch->chan.flags = cpu_to_le32(chan->flags);
+
 	qch->center_freq1 = cpu_to_le16(chdef->center_freq1);
 	qch->center_freq2 = cpu_to_le16(chdef->center_freq2);
 	qch->width = qlink_chanwidth_nl_to_qlink(chdef->width);
-- 
2.11.0

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

* [PATCH 03/10] qtnfmac: add support for radar detection and CAC
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 01/10] qtnfmac: check that MAC exists in regulatory notifier Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-12-04 14:49   ` Kalle Valo
  2017-11-13 10:28 ` [PATCH 04/10] qtnfmac: change default interface mode from AP to STA Sergey Matyukevich
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>

Implement two parts of radar handling logic:
- cfg80211 .start_radar_detect callback to allow nl80211 to initiate CAC
- radar event to allow wlan device to advertize CAC and radar events

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 18 ++++++-
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 38 ++++++++++++++
 drivers/net/wireless/quantenna/qtnfmac/commands.h |  3 ++
 drivers/net/wireless/quantenna/qtnfmac/event.c    | 61 +++++++++++++++++++++++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h    | 36 +++++++++++++
 5 files changed, 155 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 67a57c841c3f..64fc4119b3a6 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -751,6 +751,21 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 	return ret;
 }
 
+static int qtnf_start_radar_detection(struct wiphy *wiphy,
+				      struct net_device *ndev,
+				      struct cfg80211_chan_def *chandef,
+				      u32 cac_time_ms)
+{
+	struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+	int ret;
+
+	ret = qtnf_cmd_start_cac(vif, chandef, cac_time_ms);
+	if (ret)
+		pr_err("%s: failed to start CAC ret=%d\n", ndev->name, ret);
+
+	return ret;
+}
+
 static struct cfg80211_ops qtn_cfg80211_ops = {
 	.add_virtual_intf	= qtnf_add_virtual_intf,
 	.change_virtual_intf	= qtnf_change_virtual_intf,
@@ -774,7 +789,8 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
 	.disconnect		= qtnf_disconnect,
 	.dump_survey		= qtnf_dump_survey,
 	.get_channel		= qtnf_get_channel,
-	.channel_switch		= qtnf_channel_switch
+	.channel_switch		= qtnf_channel_switch,
+	.start_radar_detection	= qtnf_start_radar_detection,
 };
 
 static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index bed81f0cb1cd..7089f3eb7a87 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2512,3 +2512,41 @@ int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
 	consume_skb(resp_skb);
 	return ret;
 }
+
+int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
+		       const struct cfg80211_chan_def *chdef,
+		       u32 cac_time_ms)
+{
+	struct qtnf_bus *bus = vif->mac->bus;
+	struct sk_buff *cmd_skb;
+	struct qlink_cmd_start_cac *cmd;
+	int ret;
+	u16 res_code;
+
+	cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+					    QLINK_CMD_START_CAC,
+					    sizeof(*cmd));
+	if (unlikely(!cmd_skb))
+		return -ENOMEM;
+
+	cmd = (struct qlink_cmd_start_cac *)cmd_skb->data;
+	cmd->cac_time_ms = cpu_to_le32(cac_time_ms);
+	qlink_chandef_cfg2q(chdef, &cmd->chan);
+
+	qtnf_bus_lock(bus);
+	ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
+	qtnf_bus_unlock(bus);
+
+	if (ret)
+		return ret;
+
+	switch (res_code) {
+	case QLINK_CMD_RESULT_OK:
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index d981a76e5835..07a957af9a58 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -76,5 +76,8 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
 int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
 			      struct cfg80211_csa_settings *params);
 int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef);
+int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
+		       const struct cfg80211_chan_def *chdef,
+		       u32 cac_time_ms);
 
 #endif /* QLINK_COMMANDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index a3a18d8469ae..9843ca36b74b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -395,6 +395,63 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
 	return 0;
 }
 
+static int qtnf_event_handle_radar(struct qtnf_vif *vif,
+				   const struct qlink_event_radar *ev,
+				   u16 len)
+{
+	struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+	struct cfg80211_chan_def chandef;
+
+	if (len < sizeof(*ev)) {
+		pr_err("MAC%u: payload is too short\n", vif->mac->macid);
+		return -EINVAL;
+	}
+
+	if (!wiphy->registered || !vif->netdev)
+		return 0;
+
+	qlink_chandef_q2cfg(wiphy, &ev->chan, &chandef);
+
+	if (!cfg80211_chandef_valid(&chandef)) {
+		pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n",
+		       vif->mac->macid,
+		       chandef.center_freq1, chandef.center_freq2,
+		       chandef.width);
+		return -EINVAL;
+	}
+
+	pr_info("%s: radar event=%u f1=%u f2=%u bw=%u\n",
+		vif->netdev->name, ev->event,
+		chandef.center_freq1, chandef.center_freq2,
+		chandef.width);
+
+	switch (ev->event) {
+	case QLINK_RADAR_DETECTED:
+		cfg80211_radar_event(wiphy, &chandef, GFP_KERNEL);
+		break;
+	case QLINK_RADAR_CAC_FINISHED:
+		if (!vif->wdev.cac_started)
+			break;
+
+		cfg80211_cac_event(vif->netdev, &chandef,
+				   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
+		break;
+	case QLINK_RADAR_CAC_ABORTED:
+		if (!vif->wdev.cac_started)
+			break;
+
+		cfg80211_cac_event(vif->netdev, &chandef,
+				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+		break;
+	default:
+		pr_warn("%s: unhandled radar event %u\n",
+			vif->netdev->name, ev->event);
+		break;
+	}
+
+	return 0;
+}
+
 static int qtnf_event_parse(struct qtnf_wmac *mac,
 			    const struct sk_buff *event_skb)
 {
@@ -449,6 +506,10 @@ static int qtnf_event_parse(struct qtnf_wmac *mac,
 		ret = qtnf_event_handle_freq_change(mac, (const void *)event,
 						    event_len);
 		break;
+	case QLINK_EVENT_RADAR:
+		ret = qtnf_event_handle_radar(vif, (const void *)event,
+					      event_len);
+		break;
 	default:
 		pr_warn("unknown event type: %x\n", event_id);
 		break;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 534d11e4175a..3e3de4629a53 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -205,6 +205,7 @@ struct qlink_auth_encr {
  * @QLINK_CMD_REG_NOTIFY: notify device about regulatory domain change. This
  *	command is supported only if device reports QLINK_HW_SUPPORTS_REG_UPDATE
  *	capability.
+ * @QLINK_CMD_START_CAC: start radar detection procedure on a specified channel.
  */
 enum qlink_cmd_type {
 	QLINK_CMD_FW_INIT		= 0x0001,
@@ -224,6 +225,7 @@ enum qlink_cmd_type {
 	QLINK_CMD_BAND_INFO_GET		= 0x001A,
 	QLINK_CMD_CHAN_SWITCH		= 0x001B,
 	QLINK_CMD_CHAN_GET		= 0x001C,
+	QLINK_CMD_START_CAC		= 0x001D,
 	QLINK_CMD_START_AP		= 0x0021,
 	QLINK_CMD_STOP_AP		= 0x0022,
 	QLINK_CMD_GET_STA_INFO		= 0x0030,
@@ -617,6 +619,18 @@ struct qlink_cmd_start_ap {
 	u8 info[0];
 } __packed;
 
+/**
+ * struct qlink_cmd_start_cac - data for QLINK_CMD_START_CAC command
+ *
+ * @chan: a channel to start a radar detection procedure on.
+ * @cac_time_ms: CAC time.
+ */
+struct qlink_cmd_start_cac {
+	struct qlink_cmd chdr;
+	struct qlink_chandef chan;
+	__le32 cac_time_ms;
+} __packed;
+
 /* QLINK Command Responses messages related definitions
  */
 
@@ -814,6 +828,7 @@ enum qlink_event_type {
 	QLINK_EVENT_BSS_JOIN		= 0x0026,
 	QLINK_EVENT_BSS_LEAVE		= 0x0027,
 	QLINK_EVENT_FREQ_CHANGE		= 0x0028,
+	QLINK_EVENT_RADAR		= 0x0029,
 };
 
 /**
@@ -963,6 +978,27 @@ struct qlink_event_scan_complete {
 	__le32 flags;
 } __packed;
 
+enum qlink_radar_event {
+	QLINK_RADAR_DETECTED,
+	QLINK_RADAR_CAC_FINISHED,
+	QLINK_RADAR_CAC_ABORTED,
+	QLINK_RADAR_NOP_FINISHED,
+	QLINK_RADAR_PRE_CAC_EXPIRED,
+};
+
+/**
+ * struct qlink_event_radar - data for QLINK_EVENT_RADAR event
+ *
+ * @chan: channel on which radar event happened.
+ * @event: radar event type, one of &enum qlink_radar_event.
+ */
+struct qlink_event_radar {
+	struct qlink_event ehdr;
+	struct qlink_chandef chan;
+	u8 event;
+	u8 rsvd[3];
+} __packed;
+
 /* QLINK TLVs (Type-Length Values) definitions
  */
 
-- 
2.11.0

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

* [PATCH 04/10] qtnfmac: change default interface mode from AP to STA
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
                   ` (2 preceding siblings ...)
  2017-11-13 10:28 ` [PATCH 03/10] qtnfmac: add support for radar detection and CAC Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 05/10] qtnfmac: check for passed channel being NULL in MGMT_TX command Sergey Matyukevich
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>

To mimic mac80211 behaviour, change default interface type from AP to STA.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  2 +-
 drivers/net/wireless/quantenna/qtnfmac/core.c     | 11 ++++-------
 drivers/net/wireless/quantenna/qtnfmac/core.h     |  3 +--
 3 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 64fc4119b3a6..a11278de678d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -190,7 +190,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
 		goto err_mac;
 	}
 
-	if (qtnf_core_net_attach(mac, vif, name, name_assign_t, type)) {
+	if (qtnf_core_net_attach(mac, vif, name, name_assign_t)) {
 		pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid,
 		       vif->vifid);
 		goto err_net;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 2d2c1ea65cb2..ea850cb7dffc 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -258,7 +258,7 @@ static void qtnf_mac_init_primary_intf(struct qtnf_wmac *mac)
 {
 	struct qtnf_vif *vif = &mac->iflist[QTNF_PRIMARY_VIF_IDX];
 
-	vif->wdev.iftype = NL80211_IFTYPE_AP;
+	vif->wdev.iftype = NL80211_IFTYPE_STATION;
 	vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
 	vif->wdev.wiphy = priv_to_wiphy(mac);
 	INIT_WORK(&vif->reset_work, qtnf_vif_reset_handler);
@@ -298,8 +298,7 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
 }
 
 int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
-			 const char *name, unsigned char name_assign_type,
-			 enum nl80211_iftype iftype)
+			 const char *name, unsigned char name_assign_type)
 {
 	struct wiphy *wiphy = priv_to_wiphy(mac);
 	struct net_device *dev;
@@ -320,7 +319,6 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
 	dev->needs_free_netdev = true;
 	dev_net_set(dev, wiphy_net(wiphy));
 	dev->ieee80211_ptr = &vif->wdev;
-	dev->ieee80211_ptr->iftype = iftype;
 	ether_addr_copy(dev->dev_addr, vif->mac_addr);
 	SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
 	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
@@ -418,7 +416,7 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid)
 		goto error;
 	}
 
-	ret = qtnf_cmd_send_add_intf(vif, NL80211_IFTYPE_AP, vif->mac_addr);
+	ret = qtnf_cmd_send_add_intf(vif, vif->wdev.iftype, vif->mac_addr);
 	if (ret) {
 		pr_err("MAC%u: failed to add VIF\n", macid);
 		goto error;
@@ -446,8 +444,7 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid)
 
 	rtnl_lock();
 
-	ret = qtnf_core_net_attach(mac, vif, "wlan%d", NET_NAME_ENUM,
-				   NL80211_IFTYPE_AP);
+	ret = qtnf_core_net_attach(mac, vif, "wlan%d", NET_NAME_ENUM);
 	rtnl_unlock();
 
 	if (ret) {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 1b7bc0318f3e..8e42d1bdc65f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -144,8 +144,7 @@ struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac);
 struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac);
 struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus);
 int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv,
-			 const char *name, unsigned char name_assign_type,
-			 enum nl80211_iftype iftype);
+			 const char *name, unsigned char name_assign_type);
 void qtnf_main_work_queue(struct work_struct *work);
 int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed);
 int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac);
-- 
2.11.0

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

* [PATCH 05/10] qtnfmac: check for passed channel being NULL in MGMT_TX command
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
                   ` (3 preceding siblings ...)
  2017-11-13 10:28 ` [PATCH 04/10] qtnfmac: change default interface mode from AP to STA Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 06/10] qtnfmac: fix rssi data passed to wireless core Sergey Matyukevich
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>

Parameters passed into .mgmt_tx callback may have a NULL channel in case
userspace wants to send a frame on current channel. Make sure this case
is handled, pass "freq==0" in case channel is not specififed to tell
wlan device to use current channel.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index a11278de678d..f5eb2cdefae2 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -381,6 +381,7 @@ qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	const struct ieee80211_mgmt *mgmt_frame = (void *)params->buf;
 	u32 short_cookie = prandom_u32();
 	u16 flags = 0;
+	u16 freq;
 
 	*cookie = short_cookie;
 
@@ -393,13 +394,21 @@ qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	if (params->dont_wait_for_ack)
 		flags |= QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT;
 
+	/* If channel is not specified, pass "freq = 0" to tell device
+	 * firmware to use current channel.
+	 */
+	if (params->chan)
+		freq = params->chan->center_freq;
+	else
+		freq = 0;
+
 	pr_debug("%s freq:%u; FC:%.4X; DA:%pM; len:%zu; C:%.8X; FL:%.4X\n",
-		 wdev->netdev->name, params->chan->center_freq,
+		 wdev->netdev->name, freq,
 		 le16_to_cpu(mgmt_frame->frame_control), mgmt_frame->da,
 		 params->len, short_cookie, flags);
 
 	return qtnf_cmd_send_mgmt_frame(vif, short_cookie, flags,
-					params->chan->center_freq,
+					freq,
 					params->buf, params->len);
 }
 
-- 
2.11.0

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

* [PATCH 06/10] qtnfmac: fix rssi data passed to wireless core
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
                   ` (4 preceding siblings ...)
  2017-11-13 10:28 ` [PATCH 05/10] qtnfmac: check for passed channel being NULL in MGMT_TX command Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 07/10] qtnfmac: fill wiphy's extended capabilities Sergey Matyukevich
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless
  Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov, Sergey Matyukevich

Fix RSSI values passed to wireless core by qtnfmac driver:
- fix RSSI values in scan results:
  driver registers wiphy with CFG80211_SIGNAL_TYPE_MBM signal type,
  so mBm should be passed using DBM_TO_MBM macro
- accompany firmware changes fixing RSSI values in received mgmt frames
  update qlink message format and pass correct signed values to core

Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/event.c |  7 +++----
 drivers/net/wireless/quantenna/qtnfmac/qlink.h | 11 ++++++-----
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 9843ca36b74b..b3489b5b5d9e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -237,9 +237,8 @@ qtnf_event_handle_mgmt_received(struct qtnf_vif *vif,
 	pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif->netdev->name, frame_len,
 		 le16_to_cpu(frame->frame_control), frame->addr2);
 
-	cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq),
-			 le32_to_cpu(rxmgmt->sig_dbm), rxmgmt->frame_data,
-			 frame_len, flags);
+	cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq), rxmgmt->sig_dbm,
+			 rxmgmt->frame_data, frame_len, flags);
 
 	return 0;
 }
@@ -324,7 +323,7 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif,
 				  sr->bssid, get_unaligned_le64(&sr->tsf),
 				  le16_to_cpu(sr->capab),
 				  le16_to_cpu(sr->bintval), ies, ies_len,
-				  sr->signal, GFP_KERNEL);
+				  DBM_TO_MBM(sr->sig_dbm), GFP_KERNEL);
 	if (!bss)
 		return -ENOMEM;
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 3e3de4629a53..1f150be98820 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -19,7 +19,7 @@
 
 #include <linux/ieee80211.h>
 
-#define QLINK_PROTO_VER		7
+#define QLINK_PROTO_VER		8
 
 #define QLINK_MACID_RSVD		0xFF
 #define QLINK_VIFID_RSVD		0xFF
@@ -916,15 +916,16 @@ enum qlink_rxmgmt_flags {
  * struct qlink_event_rxmgmt - data for QLINK_EVENT_MGMT_RECEIVED event
  *
  * @freq: Frequency on which the frame was received in MHz.
- * @sig_dbm: signal strength in dBm.
  * @flags: bitmap of &enum qlink_rxmgmt_flags.
+ * @sig_dbm: signal strength in dBm.
  * @frame_data: data of Rx'd frame itself.
  */
 struct qlink_event_rxmgmt {
 	struct qlink_event ehdr;
 	__le32 freq;
-	__le32 sig_dbm;
 	__le32 flags;
+	s8 sig_dbm;
+	u8 rsvd[3];
 	u8 frame_data[0];
 } __packed;
 
@@ -936,7 +937,7 @@ struct qlink_event_rxmgmt {
  *	event was generated was discovered.
  * @capab: capabilities field.
  * @bintval: beacon interval announced by discovered BSS.
- * @signal: signal strength.
+ * @sig_dbm: signal strength in dBm.
  * @bssid: BSSID announced by discovered BSS.
  * @ssid_len: length of SSID announced by BSS.
  * @ssid: SSID announced by discovered BSS.
@@ -948,7 +949,7 @@ struct qlink_event_scan_result {
 	__le16 freq;
 	__le16 capab;
 	__le16 bintval;
-	s8 signal;
+	s8 sig_dbm;
 	u8 ssid_len;
 	u8 ssid[IEEE80211_MAX_SSID_LEN];
 	u8 bssid[ETH_ALEN];
-- 
2.11.0

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

* [PATCH 07/10] qtnfmac: fill wiphy's extended capabilities
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
                   ` (5 preceding siblings ...)
  2017-11-13 10:28 ` [PATCH 06/10] qtnfmac: fix rssi data passed to wireless core Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 08/10] qtnfmac: modify GET_STA_STATS cmd format for back/forward compatibility Sergey Matyukevich
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

From: Vasily Ulyanov <vulyanov@quantenna.com>

These are needed to inform userspace about features the hardware
supports (e.g. BSS Transition Management 802.11v)

Signed-off-by: Vasily Ulyanov <vulyanov@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 44 +++++++++++++++++++++++
 drivers/net/wireless/quantenna/qtnfmac/core.c     |  2 ++
 drivers/net/wireless/quantenna/qtnfmac/core.h     |  3 ++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h    |  1 +
 4 files changed, 50 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 7089f3eb7a87..839e86b99837 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1029,6 +1029,10 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
 	struct qlink_iface_comb_num *comb;
 	size_t tlv_full_len;
 	const struct qlink_tlv_hdr *tlv;
+	u8 *ext_capa = NULL;
+	u8 *ext_capa_mask = NULL;
+	u8 ext_capa_len = 0;
+	u8 ext_capa_mask_len = 0;
 
 	mac->macinfo.n_limits = 0;
 
@@ -1092,6 +1096,18 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
 			if (limits[rec].types)
 				rec++;
 			break;
+		case WLAN_EID_EXT_CAPABILITY:
+			if (unlikely(tlv_value_len > U8_MAX))
+				return -EINVAL;
+			ext_capa = (u8 *)tlv->val;
+			ext_capa_len = tlv_value_len;
+			break;
+		case QTN_TLV_ID_EXT_CAPABILITY_MASK:
+			if (unlikely(tlv_value_len > U8_MAX))
+				return -EINVAL;
+			ext_capa_mask = (u8 *)tlv->val;
+			ext_capa_mask_len = tlv_value_len;
+			break;
 		default:
 			break;
 		}
@@ -1112,6 +1128,34 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
 		return -EINVAL;
 	}
 
+	if (ext_capa_len != ext_capa_mask_len) {
+		pr_err("MAC%u: ext_capa/_mask lengths mismatch: %u != %u\n",
+		       mac->macid, ext_capa_len, ext_capa_mask_len);
+		return -EINVAL;
+	}
+
+	if (ext_capa_len > 0) {
+		ext_capa = kmemdup(ext_capa, ext_capa_len, GFP_KERNEL);
+		if (!ext_capa)
+			return -ENOMEM;
+
+		ext_capa_mask =
+			kmemdup(ext_capa_mask, ext_capa_mask_len, GFP_KERNEL);
+		if (!ext_capa_mask) {
+			kfree(ext_capa);
+			return -ENOMEM;
+		}
+	} else {
+		ext_capa = NULL;
+		ext_capa_mask = NULL;
+	}
+
+	kfree(mac->macinfo.extended_capabilities);
+	kfree(mac->macinfo.extended_capabilities_mask);
+	mac->macinfo.extended_capabilities = ext_capa;
+	mac->macinfo.extended_capabilities_mask = ext_capa_mask;
+	mac->macinfo.extended_capabilities_len = ext_capa_len;
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index ea850cb7dffc..3de0b26f839d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -381,6 +381,8 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
 	}
 
 	kfree(mac->macinfo.limits);
+	kfree(mac->macinfo.extended_capabilities);
+	kfree(mac->macinfo.extended_capabilities_mask);
 	kfree(wiphy->iface_combinations);
 	wiphy_free(wiphy);
 	bus->mac[macid] = NULL;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 8e42d1bdc65f..d7e295efb07d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -106,6 +106,9 @@ struct qtnf_mac_info {
 	struct ieee80211_vht_cap vht_cap_mod_mask;
 	struct ieee80211_iface_limit *limits;
 	size_t n_limits;
+	u8 *extended_capabilities;
+	u8 *extended_capabilities_mask;
+	u8 extended_capabilities_len;
 };
 
 struct qtnf_chan_stats {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 1f150be98820..f4d7d1603e3c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -1020,6 +1020,7 @@ enum qlink_tlv_id {
 	QTN_TLV_ID_KEY			= 0x0302,
 	QTN_TLV_ID_SEQ			= 0x0303,
 	QTN_TLV_ID_IE_SET		= 0x0305,
+	QTN_TLV_ID_EXT_CAPABILITY_MASK	= 0x0306,
 };
 
 struct qlink_tlv_hdr {
-- 
2.11.0

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

* [PATCH 08/10] qtnfmac: modify GET_STA_STATS cmd format for back/forward compatibility
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
                   ` (6 preceding siblings ...)
  2017-11-13 10:28 ` [PATCH 07/10] qtnfmac: fill wiphy's extended capabilities Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 09/10] qtnfmac: keeping track of "generation" for STA info Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 10/10] qtnfmac: support MAC address based access control Sergey Matyukevich
  9 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>

A set of per-STA statistics can potentially change quite often.
To ensure backwards and forward compatibility,
modify GET_STA_STATS command format:
  - introduce two TLV types
  - first TLV is a variable-sized bitmap of statistics values
    that are filled by firmware
  - second TLV is a structure with statistics itself

Only values specified in first TLV are valid.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 217 +++++++++++----------
 drivers/net/wireless/quantenna/qtnfmac/qlink.h     | 204 ++++++++++++-------
 .../net/wireless/quantenna/qtnfmac/qlink_util.c    |  12 ++
 .../net/wireless/quantenna/qtnfmac/qlink_util.h    |   2 +
 4 files changed, 267 insertions(+), 168 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 839e86b99837..38b9c1078058 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -461,30 +461,8 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
 }
 
 static void
-qtnf_sta_info_parse_basic_counters(struct station_info *sinfo,
-		const struct qlink_sta_stat_basic_counters *counters)
-{
-	sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES) |
-			 BIT(NL80211_STA_INFO_TX_BYTES);
-	sinfo->rx_bytes = get_unaligned_le64(&counters->rx_bytes);
-	sinfo->tx_bytes = get_unaligned_le64(&counters->tx_bytes);
-
-	sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS) |
-			 BIT(NL80211_STA_INFO_TX_PACKETS) |
-			 BIT(NL80211_STA_INFO_BEACON_RX);
-	sinfo->rx_packets = get_unaligned_le32(&counters->rx_packets);
-	sinfo->tx_packets = get_unaligned_le32(&counters->tx_packets);
-	sinfo->rx_beacon = get_unaligned_le64(&counters->rx_beacons);
-
-	sinfo->filled |= BIT(NL80211_STA_INFO_RX_DROP_MISC) |
-			 BIT(NL80211_STA_INFO_TX_FAILED);
-	sinfo->rx_dropped_misc = get_unaligned_le32(&counters->rx_dropped);
-	sinfo->tx_failed = get_unaligned_le32(&counters->tx_failed);
-}
-
-static void
 qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
-			 const struct  qlink_sta_info_rate *rate_src)
+			 const struct qlink_sta_info_rate *rate_src)
 {
 	rate_dst->legacy = get_unaligned_le16(&rate_src->rate) * 10;
 
@@ -493,22 +471,23 @@ qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
 	rate_dst->flags = 0;
 
 	switch (rate_src->bw) {
-	case QLINK_STA_INFO_RATE_BW_5:
+	case QLINK_CHAN_WIDTH_5:
 		rate_dst->bw = RATE_INFO_BW_5;
 		break;
-	case QLINK_STA_INFO_RATE_BW_10:
+	case QLINK_CHAN_WIDTH_10:
 		rate_dst->bw = RATE_INFO_BW_10;
 		break;
-	case QLINK_STA_INFO_RATE_BW_20:
+	case QLINK_CHAN_WIDTH_20:
+	case QLINK_CHAN_WIDTH_20_NOHT:
 		rate_dst->bw = RATE_INFO_BW_20;
 		break;
-	case QLINK_STA_INFO_RATE_BW_40:
+	case QLINK_CHAN_WIDTH_40:
 		rate_dst->bw = RATE_INFO_BW_40;
 		break;
-	case QLINK_STA_INFO_RATE_BW_80:
+	case QLINK_CHAN_WIDTH_80:
 		rate_dst->bw = RATE_INFO_BW_80;
 		break;
-	case QLINK_STA_INFO_RATE_BW_160:
+	case QLINK_CHAN_WIDTH_160:
 		rate_dst->bw = RATE_INFO_BW_160;
 		break;
 	default:
@@ -578,87 +557,125 @@ qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst,
 }
 
 static void
-qtnf_sta_info_parse_generic_info(struct station_info *sinfo,
-				 const struct qlink_sta_info_generic *info)
+qtnf_cmd_sta_info_parse(struct station_info *sinfo,
+			const struct qlink_tlv_hdr *tlv,
+			size_t resp_size)
 {
-	sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME) |
-			 BIT(NL80211_STA_INFO_INACTIVE_TIME);
-	sinfo->connected_time = get_unaligned_le32(&info->connected_time);
-	sinfo->inactive_time = get_unaligned_le32(&info->inactive_time);
+	const struct qlink_sta_stats *stats = NULL;
+	const u8 *map = NULL;
+	unsigned int map_len = 0;
+	unsigned int stats_len = 0;
+	u16 tlv_len;
+
+#define qtnf_sta_stat_avail(stat_name, bitn)	\
+	(qtnf_utils_is_bit_set(map, bitn, map_len) && \
+	 (offsetofend(struct qlink_sta_stats, stat_name) <= stats_len))
+
+	while (resp_size >= sizeof(*tlv)) {
+		tlv_len = le16_to_cpu(tlv->len);
+
+		switch (le16_to_cpu(tlv->type)) {
+		case QTN_TLV_ID_STA_STATS_MAP:
+			map_len = tlv_len;
+			map = tlv->val;
+			break;
+		case QTN_TLV_ID_STA_STATS:
+			stats_len = tlv_len;
+			stats = (const struct qlink_sta_stats *)tlv->val;
+			break;
+		default:
+			break;
+		}
+
+		resp_size -= tlv_len + sizeof(*tlv);
+		tlv = (const struct qlink_tlv_hdr *)(tlv->val + tlv_len);
+	}
 
-	sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
-			 BIT(NL80211_STA_INFO_SIGNAL_AVG);
-	sinfo->signal = info->rssi - 120;
-	sinfo->signal_avg = info->rssi_avg - QLINK_RSSI_OFFSET;
+	if (!map || !stats)
+		return;
+
+	if (qtnf_sta_stat_avail(inactive_time, QLINK_STA_INFO_INACTIVE_TIME)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME);
+		sinfo->inactive_time = le32_to_cpu(stats->inactive_time);
+	}
 
-	if (info->rx_rate.rate) {
+	if (qtnf_sta_stat_avail(connected_time,
+				QLINK_STA_INFO_CONNECTED_TIME)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
+		sinfo->connected_time = le32_to_cpu(stats->connected_time);
+	}
+
+	if (qtnf_sta_stat_avail(signal, QLINK_STA_INFO_SIGNAL)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+		sinfo->signal = stats->signal - QLINK_RSSI_OFFSET;
+	}
+
+	if (qtnf_sta_stat_avail(signal_avg, QLINK_STA_INFO_SIGNAL_AVG)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG);
+		sinfo->signal_avg = stats->signal_avg - QLINK_RSSI_OFFSET;
+	}
+
+	if (qtnf_sta_stat_avail(rxrate, QLINK_STA_INFO_RX_BITRATE)) {
 		sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
-		qtnf_sta_info_parse_rate(&sinfo->rxrate, &info->rx_rate);
+		qtnf_sta_info_parse_rate(&sinfo->rxrate, &stats->rxrate);
 	}
 
-	if (info->tx_rate.rate) {
+	if (qtnf_sta_stat_avail(txrate, QLINK_STA_INFO_TX_BITRATE)) {
 		sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
-		qtnf_sta_info_parse_rate(&sinfo->txrate, &info->tx_rate);
+		qtnf_sta_info_parse_rate(&sinfo->txrate, &stats->txrate);
 	}
 
-	sinfo->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
-	qtnf_sta_info_parse_flags(&sinfo->sta_flags, &info->state);
-}
+	if (qtnf_sta_stat_avail(sta_flags, QLINK_STA_INFO_STA_FLAGS)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
+		qtnf_sta_info_parse_flags(&sinfo->sta_flags, &stats->sta_flags);
+	}
 
-static int qtnf_cmd_sta_info_parse(struct station_info *sinfo,
-				   const u8 *payload, size_t payload_size)
-{
-	const struct qlink_sta_stat_basic_counters *counters;
-	const struct qlink_sta_info_generic *sta_info;
-	u16 tlv_type;
-	u16 tlv_value_len;
-	size_t tlv_full_len;
-	const struct qlink_tlv_hdr *tlv;
+	if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
+		sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes);
+	}
 
-	sinfo->filled = 0;
+	if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
+		sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes);
+	}
 
-	tlv = (const struct qlink_tlv_hdr *)payload;
-	while (payload_size >= sizeof(struct qlink_tlv_hdr)) {
-		tlv_type = le16_to_cpu(tlv->type);
-		tlv_value_len = le16_to_cpu(tlv->len);
-		tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
-		if (tlv_full_len > payload_size) {
-			pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
-				tlv_type, tlv_value_len);
-			return -EINVAL;
-		}
-		switch (tlv_type) {
-		case QTN_TLV_ID_STA_BASIC_COUNTERS:
-			if (unlikely(tlv_value_len < sizeof(*counters))) {
-				pr_err("invalid TLV size %.4X: %u\n",
-				       tlv_type, tlv_value_len);
-				break;
-			}
+	if (qtnf_sta_stat_avail(rx_bytes, QLINK_STA_INFO_RX_BYTES64)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64);
+		sinfo->rx_bytes = le64_to_cpu(stats->rx_bytes);
+	}
 
-			counters = (void *)tlv->val;
-			qtnf_sta_info_parse_basic_counters(sinfo, counters);
-			break;
-		case QTN_TLV_ID_STA_GENERIC_INFO:
-			if (unlikely(tlv_value_len < sizeof(*sta_info)))
-				break;
+	if (qtnf_sta_stat_avail(tx_bytes, QLINK_STA_INFO_TX_BYTES64)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64);
+		sinfo->tx_bytes = le64_to_cpu(stats->tx_bytes);
+	}
 
-			sta_info = (void *)tlv->val;
-			qtnf_sta_info_parse_generic_info(sinfo, sta_info);
-			break;
-		default:
-			pr_warn("unexpected TLV type: %.4X\n", tlv_type);
-			break;
-		}
-		payload_size -= tlv_full_len;
-		tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+	if (qtnf_sta_stat_avail(rx_packets, QLINK_STA_INFO_RX_PACKETS)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
+		sinfo->rx_packets = le32_to_cpu(stats->rx_packets);
 	}
 
-	if (payload_size) {
-		pr_warn("malformed TLV buf; bytes left: %zu\n", payload_size);
-		return -EINVAL;
+	if (qtnf_sta_stat_avail(tx_packets, QLINK_STA_INFO_TX_PACKETS)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
+		sinfo->tx_packets = le32_to_cpu(stats->tx_packets);
 	}
 
-	return 0;
+	if (qtnf_sta_stat_avail(rx_beacon, QLINK_STA_INFO_BEACON_RX)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_BEACON_RX);
+		sinfo->rx_beacon = le64_to_cpu(stats->rx_beacon);
+	}
+
+	if (qtnf_sta_stat_avail(rx_dropped_misc, QLINK_STA_INFO_RX_DROP_MISC)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_RX_DROP_MISC);
+		sinfo->rx_dropped_misc = le32_to_cpu(stats->rx_dropped_misc);
+	}
+
+	if (qtnf_sta_stat_avail(tx_failed, QLINK_STA_INFO_TX_FAILED)) {
+		sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
+		sinfo->tx_failed = le32_to_cpu(stats->tx_failed);
+	}
+
+#undef qtnf_sta_stat_avail
 }
 
 int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
@@ -715,7 +732,9 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
 		goto out;
 	}
 
-	ret = qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len);
+	qtnf_cmd_sta_info_parse(sinfo,
+				(const struct qlink_tlv_hdr *)resp->info,
+				var_resp_len);
 
 out:
 	qtnf_bus_unlock(vif->mac->bus);
@@ -1992,21 +2011,17 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
 
 	cmd = (struct qlink_cmd_change_sta *)cmd_skb->data;
 	ether_addr_copy(cmd->sta_addr, mac);
+	cmd->flag_update.mask =
+		cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_mask));
+	cmd->flag_update.value =
+		cpu_to_le32(qtnf_encode_sta_flags(params->sta_flags_set));
 
 	switch (vif->wdev.iftype) {
 	case NL80211_IFTYPE_AP:
 		cmd->if_type = cpu_to_le16(QLINK_IFTYPE_AP);
-		cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags(
-						  params->sta_flags_mask));
-		cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags(
-						 params->sta_flags_set));
 		break;
 	case NL80211_IFTYPE_STATION:
 		cmd->if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
-		cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags(
-						  params->sta_flags_mask));
-		cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags(
-						 params->sta_flags_set));
 		break;
 	default:
 		pr_err("unsupported iftype %d\n", vif->wdev.iftype);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index f4d7d1603e3c..5d98000b0f5b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -19,7 +19,7 @@
 
 #include <linux/ieee80211.h>
 
-#define QLINK_PROTO_VER		8
+#define QLINK_PROTO_VER		9
 
 #define QLINK_MACID_RSVD		0xFF
 #define QLINK_VIFID_RSVD		0xFF
@@ -185,6 +185,17 @@ struct qlink_auth_encr {
 	u8 rsvd[2];
 } __packed;
 
+/**
+ * struct qlink_sta_info_state - station flags mask/value
+ *
+ * @mask: STA flags mask, bitmap of &enum qlink_sta_flags
+ * @value: STA flags values, bitmap of &enum qlink_sta_flags
+ */
+struct qlink_sta_info_state {
+	__le32 mask;
+	__le32 value;
+} __packed;
+
 /* QLINK Command messages related definitions
  */
 
@@ -402,16 +413,14 @@ struct qlink_cmd_set_def_mgmt_key {
 /**
  * struct qlink_cmd_change_sta - data for QLINK_CMD_CHANGE_STA command
  *
- * @sta_flags_mask: STA flags mask, bitmap of &enum qlink_sta_flags
- * @sta_flags_set: STA flags values, bitmap of &enum qlink_sta_flags
+ * @flag_update: STA flags to update
  * @if_type: Mode of interface operation, one of &enum qlink_iface_type
  * @vlanid: VLAN ID to assign to specific STA
  * @sta_addr: address of the STA for which parameters are set.
  */
 struct qlink_cmd_change_sta {
 	struct qlink_cmd chdr;
-	__le32 sta_flags_mask;
-	__le32 sta_flags_set;
+	struct qlink_sta_info_state flag_update;
 	__le16 if_type;
 	__le16 vlanid;
 	u8 sta_addr[ETH_ALEN];
@@ -755,17 +764,27 @@ struct qlink_resp_manage_intf {
 	struct qlink_intf_info intf_info;
 } __packed;
 
+enum qlink_sta_info_rate_flags {
+	QLINK_STA_INFO_RATE_FLAG_HT_MCS		= BIT(0),
+	QLINK_STA_INFO_RATE_FLAG_VHT_MCS	= BIT(1),
+	QLINK_STA_INFO_RATE_FLAG_SHORT_GI	= BIT(2),
+	QLINK_STA_INFO_RATE_FLAG_60G		= BIT(3),
+};
+
 /**
  * struct qlink_resp_get_sta_info - response for QLINK_CMD_GET_STA_INFO command
  *
  * Response data containing statistics for specified STA.
  *
+ * @filled: a bitmask of &enum qlink_sta_info, specifies which info in response
+ *	is valid.
  * @sta_addr: MAC address of STA the response carries statistic for.
- * @info: statistics for specified STA.
+ * @info: variable statistics for specified STA.
  */
 struct qlink_resp_get_sta_info {
 	struct qlink_resp rhdr;
 	u8 sta_addr[ETH_ALEN];
+	u8 rsvd[2];
 	u8 info[0];
 } __packed;
 
@@ -1003,6 +1022,15 @@ struct qlink_event_radar {
 /* QLINK TLVs (Type-Length Values) definitions
  */
 
+/**
+ * enum qlink_tlv_id - list of TLVs that Qlink messages can carry
+ *
+ * @QTN_TLV_ID_STA_STATS_MAP: a bitmap of &enum qlink_sta_info, used to
+ *	indicate which statistic carried in QTN_TLV_ID_STA_STATS is valid.
+ * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by
+ *	&struct qlink_sta_stats. Valid values are marked as such in a bitmap
+ *	carried by QTN_TLV_ID_STA_STATS_MAP.
+ */
 enum qlink_tlv_id {
 	QTN_TLV_ID_FRAG_THRESH		= 0x0201,
 	QTN_TLV_ID_RTS_THRESH		= 0x0202,
@@ -1011,12 +1039,12 @@ enum qlink_tlv_id {
 	QTN_TLV_ID_REG_RULE		= 0x0207,
 	QTN_TLV_ID_CHANNEL		= 0x020F,
 	QTN_TLV_ID_CHANDEF		= 0x0210,
+	QTN_TLV_ID_STA_STATS_MAP	= 0x0211,
+	QTN_TLV_ID_STA_STATS		= 0x0212,
 	QTN_TLV_ID_COVERAGE_CLASS	= 0x0213,
 	QTN_TLV_ID_IFACE_LIMIT		= 0x0214,
 	QTN_TLV_ID_NUM_IFACE_COMB	= 0x0215,
 	QTN_TLV_ID_CHANNEL_STATS	= 0x0216,
-	QTN_TLV_ID_STA_BASIC_COUNTERS	= 0x0300,
-	QTN_TLV_ID_STA_GENERIC_INFO	= 0x0301,
 	QTN_TLV_ID_KEY			= 0x0302,
 	QTN_TLV_ID_SEQ			= 0x0303,
 	QTN_TLV_ID_IE_SET		= 0x0305,
@@ -1038,67 +1066,8 @@ struct qlink_iface_comb_num {
 	__le16 iface_comb_num;
 } __packed;
 
-struct qlink_sta_stat_basic_counters {
-	__le64 rx_bytes;
-	__le64 tx_bytes;
-	__le64 rx_beacons;
-	__le32 rx_packets;
-	__le32 tx_packets;
-	__le32 rx_dropped;
-	__le32 tx_failed;
-} __packed;
-
-enum qlink_sta_info_rate_flags {
-	QLINK_STA_INFO_RATE_FLAG_INVALID	= 0,
-	QLINK_STA_INFO_RATE_FLAG_HT_MCS		= BIT(0),
-	QLINK_STA_INFO_RATE_FLAG_VHT_MCS	= BIT(1),
-	QLINK_STA_INFO_RATE_FLAG_SHORT_GI	= BIT(2),
-	QLINK_STA_INFO_RATE_FLAG_60G		= BIT(3),
-};
-
-enum qlink_sta_info_rate_bw {
-	QLINK_STA_INFO_RATE_BW_5		= 0,
-	QLINK_STA_INFO_RATE_BW_10		= 1,
-	QLINK_STA_INFO_RATE_BW_20		= 2,
-	QLINK_STA_INFO_RATE_BW_40		= 3,
-	QLINK_STA_INFO_RATE_BW_80		= 4,
-	QLINK_STA_INFO_RATE_BW_160		= 5,
-};
-
-/**
- * struct qlink_sta_info_rate - STA rate statistics
- *
- * @rate: data rate in Mbps.
- * @flags: bitmap of &enum qlink_sta_flags.
- * @mcs: 802.11-defined MCS index.
- * nss: Number of Spatial Streams.
- * @bw: bandwidth, one of &enum qlink_sta_info_rate_bw.
- */
-struct qlink_sta_info_rate {
-	__le16 rate;
-	u8 flags;
-	u8 mcs;
-	u8 nss;
-	u8 bw;
-} __packed;
-
-struct qlink_sta_info_state {
-	__le32 mask;
-	__le32 value;
-} __packed;
-
 #define QLINK_RSSI_OFFSET	120
 
-struct qlink_sta_info_generic {
-	struct qlink_sta_info_state state;
-	__le32 connected_time;
-	__le32 inactive_time;
-	struct qlink_sta_info_rate rx_rate;
-	struct qlink_sta_info_rate tx_rate;
-	u8 rssi;
-	u8 rssi_avg;
-} __packed;
-
 struct qlink_tlv_frag_rts_thr {
 	struct qlink_tlv_hdr hdr;
 	__le16 thr;
@@ -1243,4 +1212,105 @@ struct qlink_chan_stats {
 	s8 chan_noise;
 } __packed;
 
+/**
+ * enum qlink_sta_info - station information bitmap
+ *
+ * Used to indicate which statistics values in &struct qlink_sta_stats
+ * are valid. Individual values are used to fill a bitmap carried in a
+ * payload of QTN_TLV_ID_STA_STATS_MAP.
+ *
+ * @QLINK_STA_INFO_CONNECTED_TIME: connected_time value is valid.
+ * @QLINK_STA_INFO_INACTIVE_TIME: inactive_time value is valid.
+ * @QLINK_STA_INFO_RX_BYTES: lower 32 bits of rx_bytes value are valid.
+ * @QLINK_STA_INFO_TX_BYTES: lower 32 bits of tx_bytes value are valid.
+ * @QLINK_STA_INFO_RX_BYTES64: rx_bytes value is valid.
+ * @QLINK_STA_INFO_TX_BYTES64: tx_bytes value is valid.
+ * @QLINK_STA_INFO_RX_DROP_MISC: rx_dropped_misc value is valid.
+ * @QLINK_STA_INFO_BEACON_RX: rx_beacon value is valid.
+ * @QLINK_STA_INFO_SIGNAL: signal value is valid.
+ * @QLINK_STA_INFO_SIGNAL_AVG: signal_avg value is valid.
+ * @QLINK_STA_INFO_RX_BITRATE: rxrate value is valid.
+ * @QLINK_STA_INFO_TX_BITRATE: txrate value is valid.
+ * @QLINK_STA_INFO_RX_PACKETS: rx_packets value is valid.
+ * @QLINK_STA_INFO_TX_PACKETS: tx_packets value is valid.
+ * @QLINK_STA_INFO_TX_RETRIES: tx_retries value is valid.
+ * @QLINK_STA_INFO_TX_FAILED: tx_failed value is valid.
+ * @QLINK_STA_INFO_STA_FLAGS: sta_flags value is valid.
+ */
+enum qlink_sta_info {
+	QLINK_STA_INFO_CONNECTED_TIME,
+	QLINK_STA_INFO_INACTIVE_TIME,
+	QLINK_STA_INFO_RX_BYTES,
+	QLINK_STA_INFO_TX_BYTES,
+	QLINK_STA_INFO_RX_BYTES64,
+	QLINK_STA_INFO_TX_BYTES64,
+	QLINK_STA_INFO_RX_DROP_MISC,
+	QLINK_STA_INFO_BEACON_RX,
+	QLINK_STA_INFO_SIGNAL,
+	QLINK_STA_INFO_SIGNAL_AVG,
+	QLINK_STA_INFO_RX_BITRATE,
+	QLINK_STA_INFO_TX_BITRATE,
+	QLINK_STA_INFO_RX_PACKETS,
+	QLINK_STA_INFO_TX_PACKETS,
+	QLINK_STA_INFO_TX_RETRIES,
+	QLINK_STA_INFO_TX_FAILED,
+	QLINK_STA_INFO_STA_FLAGS,
+	QLINK_STA_INFO_NUM,
+};
+
+/**
+ * struct qlink_sta_info_rate - STA rate statistics
+ *
+ * @rate: data rate in Mbps.
+ * @flags: bitmap of &enum qlink_sta_info_rate_flags.
+ * @mcs: 802.11-defined MCS index.
+ * nss: Number of Spatial Streams.
+ * @bw: bandwidth, one of &enum qlink_channel_width.
+ */
+struct qlink_sta_info_rate {
+	__le16 rate;
+	u8 flags;
+	u8 mcs;
+	u8 nss;
+	u8 bw;
+} __packed;
+
+/**
+ * struct qlink_sta_stats - data for QTN_TLV_ID_STA_STATS
+ *
+ * Carries statistics of a STA. Not all fields may be filled with
+ * valid values. Valid fields should be indicated as such using a bitmap of
+ * &enum qlink_sta_info. Bitmap is carried separately in a payload of
+ * QTN_TLV_ID_STA_STATS_MAP.
+ */
+struct qlink_sta_stats {
+	__le64 rx_bytes;
+	__le64 tx_bytes;
+	__le64 rx_beacon;
+	__le64 rx_duration;
+	__le64 t_offset;
+	__le32 connected_time;
+	__le32 inactive_time;
+	__le32 rx_packets;
+	__le32 tx_packets;
+	__le32 tx_retries;
+	__le32 tx_failed;
+	__le32 rx_dropped_misc;
+	__le32 beacon_loss_count;
+	__le32 expected_throughput;
+	struct qlink_sta_info_state sta_flags;
+	struct qlink_sta_info_rate txrate;
+	struct qlink_sta_info_rate rxrate;
+	__le16 llid;
+	__le16 plid;
+	u8 local_pm;
+	u8 peer_pm;
+	u8 nonpeer_pm;
+	u8 rx_beacon_signal_avg;
+	u8 plink_state;
+	u8 signal;
+	u8 signal_avg;
+	u8 rsvd[1];
+};
+
 #endif /* _QTN_QLINK_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index 37b78f00e8e5..19981d6440b6 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -164,3 +164,15 @@ enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val)
 		return QLINK_HIDDEN_SSID_NOT_IN_USE;
 	}
 }
+
+bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit,
+			   unsigned int arr_max_len)
+{
+	unsigned int idx = bit / BITS_PER_BYTE;
+	u8 mask = 1 << (bit - (idx * BITS_PER_BYTE));
+
+	if (idx >= arr_max_len)
+		return false;
+
+	return arr[idx] & mask;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 260383d6d109..6c24561eb41f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -69,5 +69,7 @@ void qlink_chandef_q2cfg(struct wiphy *wiphy,
 void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef,
 			 struct qlink_chandef *qch);
 enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val);
+bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit,
+			   unsigned int arr_max_len);
 
 #endif /* _QTN_FMAC_QLINK_UTIL_H_ */
-- 
2.11.0

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

* [PATCH 09/10] qtnfmac: keeping track of "generation" for STA info
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
                   ` (7 preceding siblings ...)
  2017-11-13 10:28 ` [PATCH 08/10] qtnfmac: modify GET_STA_STATS cmd format for back/forward compatibility Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-11-13 10:28 ` [PATCH 10/10] qtnfmac: support MAC address based access control Sergey Matyukevich
  9 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>

Keep generation in per-VIF data structure and increment it whenever STA
list is changed. Use generation value to fill struct station_info when
required.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 5 ++++-
 drivers/net/wireless/quantenna/qtnfmac/core.h     | 1 +
 drivers/net/wireless/quantenna/qtnfmac/event.c    | 5 +++--
 drivers/net/wireless/quantenna/qtnfmac/util.c     | 8 ++++++--
 drivers/net/wireless/quantenna/qtnfmac/util.h     | 4 ++--
 5 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index f5eb2cdefae2..452def343ad3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -418,6 +418,7 @@ qtnf_get_station(struct wiphy *wiphy, struct net_device *dev,
 {
 	struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
 
+	sinfo->generation = vif->generation;
 	return qtnf_cmd_get_sta_info(vif, mac, sinfo);
 }
 
@@ -439,11 +440,13 @@ qtnf_dump_station(struct wiphy *wiphy, struct net_device *dev,
 	ret = qtnf_cmd_get_sta_info(vif, sta_node->mac_addr, sinfo);
 
 	if (unlikely(ret == -ENOENT)) {
-		qtnf_sta_list_del(&vif->sta_list, mac);
+		qtnf_sta_list_del(vif, mac);
 		cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
 		sinfo->filled = 0;
 	}
 
+	sinfo->generation = vif->generation;
+
 	return ret;
 }
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index d7e295efb07d..e7bd21ed371b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -88,6 +88,7 @@ struct qtnf_vif {
 	struct work_struct reset_work;
 	struct qtnf_sta_list sta_list;
 	unsigned long cons_tx_timeout_cnt;
+	int generation;
 };
 
 struct qtnf_mac_info {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index b3489b5b5d9e..8a3d2b1194e4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -59,10 +59,11 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
 	pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac->macid, vif->vifid, sta_addr,
 		 frame_control);
 
-	qtnf_sta_list_add(&vif->sta_list, sta_addr);
+	qtnf_sta_list_add(vif, sta_addr);
 
 	sinfo.assoc_req_ies = NULL;
 	sinfo.assoc_req_ies_len = 0;
+	sinfo.generation = vif->generation;
 
 	payload_len = len - sizeof(*sta_assoc);
 	tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies;
@@ -132,7 +133,7 @@ qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif,
 	pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac->macid, vif->vifid,
 		 sta_addr, reason);
 
-	if (qtnf_sta_list_del(&vif->sta_list, sta_addr))
+	if (qtnf_sta_list_del(vif, sta_addr))
 		cfg80211_del_sta(vif->netdev, sta_deauth->sta_addr,
 				 GFP_KERNEL);
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.c b/drivers/net/wireless/quantenna/qtnfmac/util.c
index ed38e87471bf..e745733ba417 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/util.c
@@ -57,9 +57,10 @@ struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list,
 	return NULL;
 }
 
-struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_sta_list *list,
+struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_vif *vif,
 					const u8 *mac)
 {
+	struct qtnf_sta_list *list = &vif->sta_list;
 	struct qtnf_sta_node *node;
 
 	if (unlikely(!mac))
@@ -77,13 +78,15 @@ struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_sta_list *list,
 	ether_addr_copy(node->mac_addr, mac);
 	list_add_tail(&node->list, &list->head);
 	atomic_inc(&list->size);
+	++vif->generation;
 
 done:
 	return node;
 }
 
-bool qtnf_sta_list_del(struct qtnf_sta_list *list, const u8 *mac)
+bool qtnf_sta_list_del(struct qtnf_vif *vif, const u8 *mac)
 {
+	struct qtnf_sta_list *list = &vif->sta_list;
 	struct qtnf_sta_node *node;
 	bool ret = false;
 
@@ -93,6 +96,7 @@ bool qtnf_sta_list_del(struct qtnf_sta_list *list, const u8 *mac)
 		list_del(&node->list);
 		atomic_dec(&list->size);
 		kfree(node);
+		++vif->generation;
 		ret = true;
 	}
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.h b/drivers/net/wireless/quantenna/qtnfmac/util.h
index 0359eae8c24b..0d4d92b11540 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/util.h
@@ -26,9 +26,9 @@ struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list,
 					   const u8 *mac);
 struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list,
 						 size_t index);
-struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_sta_list *list,
+struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_vif *vif,
 					const u8 *mac);
-bool qtnf_sta_list_del(struct qtnf_sta_list *list, const u8 *mac);
+bool qtnf_sta_list_del(struct qtnf_vif *vif, const u8 *mac);
 
 void qtnf_sta_list_free(struct qtnf_sta_list *list);
 
-- 
2.11.0

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

* [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
                   ` (8 preceding siblings ...)
  2017-11-13 10:28 ` [PATCH 09/10] qtnfmac: keeping track of "generation" for STA info Sergey Matyukevich
@ 2017-11-13 10:28 ` Sergey Matyukevich
  2017-12-04 15:01   ` Kalle Valo
  9 siblings, 1 reply; 32+ messages in thread
From: Sergey Matyukevich @ 2017-11-13 10:28 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

From: Vasily Ulyanov <vulyanov@quantenna.com>

This allows a running AP to blacklist STAs by their MAC addresses
respecting the configured policy (either accept or deny unless listed).
It can be setup on .start_ap or with .set_mac_acl commands.

Signed-off-by: Vasily Ulyanov <vulyanov@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c  | 19 +++++++
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 62 ++++++++++++++++++++++
 drivers/net/wireless/quantenna/qtnfmac/commands.h  |  2 +
 drivers/net/wireless/quantenna/qtnfmac/core.h      |  1 +
 drivers/net/wireless/quantenna/qtnfmac/qlink.h     | 37 ++++++++++++-
 .../net/wireless/quantenna/qtnfmac/qlink_util.c    | 18 +++++++
 .../net/wireless/quantenna/qtnfmac/qlink_util.h    |  2 +
 7 files changed, 140 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 452def343ad3..89dc9cab647d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -778,6 +778,20 @@ static int qtnf_start_radar_detection(struct wiphy *wiphy,
 	return ret;
 }
 
+static int qtnf_set_mac_acl(struct wiphy *wiphy,
+			    struct net_device *dev,
+			    const struct cfg80211_acl_data *params)
+{
+	struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+	int ret;
+
+	ret = qtnf_cmd_set_mac_acl(vif, params);
+	if (ret)
+		pr_err("%s: failed to set mac ACL ret=%d\n", dev->name, ret);
+
+	return ret;
+}
+
 static struct cfg80211_ops qtn_cfg80211_ops = {
 	.add_virtual_intf	= qtnf_add_virtual_intf,
 	.change_virtual_intf	= qtnf_change_virtual_intf,
@@ -803,6 +817,7 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
 	.get_channel		= qtnf_get_channel,
 	.channel_switch		= qtnf_channel_switch,
 	.start_radar_detection	= qtnf_start_radar_detection,
+	.set_mac_acl		= qtnf_set_mac_acl,
 };
 
 static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
@@ -918,6 +933,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
 	wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
 	wiphy->mgmt_stypes = qtnf_mgmt_stypes;
 	wiphy->max_remain_on_channel_duration = 5000;
+	wiphy->max_acl_mac_addrs = mac->macinfo.max_acl_mac_addrs;
 
 	wiphy->iface_combinations = iface_comb;
 	wiphy->n_iface_combinations = 1;
@@ -932,6 +948,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
 			WIPHY_FLAG_AP_UAPSD |
 			WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
+	if (wiphy->max_acl_mac_addrs > 0)
+		wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
+
 	wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
 				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 38b9c1078058..6ffe4837bbdb 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -162,6 +162,14 @@ static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type,
 		memcpy(tlv->ie_data, buf, len);
 }
 
+static inline size_t qtnf_cmd_acl_data_size(const struct cfg80211_acl_data *acl)
+{
+	size_t size = sizeof(struct qlink_acl_data) +
+		      acl->n_acl_entries * sizeof(struct qlink_mac_address);
+
+	return size;
+}
+
 static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
 				      const struct cfg80211_ap_settings *s)
 {
@@ -178,6 +186,9 @@ static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
 	if (cfg80211_chandef_valid(&s->chandef))
 		len += sizeof(struct qlink_tlv_chandef);
 
+	if (s->acl)
+		len += qtnf_cmd_acl_data_size(s->acl);
+
 	if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) {
 		pr_err("VIF%u.%u: can not fit AP settings: %u\n",
 		       vif->mac->macid, vif->vifid, len);
@@ -283,6 +294,16 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
 		memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap));
 	}
 
+	if (s->acl) {
+		size_t acl_size = qtnf_cmd_acl_data_size(s->acl);
+		struct qlink_tlv_hdr *tlv =
+			skb_put(cmd_skb, sizeof(*tlv) + acl_size);
+
+		tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA);
+		tlv->len = cpu_to_le16(acl_size);
+		qlink_acl_data_cfg2q(s->acl, (struct qlink_acl_data *)tlv->val);
+	}
+
 	qtnf_bus_lock(vif->mac->bus);
 
 	ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
@@ -1206,6 +1227,7 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
 	mac_info->radar_detect_widths =
 			qlink_chan_width_mask_to_nl(le16_to_cpu(
 					resp_info->radar_detect_widths));
+	mac_info->max_acl_mac_addrs = le32_to_cpu(resp_info->max_acl_mac_addrs);
 
 	memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask,
 	       sizeof(mac_info->ht_cap_mod_mask));
@@ -2609,3 +2631,43 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
 
 	return ret;
 }
+
+int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
+			 const struct cfg80211_acl_data *params)
+{
+	struct qtnf_bus *bus = vif->mac->bus;
+	struct sk_buff *cmd_skb;
+	struct qlink_cmd_set_mac_acl *cmd;
+	u16 res_code;
+	int ret;
+
+	cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+					    QLINK_CMD_SET_MAC_ACL,
+					    sizeof(*cmd) +
+					    qtnf_cmd_acl_data_size(params));
+	if (unlikely(!cmd_skb))
+		return -ENOMEM;
+
+	cmd = (struct qlink_cmd_set_mac_acl *)cmd_skb->data;
+	qlink_acl_data_cfg2q(params, &cmd->acl);
+
+	qtnf_bus_lock(bus);
+	ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
+	qtnf_bus_unlock(bus);
+
+	if (unlikely(ret))
+		return ret;
+
+	switch (res_code) {
+	case QLINK_CMD_RESULT_OK:
+		break;
+	case QLINK_CMD_RESULT_INVALID:
+		ret = -EINVAL;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index 07a957af9a58..69a7d56f7e58 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -79,5 +79,7 @@ int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef);
 int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
 		       const struct cfg80211_chan_def *chdef,
 		       u32 cac_time_ms);
+int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
+			 const struct cfg80211_acl_data *params);
 
 #endif /* QLINK_COMMANDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index e7bd21ed371b..c10900162297 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -103,6 +103,7 @@ struct qtnf_mac_info {
 	u8 sretry_limit;
 	u8 coverage_class;
 	u8 radar_detect_widths;
+	u32 max_acl_mac_addrs;
 	struct ieee80211_ht_cap ht_cap_mod_mask;
 	struct ieee80211_vht_cap vht_cap_mod_mask;
 	struct ieee80211_iface_limit *limits;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 5d98000b0f5b..6a1f960228a1 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -19,7 +19,7 @@
 
 #include <linux/ieee80211.h>
 
-#define QLINK_PROTO_VER		9
+#define QLINK_PROTO_VER		10
 
 #define QLINK_MACID_RSVD		0xFF
 #define QLINK_VIFID_RSVD		0xFF
@@ -239,6 +239,7 @@ enum qlink_cmd_type {
 	QLINK_CMD_START_CAC		= 0x001D,
 	QLINK_CMD_START_AP		= 0x0021,
 	QLINK_CMD_STOP_AP		= 0x0022,
+	QLINK_CMD_SET_MAC_ACL		= 0x0023,
 	QLINK_CMD_GET_STA_INFO		= 0x0030,
 	QLINK_CMD_ADD_KEY		= 0x0040,
 	QLINK_CMD_DEL_KEY		= 0x0041,
@@ -640,6 +641,38 @@ struct qlink_cmd_start_cac {
 	__le32 cac_time_ms;
 } __packed;
 
+enum qlink_acl_policy {
+	QLINK_ACL_POLICY_ACCEPT_UNLESS_LISTED,
+	QLINK_ACL_POLICY_DENY_UNLESS_LISTED,
+};
+
+struct qlink_mac_address {
+	u8 addr[ETH_ALEN];
+} __packed;
+
+/**
+ * struct qlink_acl_data - ACL data
+ *
+ * @policy: filter policy, one of &enum qlink_acl_policy.
+ * @num_entries: number of MAC addresses in array.
+ * @mac_address: MAC addresses array.
+ */
+struct qlink_acl_data {
+	__le32 policy;
+	__le32 num_entries;
+	struct qlink_mac_address mac_addrs[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_set_mac_acl - data for QLINK_CMD_SET_MAC_ACL command
+ *
+ * @acl: ACL data.
+ */
+struct qlink_cmd_set_mac_acl {
+	struct qlink_cmd chdr;
+	struct qlink_acl_data acl;
+} __packed;
+
 /* QLINK Command Responses messages related definitions
  */
 
@@ -701,6 +734,7 @@ struct qlink_resp_get_mac_info {
 	struct ieee80211_ht_cap ht_cap_mod_mask;
 	__le16 max_ap_assoc_sta;
 	__le16 radar_detect_widths;
+	__le32 max_acl_mac_addrs;
 	u8 bands_cap;
 	u8 rsvd[1];
 	u8 var_info[0];
@@ -1049,6 +1083,7 @@ enum qlink_tlv_id {
 	QTN_TLV_ID_SEQ			= 0x0303,
 	QTN_TLV_ID_IE_SET		= 0x0305,
 	QTN_TLV_ID_EXT_CAPABILITY_MASK	= 0x0306,
+	QTN_TLV_ID_ACL_DATA		= 0x0307,
 };
 
 struct qlink_tlv_hdr {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index 19981d6440b6..aeeda81b09ea 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -176,3 +176,21 @@ bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit,
 
 	return arr[idx] & mask;
 }
+
+void qlink_acl_data_cfg2q(const struct cfg80211_acl_data *acl,
+			  struct qlink_acl_data *qacl)
+{
+	switch (acl->acl_policy) {
+	case NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED:
+		qacl->policy =
+			cpu_to_le32(QLINK_ACL_POLICY_ACCEPT_UNLESS_LISTED);
+		break;
+	case NL80211_ACL_POLICY_DENY_UNLESS_LISTED:
+		qacl->policy = cpu_to_le32(QLINK_ACL_POLICY_DENY_UNLESS_LISTED);
+		break;
+	}
+
+	qacl->num_entries = cpu_to_le32(acl->n_acl_entries);
+	memcpy(qacl->mac_addrs, acl->mac_addrs,
+	       acl->n_acl_entries * sizeof(*qacl->mac_addrs));
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 6c24561eb41f..54caeb38917c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -71,5 +71,7 @@ void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef,
 enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val);
 bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit,
 			   unsigned int arr_max_len);
+void qlink_acl_data_cfg2q(const struct cfg80211_acl_data *acl,
+			  struct qlink_acl_data *qacl);
 
 #endif /* _QTN_FMAC_QLINK_UTIL_H_ */
-- 
2.11.0

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

* Re: [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware
  2017-11-13 10:28 ` [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware Sergey Matyukevich
@ 2017-12-04 14:46   ` Kalle Valo
  2017-12-05 16:24     ` Sergey Matyukevich
  0 siblings, 1 reply; 32+ messages in thread
From: Kalle Valo @ 2017-12-04 14:46 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-wireless, Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> writes:

> Center frequency is not enough to describe the channel in HT and VHT
> modes. For 40MHz and 80MHz channels both primary channel and center
> frequency should be specified in order to qualify channel completely.
> This change adds primary channel info into qlink_chandef structure.
>
> Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>

[...]

> +/**
>   * struct qlink_chandef - qlink channel definition
>   *
> + * @chan: primary channel definition
>   * @center_freq1: center frequency of first segment
>   * @center_freq2: center frequency of second segment (80+80 only)
>   * @width: channel width, one of @enum qlink_channel_width
>   */
>  struct qlink_chandef {
> +	struct qlink_channel chan;
>  	__le16 center_freq1;
>  	__le16 center_freq2;
>  	u8 width;
> -	u8 rsvd[3];
> +	u8 rsvd;
>  } __packed;

Doesn't this break backwards compatibility with the older firmware? The
basic princinple is that old firmware images continue to work with newer
driver (or there will be a firmware image with new name, eg. fw-2.bin).
You can check how iwlwifi does that.

As this is a new driver I guess it doesn't matter that much to break it,
but please keep this in mind in the future.

-- 
Kalle Valo

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

* Re: [PATCH 03/10] qtnfmac: add support for radar detection and CAC
  2017-11-13 10:28 ` [PATCH 03/10] qtnfmac: add support for radar detection and CAC Sergey Matyukevich
@ 2017-12-04 14:49   ` Kalle Valo
  2017-12-04 14:52     ` Kalle Valo
  0 siblings, 1 reply; 32+ messages in thread
From: Kalle Valo @ 2017-12-04 14:49 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-wireless, Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> writes:

> From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
>
> Implement two parts of radar handling logic:
> - cfg80211 .start_radar_detect callback to allow nl80211 to initiate CAC
> - radar event to allow wlan device to advertize CAC and radar events
>
> Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>

[...]

> +int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
> +		       const struct cfg80211_chan_def *chdef,
> +		       u32 cac_time_ms)
> +{
> +	struct qtnf_bus *bus = vif->mac->bus;
> +	struct sk_buff *cmd_skb;
> +	struct qlink_cmd_start_cac *cmd;
> +	int ret;
> +	u16 res_code;
> +
> +	cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
> +					    QLINK_CMD_START_CAC,
> +					    sizeof(*cmd));
> +	if (unlikely(!cmd_skb))
> +		return -ENOMEM;

The unlikely() looks pretty useless here. likely() and unlikely() are
supposed to be used in cases where it matters and the improvment can be
measured, I doubt that's the case here.

-- 
Kalle Valo

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

* Re: [PATCH 03/10] qtnfmac: add support for radar detection and CAC
  2017-12-04 14:49   ` Kalle Valo
@ 2017-12-04 14:52     ` Kalle Valo
  2017-12-05 16:27       ` Sergey Matyukevich
  0 siblings, 1 reply; 32+ messages in thread
From: Kalle Valo @ 2017-12-04 14:52 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-wireless, Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

Kalle Valo <kvalo@codeaurora.org> writes:

> Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> writes:
>
>> From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
>>
>> Implement two parts of radar handling logic:
>> - cfg80211 .start_radar_detect callback to allow nl80211 to initiate CAC
>> - radar event to allow wlan device to advertize CAC and radar events
>>
>> Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
>
> [...]
>
>> +int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
>> +		       const struct cfg80211_chan_def *chdef,
>> +		       u32 cac_time_ms)
>> +{
>> +	struct qtnf_bus *bus = vif->mac->bus;
>> +	struct sk_buff *cmd_skb;
>> +	struct qlink_cmd_start_cac *cmd;
>> +	int ret;
>> +	u16 res_code;
>> +
>> +	cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
>> +					    QLINK_CMD_START_CAC,
>> +					    sizeof(*cmd));
>> +	if (unlikely(!cmd_skb))
>> +		return -ENOMEM;
>
> The unlikely() looks pretty useless here. likely() and unlikely() are
> supposed to be used in cases where it matters and the improvment can be
> measured, I doubt that's the case here.

But no need to resend just because of this.

-- 
Kalle Valo

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-11-13 10:28 ` [PATCH 10/10] qtnfmac: support MAC address based access control Sergey Matyukevich
@ 2017-12-04 15:01   ` Kalle Valo
  2017-12-05 16:00     ` Sergey Matyukevich
  0 siblings, 1 reply; 32+ messages in thread
From: Kalle Valo @ 2017-12-04 15:01 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: linux-wireless, Igor Mitsyanko, Avinash Patil, Vasily Ulyanov

Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> writes:

> From: Vasily Ulyanov <vulyanov@quantenna.com>
>
> This allows a running AP to blacklist STAs by their MAC addresses
> respecting the configured policy (either accept or deny unless listed).
> It can be setup on .start_ap or with .set_mac_acl commands.
>
> Signed-off-by: Vasily Ulyanov <vulyanov@quantenna.com>

[...]

> @@ -918,6 +933,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
>  	wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
>  	wiphy->mgmt_stypes = qtnf_mgmt_stypes;
>  	wiphy->max_remain_on_channel_duration = 5000;
> +	wiphy->max_acl_mac_addrs = mac->macinfo.max_acl_mac_addrs;
>  
>  	wiphy->iface_combinations = iface_comb;
>  	wiphy->n_iface_combinations = 1;
> @@ -932,6 +948,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
>  			WIPHY_FLAG_AP_UAPSD |
>  			WIPHY_FLAG_HAS_CHANNEL_SWITCH;
>  
> +	if (wiphy->max_acl_mac_addrs > 0)
> +		wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;

Conditonally enabling WIPHY_FLAG_HAVE_AP_SME looks somewhat suspicious
to me and from a quick search I don't see any other driver doing
something similar. Can you explain why AP_SME is related to MAC ACL?

-- 
Kalle Valo

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-04 15:01   ` Kalle Valo
@ 2017-12-05 16:00     ` Sergey Matyukevich
  2017-12-18 12:43       ` Sergey Matyukevich
  2017-12-18 14:01       ` Kalle Valo
  0 siblings, 2 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-12-05 16:00 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Igor Mitsyanko, Avinash Patil

Hello Kalle,

> Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> writes:
> 
> > From: Vasily Ulyanov <vulyanov@quantenna.com>
> >
> > This allows a running AP to blacklist STAs by their MAC addresses
> > respecting the configured policy (either accept or deny unless listed).
> > It can be setup on .start_ap or with .set_mac_acl commands.
> >
> > Signed-off-by: Vasily Ulyanov <vulyanov@quantenna.com>
> 
> [...]
> 
> > @@ -918,6 +933,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
> >       wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
> >       wiphy->mgmt_stypes = qtnf_mgmt_stypes;
> >       wiphy->max_remain_on_channel_duration = 5000;
> > +     wiphy->max_acl_mac_addrs = mac->macinfo.max_acl_mac_addrs;
> >
> >       wiphy->iface_combinations = iface_comb;
> >       wiphy->n_iface_combinations = 1;
> > @@ -932,6 +948,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
> >                       WIPHY_FLAG_AP_UAPSD |
> >                       WIPHY_FLAG_HAS_CHANNEL_SWITCH;
> >
> > +     if (wiphy->max_acl_mac_addrs > 0)
> > +             wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
> 
> Conditonally enabling WIPHY_FLAG_HAVE_AP_SME looks somewhat suspicious
> to me and from a quick search I don't see any other driver doing
> something similar. Can you explain why AP_SME is related to MAC ACL?

Wireless core performs several sanity check on wiphy registration: see
wiphy_register implementation in net/wireless/core.c. One of those
checks is as follows: if max_acl_mac_addrs is non-zero, then two
conditions should be fulfilled:
- cfg80211 set_mac_acl callback should be available
- WIPHY_FLAG_HAVE_AP_SME should be set

The first condition is perfectly sane: it should be possible to
set MACs to enable ACL feature. The second condition is that clear
to me, but we have to comply in order to pass wiphy_registration.
I assume that it somehow related to hostapd logic, but I haven't
yet check that myself.

The conditional enablement of WIPHY_FLAG_HAVE_AP_SME is easy to
explain. We enable use firmware/hardware features to implement
MAC-based ACL. So we enable it only if firmware report non-zero
max_acl_mac_addrs value.

Regards,
Sergey

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

* Re: [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware
  2017-12-04 14:46   ` Kalle Valo
@ 2017-12-05 16:24     ` Sergey Matyukevich
  2018-01-12 11:23       ` Kalle Valo
  0 siblings, 1 reply; 32+ messages in thread
From: Sergey Matyukevich @ 2017-12-05 16:24 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Igor Mitsyanko, Avinash Patil

Hello Kalle,

> > Center frequency is not enough to describe the channel in HT and VHT
> > modes. For 40MHz and 80MHz channels both primary channel and center
> > frequency should be specified in order to qualify channel completely.
> > This change adds primary channel info into qlink_chandef structure.
> >
> > Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
> 
> [...]
> 
> > +/**
> >   * struct qlink_chandef - qlink channel definition
> >   *
> > + * @chan: primary channel definition
> >   * @center_freq1: center frequency of first segment
> >   * @center_freq2: center frequency of second segment (80+80 only)
> >   * @width: channel width, one of @enum qlink_channel_width
> >   */
> >  struct qlink_chandef {
> > +     struct qlink_channel chan;
> >       __le16 center_freq1;
> >       __le16 center_freq2;
> >       u8 width;
> > -     u8 rsvd[3];
> > +     u8 rsvd;
> >  } __packed;
> 
> Doesn't this break backwards compatibility with the older firmware? The
> basic princinple is that old firmware images continue to work with newer
> driver (or there will be a firmware image with new name, eg. fw-2.bin).
> You can check how iwlwifi does that.

Yes, it breaks. That is why we increment qlink protocol version in each
change affecting backwards compatibility. So driver is going to work only
with matching firmware. This is a very simplistic approach, but it looks
reasonable for current stage of development since we keep adding features.

> As this is a new driver I guess it doesn't matter that much to break it,
> but please keep this in mind in the future.

Sure, we keep that in mind. Though we haven't settled on any
specific approach so far.

Regards,
Sergey

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

* Re: [PATCH 03/10] qtnfmac: add support for radar detection and CAC
  2017-12-04 14:52     ` Kalle Valo
@ 2017-12-05 16:27       ` Sergey Matyukevich
  0 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-12-05 16:27 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Igor Mitsyanko, Avinash Patil

> >> +int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
> >> +                   const struct cfg80211_chan_def *chdef,
> >> +                   u32 cac_time_ms)
> >> +{
> >> +    struct qtnf_bus *bus = vif->mac->bus;
> >> +    struct sk_buff *cmd_skb;
> >> +    struct qlink_cmd_start_cac *cmd;
> >> +    int ret;
> >> +    u16 res_code;
> >> +
> >> +    cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
> >> +                                        QLINK_CMD_START_CAC,
> >> +                                        sizeof(*cmd));
> >> +    if (unlikely(!cmd_skb))
> >> +            return -ENOMEM;
> >
> > The unlikely() looks pretty useless here. likely() and unlikely() are
> > supposed to be used in cases where it matters and the improvment can be
> > measured, I doubt that's the case here.

Noted once again. Though it is not easy to get rid of some habits sometimes :)

Regards,
Sergey

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-05 16:00     ` Sergey Matyukevich
@ 2017-12-18 12:43       ` Sergey Matyukevich
  2017-12-18 14:01       ` Kalle Valo
  1 sibling, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2017-12-18 12:43 UTC (permalink / raw)
  To: Kalle Valo, linux-wireless, Igor Mitsyanko, Avinash Patil

Hello Kalle,

> > > This allows a running AP to blacklist STAs by their MAC addresses
> > > respecting the configured policy (either accept or deny unless listed).
> > > It can be setup on .start_ap or with .set_mac_acl commands.
> > >
> > > Signed-off-by: Vasily Ulyanov <vulyanov@quantenna.com>
> >
> > [...]
> >
> > > @@ -918,6 +933,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
> > >       wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
> > >       wiphy->mgmt_stypes = qtnf_mgmt_stypes;
> > >       wiphy->max_remain_on_channel_duration = 5000;
> > > +     wiphy->max_acl_mac_addrs = mac->macinfo.max_acl_mac_addrs;
> > >
> > >       wiphy->iface_combinations = iface_comb;
> > >       wiphy->n_iface_combinations = 1;
> > > @@ -932,6 +948,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
> > >                       WIPHY_FLAG_AP_UAPSD |
> > >                       WIPHY_FLAG_HAS_CHANNEL_SWITCH;
> > >
> > > +     if (wiphy->max_acl_mac_addrs > 0)
> > > +             wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
> >
> > Conditonally enabling WIPHY_FLAG_HAVE_AP_SME looks somewhat suspicious
> > to me and from a quick search I don't see any other driver doing
> > something similar. Can you explain why AP_SME is related to MAC ACL?
> 
> Wireless core performs several sanity check on wiphy registration: see
> wiphy_register implementation in net/wireless/core.c. One of those
> checks is as follows: if max_acl_mac_addrs is non-zero, then two
> conditions should be fulfilled:
> - cfg80211 set_mac_acl callback should be available
> - WIPHY_FLAG_HAVE_AP_SME should be set
> 
> The first condition is perfectly sane: it should be possible to
> set MACs to enable ACL feature. The second condition is that clear
> to me, but we have to comply in order to pass wiphy_registration.
> I assume that it somehow related to hostapd logic, but I haven't
> yet check that myself.
> 
> The conditional enablement of WIPHY_FLAG_HAVE_AP_SME is easy to
> explain. We enable use firmware/hardware features to implement
> MAC-based ACL. So we enable it only if firmware report non-zero
> max_acl_mac_addrs value.

I noticed that this patch series is marked as 'Deferred' in linux-wireless
patchwork. Could you please take a look at my answers to your review comments.
Let us know if you still have concerns, so that we could proceed accordingly,
e.g. fix things and resubmit this series.

Regards,
Sergey

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-05 16:00     ` Sergey Matyukevich
  2017-12-18 12:43       ` Sergey Matyukevich
@ 2017-12-18 14:01       ` Kalle Valo
  2017-12-18 16:18         ` Sergey Matyukevich
  1 sibling, 1 reply; 32+ messages in thread
From: Kalle Valo @ 2017-12-18 14:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Johannes Berg

Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> writes:

> Hello Kalle,
>
>> Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> writes:
>> 
>> > From: Vasily Ulyanov <vulyanov@quantenna.com>
>> >
>> > This allows a running AP to blacklist STAs by their MAC addresses
>> > respecting the configured policy (either accept or deny unless listed).
>> > It can be setup on .start_ap or with .set_mac_acl commands.
>> >
>> > Signed-off-by: Vasily Ulyanov <vulyanov@quantenna.com>
>> 
>> [...]
>> 
>> > @@ -918,6 +933,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
>> >       wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
>> >       wiphy->mgmt_stypes = qtnf_mgmt_stypes;
>> >       wiphy->max_remain_on_channel_duration = 5000;
>> > +     wiphy->max_acl_mac_addrs = mac->macinfo.max_acl_mac_addrs;
>> >
>> >       wiphy->iface_combinations = iface_comb;
>> >       wiphy->n_iface_combinations = 1;
>> > @@ -932,6 +948,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
>> >                       WIPHY_FLAG_AP_UAPSD |
>> >                       WIPHY_FLAG_HAS_CHANNEL_SWITCH;
>> >
>> > +     if (wiphy->max_acl_mac_addrs > 0)
>> > +             wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
>> 
>> Conditonally enabling WIPHY_FLAG_HAVE_AP_SME looks somewhat suspicious
>> to me and from a quick search I don't see any other driver doing
>> something similar. Can you explain why AP_SME is related to MAC ACL?
>
> Wireless core performs several sanity check on wiphy registration: see
> wiphy_register implementation in net/wireless/core.c. One of those
> checks is as follows: if max_acl_mac_addrs is non-zero, then two
> conditions should be fulfilled:
> - cfg80211 set_mac_acl callback should be available
> - WIPHY_FLAG_HAVE_AP_SME should be set
>
> The first condition is perfectly sane: it should be possible to
> set MACs to enable ACL feature. The second condition is that clear
> to me, but we have to comply in order to pass wiphy_registration.
> I assume that it somehow related to hostapd logic, but I haven't
> yet check that myself.
>
> The conditional enablement of WIPHY_FLAG_HAVE_AP_SME is easy to
> explain. We enable use firmware/hardware features to implement
> MAC-based ACL. So we enable it only if firmware report non-zero
> max_acl_mac_addrs value.

To me this looks like an ugly hack, either your firmware has AP_SME
support or not. It should not be enabled based on what settings user
space provides. If cfg80211 is giving you problems you should fix
cfg80211, not try to a workaround it in the driver like the vendor
drivers do. We work differently in upstream.

But Johannes (CCed) might think differently, and if he acks this, then
I'll of course take this.

-- 
Kalle Valo

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-18 14:01       ` Kalle Valo
@ 2017-12-18 16:18         ` Sergey Matyukevich
  2017-12-19  9:38           ` Johannes Berg
  0 siblings, 1 reply; 32+ messages in thread
From: Sergey Matyukevich @ 2017-12-18 16:18 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Igor Mitsyanko, Avinash Patil, Johannes Berg

Hello Kalle,

> >> > This allows a running AP to blacklist STAs by their MAC addresses
> >> > respecting the configured policy (either accept or deny unless listed).
> >> > It can be setup on .start_ap or with .set_mac_acl commands.
> >> >
> >> > Signed-off-by: Vasily Ulyanov <vulyanov@quantenna.com>
> >>
> >> [...]
> >>
> >> > @@ -918,6 +933,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
> >> >       wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
> >> >       wiphy->mgmt_stypes = qtnf_mgmt_stypes;
> >> >       wiphy->max_remain_on_channel_duration = 5000;
> >> > +     wiphy->max_acl_mac_addrs = mac->macinfo.max_acl_mac_addrs;
> >> >
> >> >       wiphy->iface_combinations = iface_comb;
> >> >       wiphy->n_iface_combinations = 1;
> >> > @@ -932,6 +948,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
> >> >                       WIPHY_FLAG_AP_UAPSD |
> >> >                       WIPHY_FLAG_HAS_CHANNEL_SWITCH;
> >> >
> >> > +     if (wiphy->max_acl_mac_addrs > 0)
> >> > +             wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
> >>
> >> Conditonally enabling WIPHY_FLAG_HAVE_AP_SME looks somewhat suspicious
> >> to me and from a quick search I don't see any other driver doing
> >> something similar. Can you explain why AP_SME is related to MAC ACL?
> >
> > Wireless core performs several sanity check on wiphy registration: see
> > wiphy_register implementation in net/wireless/core.c. One of those
> > checks is as follows: if max_acl_mac_addrs is non-zero, then two
> > conditions should be fulfilled:
> > - cfg80211 set_mac_acl callback should be available
> > - WIPHY_FLAG_HAVE_AP_SME should be set
> >
> > The first condition is perfectly sane: it should be possible to
> > set MACs to enable ACL feature. The second condition is that clear
> > to me, but we have to comply in order to pass wiphy_registration.
> > I assume that it somehow related to hostapd logic, but I haven't
> > yet check that myself.
> >
> > The conditional enablement of WIPHY_FLAG_HAVE_AP_SME is easy to
> > explain. We enable use firmware/hardware features to implement
> > MAC-based ACL. So we enable it only if firmware report non-zero
> > max_acl_mac_addrs value.
> 
> To me this looks like an ugly hack, either your firmware has AP_SME
> support or not. It should not be enabled based on what settings user
> space provides. If cfg80211 is giving you problems you should fix
> cfg80211, not try to a workaround it in the driver like the vendor
> drivers do. We work differently in upstream.
> 
> But Johannes (CCed) might think differently, and if he acks this, then
> I'll of course take this.

I took a closer look at this patch. It turns out that this conditional
enablement of WIPHY_FLAG_HAVE_AP_SME is completely redundant here. This
capability is already enabled unconditionally (though not visible in diff)
for normal hostapd operations with FullMAC driver which mostly
handles STAs in FW.

Thanks for catching. In fact, those two lines should be removed.
I will update the patch and resubmit the whole series.


Meanwhile now it is not yet clear to me what should be done for driver which
supports MAC-based ACL, but not full-fledged AP SME. Wireless core expects
WIPHY_FLAG_HAVE_AP_SME to be set if driver supports MAC-based ACL. On the
other hand, hostapd handles WIPHY_FLAG_HAVE_AP_SME and max_acl_mac_addrs
independently, expecting certain things from drivers that advertise
WIPHY_FLAG_HAVE_AP_SME.

Regards,
Sergey

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-18 16:18         ` Sergey Matyukevich
@ 2017-12-19  9:38           ` Johannes Berg
  2017-12-19 10:29             ` Sergey Matyukevich
  0 siblings, 1 reply; 32+ messages in thread
From: Johannes Berg @ 2017-12-19  9:38 UTC (permalink / raw)
  To: Sergey Matyukevich, Kalle Valo
  Cc: linux-wireless, Igor Mitsyanko, Avinash Patil

On Mon, 2017-12-18 at 19:18 +0300, Sergey Matyukevich wrote:

> Meanwhile now it is not yet clear to me what should be done for driver which
> supports MAC-based ACL, but not full-fledged AP SME.

Are you sure that such a device can even exist? It'd have to drop the
auth frames, so they can't be handled by the host? Is there much point
in that?

johannes

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-19  9:38           ` Johannes Berg
@ 2017-12-19 10:29             ` Sergey Matyukevich
  2017-12-19 10:35               ` Johannes Berg
  0 siblings, 1 reply; 32+ messages in thread
From: Sergey Matyukevich @ 2017-12-19 10:29 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Kalle Valo, linux-wireless, Igor Mitsyanko, Avinash Patil

Hello Johannes,

> > Meanwhile now it is not yet clear to me what should be done for driver which
> > supports MAC-based ACL, but not full-fledged AP SME.
> 
> Are you sure that such a device can even exist? It'd have to drop the
> auth frames, so they can't be handled by the host? Is there much point
> in that?

I guess it should be possible to do some kind of source address filtering
in hardware. But it looks like your question is whether it makes sense
or not. Probably not, I have no idea.

By the way, what do you think about making MAC-based ACL capability the
first bit in enum nl80211_ap_sme_features ?

Regards,
Sergey

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-19 10:29             ` Sergey Matyukevich
@ 2017-12-19 10:35               ` Johannes Berg
  2017-12-19 10:42                 ` Sergey Matyukevich
  0 siblings, 1 reply; 32+ messages in thread
From: Johannes Berg @ 2017-12-19 10:35 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: Kalle Valo, linux-wireless, Igor Mitsyanko, Avinash Patil

Hi,

> I guess it should be possible to do some kind of source address filtering
> in hardware. But it looks like your question is whether it makes sense
> or not. Probably not, I have no idea.

Either way, I see no reason to support it if nobody has a driver for it
:)

> By the way, what do you think about making MAC-based ACL capability the
> first bit in enum nl80211_ap_sme_features ?

No issues with that; I thought we already had some ACL feature bit
though?

johannes

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-19 10:35               ` Johannes Berg
@ 2017-12-19 10:42                 ` Sergey Matyukevich
  2017-12-19 10:59                   ` Johannes Berg
  0 siblings, 1 reply; 32+ messages in thread
From: Sergey Matyukevich @ 2017-12-19 10:42 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Kalle Valo, linux-wireless, Igor Mitsyanko, Avinash Patil

Hello Johannes,

> > I guess it should be possible to do some kind of source address filtering
> > in hardware. But it looks like your question is whether it makes sense
> > or not. Probably not, I have no idea.
> 
> Either way, I see no reason to support it if nobody has a driver for it
> :)
> 
> > By the way, what do you think about making MAC-based ACL capability the
> > first bit in enum nl80211_ap_sme_features ?
> 
> No issues with that; I thought we already had some ACL feature bit
> though?

Not yet. At the moment enum nl80211_ap_sme_features in uapi/linux/nl80211.h
is commented out. For MAC-based ACL the following things are being checked
on wiphy registration: complete flag WIPHY_FLAG_HAVE_AP_SME, non-zero
max_acl_mac_addrs, and set_mac_acl cfg80211 callback.

I will send an RFC patch, lets see how it is going to look like...

Regards,
Sergey

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-19 10:42                 ` Sergey Matyukevich
@ 2017-12-19 10:59                   ` Johannes Berg
  2017-12-19 11:19                     ` Sergey Matyukevich
  0 siblings, 1 reply; 32+ messages in thread
From: Johannes Berg @ 2017-12-19 10:59 UTC (permalink / raw)
  To: Sergey Matyukevich
  Cc: Kalle Valo, linux-wireless, Igor Mitsyanko, Avinash Patil

On Tue, 2017-12-19 at 13:42 +0300, Sergey Matyukevich wrote:

> Not yet. At the moment enum nl80211_ap_sme_features in uapi/linux/nl80211.h
> is commented out. For MAC-based ACL the following things are being checked
> on wiphy registration: complete flag WIPHY_FLAG_HAVE_AP_SME, non-zero
> max_acl_mac_addrs, and set_mac_acl cfg80211 callback.

I guess that's enough then? Userspace can check max_acl_mac_addrs as
well, so it can just use that?

johannes

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-19 10:59                   ` Johannes Berg
@ 2017-12-19 11:19                     ` Sergey Matyukevich
  2017-12-19 12:37                       ` Arend van Spriel
  0 siblings, 1 reply; 32+ messages in thread
From: Sergey Matyukevich @ 2017-12-19 11:19 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Kalle Valo, linux-wireless, Igor Mitsyanko, Avinash Patil

> > Not yet. At the moment enum nl80211_ap_sme_features in uapi/linux/nl80211.h
> > is commented out. For MAC-based ACL the following things are being checked
> > on wiphy registration: complete flag WIPHY_FLAG_HAVE_AP_SME, non-zero
> > max_acl_mac_addrs, and set_mac_acl cfg80211 callback.
> 
> I guess that's enough then? Userspace can check max_acl_mac_addrs as
> well, so it can just use that?

Correct, that is what hostapd is doing. I was simply surprised by the fact
that MAC-based ACL support implies full-fledged AP SME support. Though
your almost convinced me that this is ok and other wireless cards simply
do not exist.

Regards,
Sergey

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-19 11:19                     ` Sergey Matyukevich
@ 2017-12-19 12:37                       ` Arend van Spriel
  2017-12-19 16:58                         ` Johannes Berg
  0 siblings, 1 reply; 32+ messages in thread
From: Arend van Spriel @ 2017-12-19 12:37 UTC (permalink / raw)
  To: Johannes Berg, Kalle Valo, linux-wireless, Igor Mitsyanko, Avinash Patil

On 12/19/2017 12:19 PM, Sergey Matyukevich wrote:
>>> Not yet. At the moment enum nl80211_ap_sme_features in uapi/linux/nl80211.h
>>> is commented out. For MAC-based ACL the following things are being checked
>>> on wiphy registration: complete flag WIPHY_FLAG_HAVE_AP_SME, non-zero
>>> max_acl_mac_addrs, and set_mac_acl cfg80211 callback.
>>
>> I guess that's enough then? Userspace can check max_acl_mac_addrs as
>> well, so it can just use that?
>
> Correct, that is what hostapd is doing. I was simply surprised by the fact
> that MAC-based ACL support implies full-fledged AP SME support. Though
> your almost convinced me that this is ok and other wireless cards simply
> do not exist.

So the question seems to be here: what shall drivers/firmware implement 
to allow flag WIPHY_FLAG_HAVE_AP_SME being set. The kerneldoc is a bit 
short in providing guidance:

  * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME

Regards,
Arend

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-19 12:37                       ` Arend van Spriel
@ 2017-12-19 16:58                         ` Johannes Berg
  2017-12-19 22:13                           ` Arend Van Spriel
  0 siblings, 1 reply; 32+ messages in thread
From: Johannes Berg @ 2017-12-19 16:58 UTC (permalink / raw)
  To: Arend van Spriel, Kalle Valo, linux-wireless, Igor Mitsyanko,
	Avinash Patil

On Tue, 2017-12-19 at 13:37 +0100, Arend van Spriel wrote:
> On 12/19/2017 12:19 PM, Sergey Matyukevich wrote:
> > > > Not yet. At the moment enum nl80211_ap_sme_features in uapi/linux/nl80211.h
> > > > is commented out. For MAC-based ACL the following things are being checked
> > > > on wiphy registration: complete flag WIPHY_FLAG_HAVE_AP_SME, non-zero
> > > > max_acl_mac_addrs, and set_mac_acl cfg80211 callback.
> > > 
> > > I guess that's enough then? Userspace can check max_acl_mac_addrs as
> > > well, so it can just use that?
> > 
> > Correct, that is what hostapd is doing. I was simply surprised by the fact
> > that MAC-based ACL support implies full-fledged AP SME support. Though
> > your almost convinced me that this is ok and other wireless cards simply
> > do not exist.
> 
> So the question seems to be here: what shall drivers/firmware implement 
> to allow flag WIPHY_FLAG_HAVE_AP_SME being set. The kerneldoc is a bit 
> short in providing guidance:
> 
>   * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME

They should implement the AP SME? :)

That is, handling auth/assoc/etc.

With the SAE-"offload"-to-host those lines are blurring again though.

johannes

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

* Re: [PATCH 10/10] qtnfmac: support MAC address based access control
  2017-12-19 16:58                         ` Johannes Berg
@ 2017-12-19 22:13                           ` Arend Van Spriel
  0 siblings, 0 replies; 32+ messages in thread
From: Arend Van Spriel @ 2017-12-19 22:13 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Kalle Valo, linux-wireless, Igor Mitsyanko, Avinash Patil

On Tue, Dec 19, 2017 at 5:58 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Tue, 2017-12-19 at 13:37 +0100, Arend van Spriel wrote:
>> On 12/19/2017 12:19 PM, Sergey Matyukevich wrote:
>> > > > Not yet. At the moment enum nl80211_ap_sme_features in uapi/linux/nl80211.h
>> > > > is commented out. For MAC-based ACL the following things are being checked
>> > > > on wiphy registration: complete flag WIPHY_FLAG_HAVE_AP_SME, non-zero
>> > > > max_acl_mac_addrs, and set_mac_acl cfg80211 callback.
>> > >
>> > > I guess that's enough then? Userspace can check max_acl_mac_addrs as
>> > > well, so it can just use that?
>> >
>> > Correct, that is what hostapd is doing. I was simply surprised by the fact
>> > that MAC-based ACL support implies full-fledged AP SME support. Though
>> > your almost convinced me that this is ok and other wireless cards simply
>> > do not exist.
>>
>> So the question seems to be here: what shall drivers/firmware implement
>> to allow flag WIPHY_FLAG_HAVE_AP_SME being set. The kerneldoc is a bit
>> short in providing guidance:
>>
>>   * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
>
> They should implement the AP SME? :)
>
> That is, handling auth/assoc/etc.

So basically everything to setup 802.11 connection. So what about the
.*_station() callbacks? Anyway, I can understand that people start
looking at the checks done in wiphy_register() as a last resort in
finding (some sort of) documentation.

> With the SAE-"offload"-to-host those lines are blurring again though.

Yeah. Thanks for (inadvertently) reminding me to chime in on that.

Regards,
Arend

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

* Re: [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware
  2017-12-05 16:24     ` Sergey Matyukevich
@ 2018-01-12 11:23       ` Kalle Valo
  2018-01-15  9:56         ` Sergey Matyukevich
  0 siblings, 1 reply; 32+ messages in thread
From: Kalle Valo @ 2018-01-12 11:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil

Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> writes:

>> > +/**
>> >   * struct qlink_chandef - qlink channel definition
>> >   *
>> > + * @chan: primary channel definition
>> >   * @center_freq1: center frequency of first segment
>> >   * @center_freq2: center frequency of second segment (80+80 only)
>> >   * @width: channel width, one of @enum qlink_channel_width
>> >   */
>> >  struct qlink_chandef {
>> > +     struct qlink_channel chan;
>> >       __le16 center_freq1;
>> >       __le16 center_freq2;
>> >       u8 width;
>> > -     u8 rsvd[3];
>> > +     u8 rsvd;
>> >  } __packed;
>> 
>> Doesn't this break backwards compatibility with the older firmware? The
>> basic princinple is that old firmware images continue to work with newer
>> driver (or there will be a firmware image with new name, eg. fw-2.bin).
>> You can check how iwlwifi does that.
>
> Yes, it breaks. That is why we increment qlink protocol version in each
> change affecting backwards compatibility. So driver is going to work only
> with matching firmware. This is a very simplistic approach, but it looks
> reasonable for current stage of development since we keep adding features.

Everyone are always adding new features, that's no excuse to break
backwards compatibility with user space. In the future you really need
to come up a way to handle the firmware interface breaks gracefully,
just like iwlwifi does.

Related to this, any progress on getting the firmware image to
linux-firmware?

-- 
Kalle Valo

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

* Re: [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware
  2018-01-12 11:23       ` Kalle Valo
@ 2018-01-15  9:56         ` Sergey Matyukevich
  0 siblings, 0 replies; 32+ messages in thread
From: Sergey Matyukevich @ 2018-01-15  9:56 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Igor Mitsyanko, Avinash Patil

Hello Kalle,

> >> > +/**
> >> >   * struct qlink_chandef - qlink channel definition
> >> >   *
> >> > + * @chan: primary channel definition
> >> >   * @center_freq1: center frequency of first segment
> >> >   * @center_freq2: center frequency of second segment (80+80 only)
> >> >   * @width: channel width, one of @enum qlink_channel_width
> >> >   */
> >> >  struct qlink_chandef {
> >> > +     struct qlink_channel chan;
> >> >       __le16 center_freq1;
> >> >       __le16 center_freq2;
> >> >       u8 width;
> >> > -     u8 rsvd[3];
> >> > +     u8 rsvd;
> >> >  } __packed;
> >>
> >> Doesn't this break backwards compatibility with the older firmware? The
> >> basic princinple is that old firmware images continue to work with newer
> >> driver (or there will be a firmware image with new name, eg. fw-2.bin).
> >> You can check how iwlwifi does that.
> >
> > Yes, it breaks. That is why we increment qlink protocol version in each
> > change affecting backwards compatibility. So driver is going to work only
> > with matching firmware. This is a very simplistic approach, but it looks
> > reasonable for current stage of development since we keep adding features.
> 
> Everyone are always adding new features, that's no excuse to break
> backwards compatibility with user space. In the future you really need
> to come up a way to handle the firmware interface breaks gracefully,
> just like iwlwifi does.
> 
> Related to this, any progress on getting the firmware image to
> linux-firmware?

Here is a brief status. In our case, one of the SoC cores runs Linux, so we
have to accompany firmware image with SDK containing all the GPL components.
SDK is not appropriate for linux-firmware repository. That is why the plan
is to make SDK accessible via Quantenna github or website, and then
to get the firmware image to linux-firmware repository. Actually, firmware
image can be submitted any time. But our understanding is that SDK should be
released prior to the next attempt to submit firmware image. So currently
the work is ongoing on making SDK fully GPL compliant, e.g. sorting out
licensing of 3rd party modules.

Regards,
Sergey

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

end of thread, other threads:[~2018-01-15  9:57 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-13 10:28 [PATCH 0/10] qtnfmac: regular portion of features and fixes Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 01/10] qtnfmac: check that MAC exists in regulatory notifier Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 02/10] qtnfmac: pass complete channel data between driver and firmware Sergey Matyukevich
2017-12-04 14:46   ` Kalle Valo
2017-12-05 16:24     ` Sergey Matyukevich
2018-01-12 11:23       ` Kalle Valo
2018-01-15  9:56         ` Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 03/10] qtnfmac: add support for radar detection and CAC Sergey Matyukevich
2017-12-04 14:49   ` Kalle Valo
2017-12-04 14:52     ` Kalle Valo
2017-12-05 16:27       ` Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 04/10] qtnfmac: change default interface mode from AP to STA Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 05/10] qtnfmac: check for passed channel being NULL in MGMT_TX command Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 06/10] qtnfmac: fix rssi data passed to wireless core Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 07/10] qtnfmac: fill wiphy's extended capabilities Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 08/10] qtnfmac: modify GET_STA_STATS cmd format for back/forward compatibility Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 09/10] qtnfmac: keeping track of "generation" for STA info Sergey Matyukevich
2017-11-13 10:28 ` [PATCH 10/10] qtnfmac: support MAC address based access control Sergey Matyukevich
2017-12-04 15:01   ` Kalle Valo
2017-12-05 16:00     ` Sergey Matyukevich
2017-12-18 12:43       ` Sergey Matyukevich
2017-12-18 14:01       ` Kalle Valo
2017-12-18 16:18         ` Sergey Matyukevich
2017-12-19  9:38           ` Johannes Berg
2017-12-19 10:29             ` Sergey Matyukevich
2017-12-19 10:35               ` Johannes Berg
2017-12-19 10:42                 ` Sergey Matyukevich
2017-12-19 10:59                   ` Johannes Berg
2017-12-19 11:19                     ` Sergey Matyukevich
2017-12-19 12:37                       ` Arend van Spriel
2017-12-19 16:58                         ` Johannes Berg
2017-12-19 22:13                           ` Arend Van Spriel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.