Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH v2 0/4] Extended Key ID support
From: Marcel Holtmann @ 2019-04-10 14:37 UTC (permalink / raw)
  To: Alexander Wetzel; +Cc: Johannes Berg, linux-wireless
In-Reply-To: <e8ad598e-a2c4-45be-6923-11fccf80d296@wetzel-home.de>

Ho Alexander,

>>> This patch series adds support for IEEE 802.11-2016 Extended Key ID
>>> support. Compared to the last RFC there are again quite some API
>>> changes, but also some bug fixes. (The bug fixes I remember are outlined
>>> in the different patches.)
>> FWIW, I've applied the first two patches here.
>> I'd really like you to continue with only that for now, and (try to) get
>> hostapd/wpa_supplicant changes upstream, perhaps with corresponding
>> hwsim tests. That way, we can see this working live.
> 
> That's splendid:-)
> I'll try to get the hostapd/wpa_supplicant patches finalized in the next weeks. Hopefully I have something to submit here once the Extended Key ID API is in mainline immediately.

have you tried to add Extended Key ID support into iwd?

Regards

Marcel


^ permalink raw reply

* BCM4335 though sdio is not fully restarted after rmmod and modprobe
From: Mohammad Rasim @ 2019-04-10 13:51 UTC (permalink / raw)
  To: brcm80211-dev-list, brcm80211-dev-list.pdl, netdev,
	linux-wireless

Hi,
I'm running mainline linux (5.1.0-rc2 to be precise) on an amlogic
board, the board comes with Ampak AP6335 combo (so the wifi is BCM4335 over SDIO).
The firmware for this chip is already shipped by linux-firmware as brcmfmac4335-sdio.bin
but one thing that's missing is the nvram settings so I grapped the
nvram txt file from the vendor package(it can be found in [0]) and
placed it in the path that the driver is expecting, and the dongle is
working and I can scan for APs, the problem I have now is when run rmmod
followed by modprobe, the chip is not restarted and I get errors and no
wlan0 interface

after running `rmmod brcmfmac` I get these errors:

[  745.955312] ieee80211 phy0: brcmf_fil_cmd_data: bus is down. we have nothing to do.
[  745.958211] ieee80211 phy0: brcmf_fil_cmd_data: bus is down. we have nothing to do.
[  745.968443] ieee80211 phy0: brcmf_fil_cmd_data: bus is down. we have nothing to do.
[  745.973286] ieee80211 phy0: brcmf_cfg80211_get_channel: chanspec failed (-5)

and after that I run `modprobe brcmfmac` I get these errors:

[  781.529964] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4335-sdio for chip BCM4335/1
[  784.355265] brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout
[  784.361630] brcmfmac: brcmf_sdio_bus_sleep: error while changing bus sleep state -110
[  784.364787] brcmfmac: brcmf_sdiod_ramrw: membytes transfer failed
[  784.370677] brcmfmac: brcmf_sdio_readshared: unable to obtain sdpcm_shared info: rv=-110 (addr=0x0)
[  784.379667] ieee80211 phy1: brcmf_bus_started: failed: -110
[  784.385174] ieee80211 phy1: brcmf_attach: dongle is not responding: err=-110
[  784.429042] brcmfmac: brcmf_sdio_bus_sleep: error while changing bus sleep state -110
[  784.432217] brcmfmac: brcmf_sdio_firmware_callback: brcmf_attach failed
[  784.443484] brcmfmac: brcmf_sdio_bus_sleep: error while changing bus sleep state -110
[  784.446325] brcmfmac: brcmf_sdiod_ramrw: membytes transfer failed
[  784.452322] brcmfmac: brcmf_sdio_readshared: unable to obtain sdpcm_shared info: rv=-110 (addr=0x0)


Any idea what's causing this ?

[0] https://github.com/kszaq/brcmfmac_sdio-firmware-aml/blob/master/firmware/brcm/nvram_bcm4335.txt


^ permalink raw reply

* [PATCH] iw: Add new command to support tid specific configuration
From: Tamizh chelvam @ 2019-04-10 13:50 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Tamizh chelvam

Add "set tid_config" command to support tid specific configurations.
This command accepts multiple tid configurations
like retry, ampdu, rtscts, noack and tx bitrate at a time.

Format:

iw dev <interface> set tid_config <configuration>

Example:

Noack configuration :

iw <interface> set tid_config tid <tid_number> peer <MAC_addr> noack enable|disable

Retry count :

iw <interface> set tid_config tid <tid_number> peer <MAC_addr> retry_count long <retry_value>

Aggregation :

iw <interface> set tid_config tid <tid_number> peer <MAC_addr> ampdu enable|disable

RTSCTS configuration :

iw <interface> set tid_config tid <tid_number> peer <MAC_addr> rtscts enable|disable

Bitrates configuration :

iw <interface> set tid_config tid <tid_number> peer <MAC_addr> bitrates <[auto] [fixed] [limit]> [legacy-<2.4|5> <legacy rate in Mbps>*] [ht-mcs-<2.4|5> <MCS index>] [vht-mcs-<2.4|5> <NSS:MCSx]]

Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
 Makefile     |   2 +-
 bitrate.c    |  40 +++++++++--
 iw.h         |   3 +
 tid_config.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 267 insertions(+), 8 deletions(-)
 create mode 100644 tid_config.c

diff --git a/Makefile b/Makefile
index 33aaf6a..ecb5df8 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ OBJS = iw.o genl.o event.o info.o phy.o \
 	reason.o status.o connect.o link.o offch.o ps.o cqm.o \
 	bitrate.o wowlan.o coalesce.o roc.o p2p.o vendor.o mgmt.o \
 	ap.o sha256.o nan.o bloom.o \
-	measurements.o ftm.o
+	measurements.o ftm.o tid_config.o
 OBJS += sections.o
 
 OBJS-$(HWSIM) += hwsim.o
diff --git a/bitrate.c b/bitrate.c
index 4a026a4..e287b13 100644
--- a/bitrate.c
+++ b/bitrate.c
@@ -76,10 +76,9 @@ static int setup_vht(struct nl80211_txrate_vht *txrate_vht,
 
 #define VHT_ARGC_MAX	100
 
-static int handle_bitrates(struct nl80211_state *state,
-			   struct nl_msg *msg,
-			   int argc, char **argv,
-			   enum id_input id)
+int set_bitrates(struct nl_msg *msg,
+		 int argc, char **argv,
+		 int arg_idx, enum nl80211_attrs attr)
 {
 	struct nlattr *nl_rates, *nl_band;
 	int i;
@@ -110,7 +109,7 @@ static int handle_bitrates(struct nl80211_state *state,
 		S_GI,
 	} parser_state = S_NONE;
 
-	for (i = 0; i < argc; i++) {
+	for (i = arg_idx; i < argc; i++) {
 		char *end;
 		double tmpd;
 		long tmpl;
@@ -195,10 +194,14 @@ static int handle_bitrates(struct nl80211_state *state,
 		case S_GI:
 			break;
 		default:
+			if (attr != NL80211_ATTR_TX_RATES)
+				goto next;
+
 			return 1;
 		}
 	}
 
+next:
 	if (have_vht_mcs_24)
 		if(!setup_vht(&txrate_vht_24, vht_argc_24, vht_argv_24))
 			return -EINVAL;
@@ -213,7 +216,7 @@ static int handle_bitrates(struct nl80211_state *state,
 	if (sgi_24 && lgi_24)
 		return 1;
 
-	nl_rates = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
+	nl_rates = nla_nest_start(msg, attr);
 	if (!nl_rates)
 		goto nla_put_failure;
 
@@ -253,11 +256,34 @@ static int handle_bitrates(struct nl80211_state *state,
 
 	nla_nest_end(msg, nl_rates);
 
-	return 0;
+	return i;
  nla_put_failure:
 	return -ENOBUFS;
 }
 
+static int handle_bitrates(struct nl80211_state *state,
+			   struct nl_msg *msg,
+			   int argc, char **argv,
+			   enum id_input id)
+{
+	int ret;
+	struct nl_msg *rate;
+
+	rate = nlmsg_alloc();
+	if (!rate) {
+		ret = -ENOMEM;
+		goto nla_put_failure;
+	}
+
+	ret = set_bitrates(rate, argc, argv, 0, NL80211_ATTR_TX_RATES);
+	if (ret < argc)
+		return 1;
+
+	return 0;
+nla_put_failure:
+	return -ENOBUFS;
+}
+
 #define DESCR_LEGACY "[legacy-<2.4|5> <legacy rate in Mbps>*]"
 #define DESCR DESCR_LEGACY " [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*] [sgi-2.4|lgi-2.4] [sgi-5|lgi-5]"
 
diff --git a/iw.h b/iw.h
index 16ff076..274f02c 100644
--- a/iw.h
+++ b/iw.h
@@ -242,4 +242,7 @@ void nan_bf(uint8_t idx, uint8_t *bf, uint16_t bf_len, const uint8_t *buf,
 
 char *hex2bin(const char *hex, char *buf);
 
+int set_bitrates(struct nl_msg *msg, int argc, char **argv, int arg_idx,
+		 enum nl80211_attrs attr);
+
 #endif /* __IW_H */
diff --git a/tid_config.c b/tid_config.c
new file mode 100644
index 0000000..4b225c6
--- /dev/null
+++ b/tid_config.c
@@ -0,0 +1,230 @@
+#include <errno.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#include "nl80211.h"
+#include "iw.h"
+
+static int handle_tid_config(struct nl80211_state *state,
+			     struct nl_msg *msg,
+			     int argc, char **argv,
+			     enum id_input id)
+{
+	struct nl_msg *tid;
+	struct nlattr *nl_tid;
+	unsigned char mac_addr[ETH_ALEN];
+	bool have_retry = false, have_ampdu = false;
+	bool have_noack = false, have_rtscts = false, have_bitrate = false;
+	int retry_short = -1, retry_long = -1;
+	bool nest_start = true;
+	uint8_t ampdu = 0, rtscts = 0, noack = 0;
+	enum nl80211_tx_rate_setting type = 0;
+	int tid_no = -1, i = 0;
+	char *end;
+	int ret = -ENOSPC;
+
+	if (argc < 4)
+		return 1;
+
+	tid = nlmsg_alloc();
+	if (!tid)
+		return -ENOMEM;
+
+	while (argc) {
+		if (strcmp(argv[0], "tid") == 0) {
+			if (argc < 2)
+				return 1;
+
+			tid_no = strtoul(argv[1], &end, 16);
+			if (*end)
+				return 1;
+
+			goto next;
+		} else if (strcmp(argv[0], "peer") == 0) {
+			if (argc < 2)
+				return 1;
+
+			if (mac_addr_a2n(mac_addr, argv[1])) {
+				fprintf(stderr, "invalid mac address\n");
+				return 2;
+			}
+
+			NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
+			goto next;
+		} else if (strcmp(argv[0], "retry_count") == 0) {
+			have_retry = true;
+			argv++;
+			argc--;
+			if (argc) {
+				if (strcmp(argv[0], "short") == 0) {
+					if (argc < 2)
+						return 1;
+
+					retry_short = strtoul(argv[1], &end, 0);
+					if (*end)
+						return 1;
+					argv += 2;
+					argc -= 2;
+				}
+				if (argc && strcmp(argv[0], "long") == 0) {
+					if (argc < 2)
+						return 1;
+					retry_long = strtoul(argv[1], &end, 0);
+					if (*end)
+						return 1;
+				}
+			}
+		} else if (strcmp(argv[0], "rtscts") == 0) {
+			have_rtscts = true;
+			if (argc < 2) {
+				argc--;
+				argv++;
+				rtscts = NL80211_TID_CONFIG_DEFAULT;
+			} else {
+				if (strcmp(argv[1], "enable") == 0)
+					rtscts = NL80211_TID_CONFIG_ENABLE;
+				else if (strcmp(argv[1], "disable") == 0)
+					rtscts = NL80211_TID_CONFIG_DISABLE;
+				else
+					rtscts = NL80211_TID_CONFIG_DEFAULT;
+			}
+		} else if (strcmp(argv[0], "ampdu") == 0) {
+			have_ampdu = true;
+			if (argc < 2) {
+				argc--;
+				argv++;
+				ampdu = NL80211_TID_CONFIG_DEFAULT;
+			} else {
+				if (strcmp(argv[1], "enable") == 0)
+					ampdu = NL80211_TID_CONFIG_ENABLE;
+				else if (strcmp(argv[1], "disable") == 0)
+					ampdu = NL80211_TID_CONFIG_DISABLE;
+				else
+					ampdu = NL80211_TID_CONFIG_DEFAULT;
+			}
+		} else if (strcmp(argv[0], "noack") == 0) {
+			have_noack = true;
+			if (argc < 2) {
+				argc--;
+				argv++;
+				noack = NL80211_TID_CONFIG_DEFAULT;
+			} else {
+				if (strcmp(argv[1], "enable") == 0)
+					noack = NL80211_TID_CONFIG_ENABLE;
+				else if (strcmp(argv[1], "disable") == 0)
+					noack = NL80211_TID_CONFIG_DISABLE;
+				else
+					noack = NL80211_TID_CONFIG_DEFAULT;
+			}
+		} else if (strcmp(argv[0], "bitrates") == 0) {
+			have_bitrate = true;
+			if (argc < 2)
+				return 1;
+			if (!strcmp(argv[1], "auto"))
+				type = NL80211_TX_RATE_AUTOMATIC;
+			else if (!strcmp(argv[1], "fixed"))
+				type = NL80211_TX_RATE_FIXED;
+			else if (!strcmp(argv[1], "limit"))
+				type = NL80211_TX_RATE_LIMITED;
+			else {
+				printf("Invalid parameter: %s\n", argv[i]);
+				return 2;
+			}
+			argc -= 2;
+			argv += 2;
+		} else {
+			return 1;
+		}
+
+		if (tid_no == -1)
+			return 1;
+		if (have_retry || have_rtscts || have_bitrate || have_ampdu ||
+		    have_noack) {
+			nl_tid = nla_nest_start(tid, i);
+			if (!nl_tid) {
+				ret = -ENOBUFS;
+				goto nla_put_failure;
+			}
+			nest_start = true;
+			NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_TID, tid_no);
+		} else {
+			goto next;
+		}
+
+		if (have_retry) {
+			NLA_PUT_FLAG(tid, NL80211_ATTR_TID_CONFIG_RETRY);
+			if (retry_short != -1) {
+				NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_RETRY_SHORT,
+					   retry_short);
+			}
+			if (retry_long != -1) {
+				NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_RETRY_LONG,
+					   retry_long);
+			}
+
+			retry_short = retry_long = -1;
+			have_retry = false;
+		}
+
+		if (have_rtscts) {
+			NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL,
+				   rtscts);
+			rtscts = 0;
+			have_rtscts = false;
+		}
+
+		if (have_ampdu) {
+			NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_AMPDU_CTRL,
+				   ampdu);
+			ampdu = 0;
+			have_ampdu = false;
+		}
+
+		if (have_noack) {
+			NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_NOACK, noack);
+			noack = 0;
+			have_noack = false;
+		}
+
+		if (have_bitrate) {
+			NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_TX_RATES_TYPE, type);
+			if (type != NL80211_TX_RATE_AUTOMATIC) {
+				ret = set_bitrates(tid, argc, argv, 0,
+						   NL80211_ATTR_TID_CONFIG_TX_RATES);
+				if (ret < 2)
+					return 1;
+
+				argc -= (ret - 2);
+				argv += (ret - 2);
+			}
+			have_bitrate = false;
+			type = 0;
+		}
+
+		if (nest_start) {
+			nla_nest_end(tid, nl_tid);
+			nest_start = false;
+		}
+next:
+		if (argc) {
+			argc -= 2;
+			argv += 2;
+		}
+	}
+
+	nla_put_nested(msg, NL80211_ATTR_TID_CONFIG, tid);
+
+	ret = 0;
+
+nla_put_failure:
+	return ret;
+}
+COMMAND(set, tid_config, "tid <tid> [peer <MAC address>] [<retry_count> short <limit> long <limit>] [rtscts enable|disable] [ampdu enable|disable] [noack enable|disable] bitrates <[auto] [fixed] [limited]> [peer <addr>] [legacy-<2.4|5> <legacy rate in Mbps>*] [ht-mcs-<2.4|5> <MCS index>] [vht-mcs-<2.4|5> <NSS:MCSx]",
+	NL80211_CMD_SET_TID_CONFIG, 0, CIB_NETDEV, handle_tid_config,
+	"Set the retry count for the TIDs ");
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH 15/21] rt2x00: rt2800lib: hardcode txmixer gain values to zero for RT3883
From: Daniel Golle @ 2019-04-10 13:12 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: Tom Psyborg, linux-wireless, Felix Fietkau, Mathias Kresin,
	Gabor Juhos
In-Reply-To: <20190410082241.GA2538@redhat.com>

On Wed, Apr 10, 2019 at 10:22:42AM +0200, Stanislaw Gruszka wrote:
> On Tue, Apr 09, 2019 at 05:26:46PM +0200, Tom Psyborg wrote:
> > On 09/04/2019, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> > > From: Gabor Juhos <juhosg@openwrt.org>
> > >
> > > Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
> > > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> > > ---
> > >  drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 ++++--
> > >  1 file changed, 4 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > > b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > > index 0687bef990e1..4ea94c62d439 100644
> > > --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > > +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > > @@ -9128,7 +9128,8 @@ static u8 rt2800_get_txmixer_gain_24g(struct
> > > rt2x00_dev *rt2x00dev)
> > >  {
> > >  	u16 word;
> > >
> > > -	if (rt2x00_rt(rt2x00dev, RT3593))
> > > +	if (rt2x00_rt(rt2x00dev, RT3593) ||
> > > +	    rt2x00_rt(rt2x00dev, RT3883))
> > >  		return 0;
> > >
> > >  	word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG);
> > > @@ -9142,7 +9143,8 @@ static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev
> > > *rt2x00dev)
> > >  {
> > >  	u16 word;
> > >
> > > -	if (rt2x00_rt(rt2x00dev, RT3593))
> > > +	if (rt2x00_rt(rt2x00dev, RT3593) ||
> > > +	    rt2x00_rt(rt2x00dev, RT3883))
> > >  		return 0;
> > >
> > >  	word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A);
> > > --
> > > 2.7.5
> > >
> > >
> > 
> > Did someone actually verified this is correct?
> 
> I don't know if it was verified or not.

Gabor supposedly verified this when he wrote that patch 6 years ago,
it was reviewed and merged by John Crispin back then:

commit 6e3de004f9cf6724b1ad950e7cb3b98f1b4af54d
Author: John Crispin <blogic@openwrt.org>
Date:   Wed Apr 23 07:52:18 2014 +0000

    mac80211: rt2x00: add support for the RT3662/RT3883 SoCs
    
    Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
    
    git-svn-id: svn://svn.openwrt.org/openwrt/trunk@40558 3c298f89-4303-0410-b956-a3cf2f4a3e73

Since when we carry it in OpenWrt and supposedly everyone with Rt3xx3
WiSoC devices is using it and there haven't been any complains so far.


Cheers


Daniel

> 
> Stanislaw

^ permalink raw reply

* Re: [PATCH v6 13/20] x86/split_lock: Enable split lock detection by default
From: Fenghua Yu @ 2019-04-10 12:35 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Ingo Molnar, Borislav Petkov, H Peter Anvin, Dave Hansen,
	Paolo Bonzini, Ashok Raj, Peter Zijlstra, Kalle Valo, Xiaoyao Li,
	Michael Chan, Ravi V Shankar, linux-kernel, x86, linux-wireless,
	netdev, kvm
In-Reply-To: <alpine.DEB.2.21.1904100827530.2020@nanos.tec.linutronix.de>

On Wed, Apr 10, 2019 at 08:31:31AM +0200, Thomas Gleixner wrote:
> On Tue, 9 Apr 2019, Fenghua Yu wrote:
> > On Thu, Apr 04, 2019 at 08:07:57PM +0200, Thomas Gleixner wrote:
> > > On Wed, 3 Apr 2019, Fenghua Yu wrote:
> > > >  static void early_init_intel(struct cpuinfo_x86 *c)
> > > >  {
> > > >  	u64 misc_enable;
> > > >  
> > > > +	init_split_lock_detect(c);
> > > 
> > > so we have in early boot:
> > > 
> > > 	early_cpu_init()
> > > 	  early_identify_cpu()
> > > 	    this_cpu->c_early_init(c)
> > > 	      early_init_intel() {
> > > 	        init_split_lock_detect();
> > > 	      }	
> > >             ....
> > >             cpu_set_core_cap_bits(c)
> > > 	       set(FEATURE_SPLIT_LOCK)
> > > 
> > > I don't have to understand how init_split_lock_detect() will magically see
> > > the feature bit which gets set afterwards, right? 
> > 
> > early_init_intel() is called twice on the boot CPU. Besides it's called
> > in earl_cpu_init(), it's also called in:
> > 	identify_boot_cpu()
> > 		identify_cpu()
> > 			init_intel()
> > 				early_init_intel()
> > 					init_split_lock_detect();
> > 
> > It's true that init_split_lock_detect() doesn't see the feature bit when
> > it's called for the first time in early_cpu_init(). But it sees the feature
> > bit when it's called for the second time in identify_boot_cpu().
> 
> That's hideous, really. 
> 
> > So is init_split_lock_detect() in the right place?
> 
> You're not seriously asking that?
> 
> It's obviously not the right place. We are not placing calls at random
> points just because they happen to work by chance.

Is it OK to put init_split_lock_detect(c) after early_init_intel() in
init_intel()? X86_FEATURE_SPLIT_LOCK_DETECT is available now and
init_split_lock_detec() is called only once on each CPU.

@@ -746,6 +749,8 @@ static void init_intel(struct cpuinfo_x86 *c)
 {
        early_init_intel(c);
 
+       init_split_lock_detect(c);
+
        intel_workarounds(c);

Thanks.

-Fenghua

^ permalink raw reply

* Re: [PATCH] ath10k: Fix the wrong value of enums for wmi tlv stats id
From: Surabhi Vishnoi @ 2019-04-10 11:47 UTC (permalink / raw)
  To: Adrian Chadd; +Cc: ath10k, linux-wireless
In-Reply-To: <CAJ-VmoncvErDWb4a2CNE38ECt2_8-vYr3sZ+AcjiPGCaPGuoCQ@mail.gmail.com>

On 2019-04-09 12:18, Adrian Chadd wrote:
> What about QCA6174 that uses TLV? Does this change its behaviour?
> 
> -a
> 

No, it will not break QCA6174, as earlier also same enum values 
(wmi_stats_id) were used for TLV targets,
enum wmi_stats_id {
         WMI_STAT_PEER = BIT(0),
         WMI_STAT_AP = BIT(1),
         WMI_STAT_PDEV = BIT(2),
         WMI_STAT_VDEV = BIT(3),
         WMI_STAT_BCNFLT = BIT(4),
         WMI_STAT_VDEV_RATE = BIT(5),
};

In the change f40a307eb92c ("ath10k: Fill rx duration for each peer in 
fw_stats for WCN3990), enum values for wmi_tlv_stats_id were wrongly 
added.

Thanks,
Surabhi Vishnoi


> On Mon, 8 Apr 2019 at 23:43, Surabhi Vishnoi <svishnoi@codeaurora.org>
> wrote:
> 
>> The enum value for WMI_TLV_STAT_PDEV, WMI_TLV_STAT_VDEV
>> and WMI_TLV_STAT_PEER is wrong, due to which the vdev stats
>> are not received from firmware in wmi_update_stats event.
>> 
>> Fix the enum values for above stats to receive all stats
>> from firmware in WMI_TLV_UPDATE_STATS_EVENTID.
>> 
>> Tested HW: WCN3990
>> Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1
>> 
>> Fixes: f40a307eb92c ("ath10k: Fill rx duration for each peer in
>> fw_stats for WCN3990)
>> Signed-off-by: Surabhi Vishnoi <svishnoi@codeaurora.org>
>> ---
>> drivers/net/wireless/ath/ath10k/wmi.h | 7 ++++---
>> 1 file changed, 4 insertions(+), 3 deletions(-)
>> 
>> diff --git a/drivers/net/wireless/ath/ath10k/wmi.h
>> b/drivers/net/wireless/ath/ath10k/wmi.h
>> index e1c40bb..12f57f9 100644
>> --- a/drivers/net/wireless/ath/ath10k/wmi.h
>> +++ b/drivers/net/wireless/ath/ath10k/wmi.h
>> @@ -4535,9 +4535,10 @@ enum wmi_10_4_stats_id {
>> };
>> 
>> enum wmi_tlv_stats_id {
>> -       WMI_TLV_STAT_PDEV       = BIT(0),
>> -       WMI_TLV_STAT_VDEV       = BIT(1),
>> -       WMI_TLV_STAT_PEER       = BIT(2),
>> +       WMI_TLV_STAT_PEER       = BIT(0),
>> +       WMI_TLV_STAT_AP         = BIT(1),
>> +       WMI_TLV_STAT_PDEV       = BIT(2),
>> +       WMI_TLV_STAT_VDEV       = BIT(3),
>> WMI_TLV_STAT_PEER_EXTD  = BIT(10),
>> };
>> 
>> --
>> 1.9.1

^ permalink raw reply

* Re: [RFC/RFT] mac80211: Switch to a virtual time-based airtime scheduler
From: Toke Høiland-Jørgensen @ 2019-04-10 10:40 UTC (permalink / raw)
  To: Yibo Zhao
  Cc: make-wifi-fast, linux-wireless, Felix Fietkau, Rajkumar Manoharan,
	Kan Yan, linux-wireless-owner
In-Reply-To: <89d32174b282006c8d4e7614657171be@codeaurora.org>

Yibo Zhao <yiboz@codeaurora.org> writes:

> On 2019-04-10 04:41, Toke Høiland-Jørgensen wrote:
>> Yibo Zhao <yiboz@codeaurora.org> writes:
>> 
>>> On 2019-04-04 16:31, Toke Høiland-Jørgensen wrote:
>>>> Yibo Zhao <yiboz@codeaurora.org> writes:
>>>> 
>>>>> On 2019-02-16 01:05, Toke Høiland-Jørgensen wrote:
>>>>>> This switches the airtime scheduler in mac80211 to use a virtual
>>>>>> time-based
>>>>>> scheduler instead of the round-robin scheduler used before. This 
>>>>>> has
>>>>>> a
>>>>>> couple of advantages:
>>>>>> 
>>>>>> - No need to sync up the round-robin scheduler in firmware/hardware
>>>>>> with
>>>>>>   the round-robin airtime scheduler.
>>>>>> 
>>>>>> - If several stations are eligible for transmission we can schedule
>>>>>> both of
>>>>>>   them; no need to hard-block the scheduling rotation until the 
>>>>>> head
>>>>>> of
>>>>>> the
>>>>>>   queue has used up its quantum.
>>>>>> 
>>>>>> - The check of whether a station is eligible for transmission 
>>>>>> becomes
>>>>>>   simpler (in ieee80211_txq_may_transmit()).
>>>>>> 
>>>>>> The drawback is that scheduling becomes slightly more expensive, as
>>>>>> we
>>>>>> need
>>>>>> to maintain an rbtree of TXQs sorted by virtual time. This means 
>>>>>> that
>>>>>> ieee80211_register_airtime() becomes O(logN) in the number of
>>>>>> currently
>>>>>> scheduled TXQs. However, hopefully this number rarely grows too big
>>>>>> (it's
>>>>>> only TXQs currently backlogged, not all associated stations), so it
>>>>>> shouldn't be too big of an issue.
>>>>>> 
>>>>>> @@ -1831,18 +1830,32 @@ void ieee80211_sta_register_airtime(struct
>>>>>> ieee80211_sta *pubsta, u8 tid,
>>>>>>  {
>>>>>>  	struct sta_info *sta = container_of(pubsta, struct sta_info, 
>>>>>> sta);
>>>>>>  	struct ieee80211_local *local = sta->sdata->local;
>>>>>> +	struct ieee80211_txq *txq = sta->sta.txq[tid];
>>>>>>  	u8 ac = ieee80211_ac_from_tid(tid);
>>>>>> -	u32 airtime = 0;
>>>>>> +	u64 airtime = 0, weight_sum;
>>>>>> +
>>>>>> +	if (!txq)
>>>>>> +		return;
>>>>>> 
>>>>>>  	if (sta->local->airtime_flags & AIRTIME_USE_TX)
>>>>>>  		airtime += tx_airtime;
>>>>>>  	if (sta->local->airtime_flags & AIRTIME_USE_RX)
>>>>>>  		airtime += rx_airtime;
>>>>>> 
>>>>>> +	/* Weights scale so the unit weight is 256 */
>>>>>> +	airtime <<= 8;
>>>>>> +
>>>>>>  	spin_lock_bh(&local->active_txq_lock[ac]);
>>>>>> +
>>>>>>  	sta->airtime[ac].tx_airtime += tx_airtime;
>>>>>>  	sta->airtime[ac].rx_airtime += rx_airtime;
>>>>>> -	sta->airtime[ac].deficit -= airtime;
>>>>>> +
>>>>>> +	weight_sum = local->airtime_weight_sum[ac] ?: 
>>>>>> sta->airtime_weight;
>>>>>> +
>>>>>> +	local->airtime_v_t[ac] += airtime / weight_sum;
>>>>> Hi Toke,
>>>>> 
>>>>> Please ignore the previous two broken emails regarding this new
>>>>> proposal
>>>>> from me.
>>>>> 
>>>>> It looks like local->airtime_v_t acts like a Tx criteria. Only the
>>>>> stations with less airtime than that are valid for Tx. That means
>>>>> there
>>>>> are situations, like 50 clients, that some of the stations can be 
>>>>> used
>>>>> to Tx when putting next_txq in the loop. Am I right?
>>>> 
>>>> I'm not sure what you mean here. Are you referring to the case where
>>>> new
>>>> stations appear with a very low (zero) airtime_v_t? That is handled
>>>> when
>>>> the station is enqueued.
>>> Hi Toke,
>>> 
>>> Sorry for the confusion. I am not referring to the case that you
>>> mentioned though it can be solved by your subtle design, max(local vt,
>>> sta vt). :-)
>>> 
>>> Actually, my concern is situation about putting next_txq in the loop.
>>> Let me explain a little more and see below.
>>> 
>>>> @@ -3640,126 +3638,191 @@ EXPORT_SYMBOL(ieee80211_tx_dequeue);
>>>>  struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8
>>>> ac)
>>>>  {
>>>>  	struct ieee80211_local *local = hw_to_local(hw);
>>>> +	struct rb_node *node = local->schedule_pos[ac];
>>>>  	struct txq_info *txqi = NULL;
>>>> +	bool first = false;
>>>> 
>>>>  	lockdep_assert_held(&local->active_txq_lock[ac]);
>>>> 
>>>> - begin:
>>>> -	txqi = list_first_entry_or_null(&local->active_txqs[ac],
>>>> -					struct txq_info,
>>>> -					schedule_order);
>>>> -	if (!txqi)
>>>> +	if (!node) {
>>>> +		node = rb_first_cached(&local->active_txqs[ac]);
>>>> +		first = true;
>>>> +	} else
>>>> +		node = rb_next(node);
>>> 
>>> Consider below piece of code from ath10k_mac_schedule_txq:
>>> 
>>>          ieee80211_txq_schedule_start(hw, ac);
>>>          while ((txq = ieee80211_next_txq(hw, ac))) {
>>>                  while (ath10k_mac_tx_can_push(hw, txq)) {
>>>                          ret = ath10k_mac_tx_push_txq(hw, txq);
>>>                          if (ret < 0)
>>>                                  break;
>>>                  }
>>>                  ieee80211_return_txq(hw, txq);
>>>                  ath10k_htt_tx_txq_update(hw, txq);
>>>                  if (ret == -EBUSY)
>>>                          break;
>>>          }
>>>          ieee80211_txq_schedule_end(hw, ac);
>>> 
>>> If my understanding is right, local->schedule_pos is used to record 
>>> the
>>> last scheduled node and used for traversal rbtree for valid txq. There
>>> is chance that an empty txq is feeded to return_txq and got removed 
>>> from
>>> rbtree. The empty txq will always be the rb_first node. Then in the
>>> following next_txq, local->schedule_pos becomes meaningless since its
>>> rb_next will return NULL and the loop break. Only rb_first get 
>>> dequeued
>>> during this loop.
>>> 
>>> 	if (!node || RB_EMPTY_NODE(node)) {
>>> 		node = rb_first_cached(&local->active_txqs[ac]);
>>> 		first = true;
>>> 	} else
>>> 		node = rb_next(node);
>> 
>> Ah, I see what you mean. Yes, that would indeed be a problem - nice
>> catch! :)
>> 
>>> How about this? The nodes on the rbtree will be dequeued and removed
>>> from rbtree one by one until HW is busy. Please note local vt and sta
>>> vt will not be updated since txq lock is held during this time.
>> 
>> Insertion and removal from the rbtree are relatively expensive, so I'd
>> rather not do that for every txq. I think a better way to solve this
>> is to just defer the actual removal from the tree until
>> ieee80211_txq_schedule_end()... Will fix that when I submit this again.
>
> Do you mean we keep the empty txqs in the rbtree until loop finishes and 
> remove them in ieee80211_txq_schedule_end(may be put return_txq in it)? 
> If it is the case, I suppose a list is needed to store the empty txqs so 
> as to dequeue them in ieee80211_txq_schedule_end.

Yeah, return_txq() would just put "to be removed" TXQs on a list, and
schedule_end() would do the actual removal (after checking whether a new
packet showed up in the meantime).

> And one more thing,
>
>> +               if (sta->airtime[ac].v_t > local->airtime_v_t[ac]) {
>> +                       if (first)
>> +                               local->airtime_v_t[ac] = 
>> sta->airtime[ac].v_t;
>> +                       else
>> +                               return NULL;
>
> As local->airtime_v_t will not be updated during loop, we don't need to 
> return NULL.

Yes we do; this is actually the break condition. I.e., stations whose
virtual time are higher than the global time (in local->airtime_v_t) are
not allowed to transmit. And since we are traversing them in order, when
we find the first such station, we are done and can break out of the
scheduling loop entirely (which is what we do by returning NULL). The
other branch in the inner if() is just for the case where no stations
are currently eligible to transmit according to this rule; here we don't
want to stall, so we advance the global timer so the first station
becomes eligible...

-Toke

^ permalink raw reply

* Re: [PATCH][V2] brcmfmac: fix leak of mypkt on error return path
From: Mukesh Ojha @ 2019-04-10  9:32 UTC (permalink / raw)
  To: Colin King, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Kalle Valo, David S . Miller,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	netdev
  Cc: kernel-janitors, linux-kernel
In-Reply-To: <20190409114333.24342-1-colin.king@canonical.com>


On 4/9/2019 5:13 PM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> Currently if the call to brcmf_sdiod_set_backplane_window fails then

Fix this one extra then pointed by Sergie.
otherwise looks good to me.

Reviewed-by: Mukesh Ojha <mojha@codeaurora.org>

Cheers,
-Mukesh

> then error return path leaks mypkt. Fix this by returning by a new
> error path labelled 'out' that calls brcmu_pkt_buf_free_skb to free
> mypkt.  Also remove redundant check on err before calling
> brcmf_sdiod_skbuff_write.
>
> Addresses-Coverity: ("Resource Leak")
> Fixes: a7c3aa1509e2 ("brcmfmac: Remove brcmf_sdiod_addrprep()")
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>
> V2: Remove  redundant check on err before calling
> brcmf_sdiod_skbuff_write, kudos to Dan Carpenter and Arend Van Spriel
> for spotting this.
>
> ---
>   drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 +++-----
>   1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> index ec129864cc9c..60aede5abb4d 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> @@ -628,15 +628,13 @@ int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
>   
>   	err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
>   	if (err)
> -		return err;
> +		goto out;
>   
>   	addr &= SBSDIO_SB_OFT_ADDR_MASK;
>   	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
>   
> -	if (!err)
> -		err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr,
> -					       mypkt);
> -
> +	err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr, mypkt);
> +out:
>   	brcmu_pkt_buf_free_skb(mypkt);
>   
>   	return err;

^ permalink raw reply

* Re: [RFC V3 1/2] mac80211: add hw 80211 encapsulation offloading support
From: Toke Høiland-Jørgensen @ 2019-04-10 10:16 UTC (permalink / raw)
  To: John Crispin
  Cc: linux-wireless, Shashidhar Lakkavalli, Vasanthakumar Thiagarajan
In-Reply-To: <46dfe65c-3bbf-7923-d358-9acec030f572@phrozen.org>

John Crispin <john@phrozen.org> writes:

> On 02/04/2019 11:50, Toke Høiland-Jørgensen wrote:
>> ieee80211_queue_skb() calls ieee80211_get_txq() which treats skb->data
>> like it contains an 802.11 header. That is probably not the intention
>> here, is it?
>>
>> I guess we could augment the TXQ stuctures to also handle 802.3 frames
>> (and introduce ieee80211_queue_skb_8023())? Or would it be better to
>> have a qdisc on 802.3-mode interfaces and push packets back to that? I
>> guess we'd still benefit from per-station queueing of packets even if
>> they are Ethernet frames, which would mean amending the TXQs would be
>> better?
>>
>> -Toke
>
> Hi Toke
>
> This patch guards the usage of the hdr pointer. hdr is only used for non 
> data frames which are not relevant when doing encap mode. The code will 
> then drop into the same path as for 80211 encapsulated frames. IMHO the 
> patch is correct and we do not need an additional 
> ieee80211_queue_skb_8023()  to benefit from per station TXQs. Let me 
> know if i missed something.

Ah, right, sorry, missed the change to ieee80211_get_txq() :)

-Toke

^ permalink raw reply

* RE: [PATCH 4/4] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: Alastair D'Silva @ 2019-04-10  9:52 UTC (permalink / raw)
  To: 'David Laight', 'Alastair D'Silva'
  Cc: 'Jani Nikula', 'Joonas Lahtinen',
	'Rodrigo Vivi', 'David Airlie',
	'Daniel Vetter', 'Karsten Keil',
	'Jassi Brar', 'Tom Lendacky',
	'David S. Miller', 'Jose Abreu',
	'Kalle Valo', 'Stanislaw Gruszka',
	'Benson Leung', 'Enric Balletbo i Serra',
	'James E.J. Bottomley', 'Martin K. Petersen',
	'Greg Kroah-Hartman', 'Alexander Viro',
	'Petr Mladek', 'Sergey Senozhatsky',
	'Steven Rostedt', 'Andrew Morton', intel-gfx,
	dri-devel, linux-kernel, netdev, ath10k, linux-wireless,
	linux-scsi, linux-fbdev, devel, linux-fsdevel
In-Reply-To: <1cd09186c67b4fa4bceb84faf835ff10@AcuMS.aculab.com>

> -----Original Message-----
> From: David Laight <David.Laight@ACULAB.COM>
> Sent: Wednesday, 10 April 2019 6:45 PM
> To: 'Alastair D'Silva' <alastair@au1.ibm.com>; alastair@d-silva.org
> Cc: Jani Nikula <jani.nikula@linux.intel.com>; Joonas Lahtinen
> <joonas.lahtinen@linux.intel.com>; Rodrigo Vivi <rodrigo.vivi@intel.com>;
> David Airlie <airlied@linux.ie>; Daniel Vetter <daniel@ffwll.ch>; Karsten Keil
> <isdn@linux-pingi.de>; Jassi Brar <jassisinghbrar@gmail.com>; Tom Lendacky
> <thomas.lendacky@amd.com>; David S. Miller <davem@davemloft.net>;
> Jose Abreu <Jose.Abreu@synopsys.com>; Kalle Valo
> <kvalo@codeaurora.org>; Stanislaw Gruszka <sgruszka@redhat.com>;
> Benson Leung <bleung@chromium.org>; Enric Balletbo i Serra
> <enric.balletbo@collabora.com>; James E.J. Bottomley
> <jejb@linux.ibm.com>; Martin K. Petersen <martin.petersen@oracle.com>;
> Greg Kroah-Hartman <gregkh@linuxfoundation.org>; Alexander Viro
> <viro@zeniv.linux.org.uk>; Petr Mladek <pmladek@suse.com>; Sergey
> Senozhatsky <sergey.senozhatsky@gmail.com>; Steven Rostedt
> <rostedt@goodmis.org>; Andrew Morton <akpm@linux-foundation.org>;
> intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux-
> kernel@vger.kernel.org; netdev@vger.kernel.org;
> ath10k@lists.infradead.org; linux-wireless@vger.kernel.org; linux-
> scsi@vger.kernel.org; linux-fbdev@vger.kernel.org;
> devel@driverdev.osuosl.org; linux-fsdevel@vger.kernel.org
> Subject: RE: [PATCH 4/4] lib/hexdump.c: Allow multiple groups to be
> separated by lines '|'
> 
> From: Alastair D'Silva
> > Sent: 10 April 2019 04:17
> > With the wider display format, it can become hard to identify how many
> > bytes into the line you are looking at.
> >
> > The patch adds new flags to hex_dump_to_buffer() and
> print_hex_dump()
> > to print vertical lines to separate every N groups of bytes.
> >
> > eg.
> > buf:00000000: 454d414e 43415053|4e495f45 00584544
> NAMESPAC|E_INDEX.
> > buf:00000010: 00000000 00000002|00000000 00000000  ........|........
> 
> Ugg, that is just horrid.
> It is enough to add an extra space if you really need the columns to be more
> easily counted.
>

I did consider that, but it would be a more invasive change, as the buffer length required would differ based on the flags.
 
> I'm not even sure that is needed if you are printing 32bit words.
> OTOH 32bit words makes 64bit values really stupid on LE systems.
> Bytes with extra spaces every 4 bytes is the format I prefer even for long
> lines.
> 
> Oh, and if you are using hexdump() a lot you want a version that never uses
> snprintf().
> 
> 	David
> 
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes,
> MK1 1PT, UK Registration No: 1397386 (Wales)
> 
> 
> ---
> This email has been checked for viruses by AVG.
> https://www.avg.com



^ permalink raw reply

* Re: [PATCH][V2] brcmfmac: fix leak of mypkt on error return path
From: Sergei Shtylyov @ 2019-04-10  9:17 UTC (permalink / raw)
  To: Colin King, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Kalle Valo, David S . Miller,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	netdev
  Cc: kernel-janitors, linux-kernel
In-Reply-To: <20190409114333.24342-1-colin.king@canonical.com>

On 09.04.2019 14:43, Colin King wrote:

> From: Colin Ian King <colin.king@canonical.com>
> 
> Currently if the call to brcmf_sdiod_set_backplane_window fails then
> then error return path leaks mypkt. Fix this by returning by a new

    One "then" is enough. :-)

> error path labelled 'out' that calls brcmu_pkt_buf_free_skb to free
> mypkt.  Also remove redundant check on err before calling
> brcmf_sdiod_skbuff_write.
> 
> Addresses-Coverity: ("Resource Leak")
> Fixes: a7c3aa1509e2 ("brcmfmac: Remove brcmf_sdiod_addrprep()")
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
[...]

MBR, Sergei

^ permalink raw reply

* Re: [PATCH 4/4] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: Sergey Senozhatsky @ 2019-04-10  8:53 UTC (permalink / raw)
  To: Alastair D'Silva
  Cc: alastair, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	David Airlie, Daniel Vetter, Karsten Keil, Jassi Brar,
	Tom Lendacky, David S. Miller, Jose Abreu, Kalle Valo,
	Stanislaw Gruszka, Benson Leung, Enric Balletbo i Serra,
	James E.J. Bottomley, Martin K. Petersen, Greg Kroah-Hartman,
	Alexander Viro, Petr Mladek, Sergey Senozhatsky, Steven Rostedt,
	Andrew Morton, intel-gfx, dri-devel, linux-kernel, netdev, ath10k,
	linux-wireless, linux-scsi, linux-fbdev, devel, linux-fsdevel
In-Reply-To: <20190410031720.11067-5-alastair@au1.ibm.com>

On (04/10/19 13:17), Alastair D'Silva wrote:
> With the wider display format, it can become hard to identify how many
> bytes into the line you are looking at.
> 
> The patch adds new flags to hex_dump_to_buffer() and print_hex_dump() to
> print vertical lines to separate every N groups of bytes.
> 
> eg.
> buf:00000000: 454d414e 43415053|4e495f45 00584544  NAMESPAC|E_INDEX.
> buf:00000010: 00000000 00000002|00000000 00000000  ........|........

What if the output had |-s in it?  |||||||||

	-ss

^ permalink raw reply

* RE: [PATCH v6 13/20] x86/split_lock: Enable split lock detection by default
From: David Laight @ 2019-04-10  8:50 UTC (permalink / raw)
  To: 'Fenghua Yu', Thomas Gleixner
  Cc: Ingo Molnar, Borislav Petkov, H Peter Anvin, Dave Hansen,
	Paolo Bonzini, Ashok Raj, Peter Zijlstra, Kalle Valo, Xiaoyao Li,
	Michael Chan, Ravi V Shankar, linux-kernel, x86,
	linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	kvm@vger.kernel.org
In-Reply-To: <20190410000229.GA209676@romley-ivt3.sc.intel.com>

FWIW it took me a while to work out what a 'split lock' was.

I suspect because I was thinking of kernel locks, not the
instruction lock prefix.
It also isn't really obvious that 'split' refers to crossing
cache lines.

Referring to it as a 'misaligned lock' might be more
easily understood.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


^ permalink raw reply

* RE: [PATCH 4/4] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: David Laight @ 2019-04-10  8:45 UTC (permalink / raw)
  To: 'Alastair D'Silva', alastair@d-silva.org
  Cc: Jani Nikula, Joonas Lahtinen, Rodrigo Vivi, David Airlie,
	Daniel Vetter, Karsten Keil, Jassi Brar, Tom Lendacky,
	David S. Miller, Jose Abreu, Kalle Valo, Stanislaw Gruszka,
	Benson Leung, Enric Balletbo i Serra, James E.J. Bottomley,
	Martin K. Petersen, Greg Kroah-Hartman, Alexander Viro,
	Petr Mladek, Sergey Senozhatsky, Steven Rostedt, Andrew Morton,
	intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
	linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
	ath10k@lists.infradead.org, linux-wireless@vger.kernel.org,
	linux-scsi@vger.kernel.org, linux-fbdev@vger.kernel.org,
	devel@driverdev.osuosl.org, linux-fsdevel@vger.kernel.org
In-Reply-To: <20190410031720.11067-5-alastair@au1.ibm.com>

From: Alastair D'Silva
> Sent: 10 April 2019 04:17
> With the wider display format, it can become hard to identify how many
> bytes into the line you are looking at.
> 
> The patch adds new flags to hex_dump_to_buffer() and print_hex_dump() to
> print vertical lines to separate every N groups of bytes.
> 
> eg.
> buf:00000000: 454d414e 43415053|4e495f45 00584544  NAMESPAC|E_INDEX.
> buf:00000010: 00000000 00000002|00000000 00000000  ........|........

Ugg, that is just horrid.
It is enough to add an extra space if you really need the columns
to be more easily counted.

I'm not even sure that is needed if you are printing 32bit words.
OTOH 32bit words makes 64bit values really stupid on LE systems.
Bytes with extra spaces every 4 bytes is the format I prefer
even for long lines.

Oh, and if you are using hexdump() a lot you want a version
that never uses snprintf().

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


^ permalink raw reply

* Re: [PATCH 15/21] rt2x00: rt2800lib: hardcode txmixer gain values to zero for RT3883
From: Stanislaw Gruszka @ 2019-04-10  8:22 UTC (permalink / raw)
  To: Tom Psyborg
  Cc: linux-wireless, Daniel Golle, Felix Fietkau, Mathias Kresin,
	Gabor Juhos
In-Reply-To: <CAKR_QVJtwmpEK2a5br2YEKPsAF0GHXwny5YbCTFoO_mgD+fVJw@mail.gmail.com>

On Tue, Apr 09, 2019 at 05:26:46PM +0200, Tom Psyborg wrote:
> On 09/04/2019, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> > From: Gabor Juhos <juhosg@openwrt.org>
> >
> > Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
> > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> > ---
> >  drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > index 0687bef990e1..4ea94c62d439 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > @@ -9128,7 +9128,8 @@ static u8 rt2800_get_txmixer_gain_24g(struct
> > rt2x00_dev *rt2x00dev)
> >  {
> >  	u16 word;
> >
> > -	if (rt2x00_rt(rt2x00dev, RT3593))
> > +	if (rt2x00_rt(rt2x00dev, RT3593) ||
> > +	    rt2x00_rt(rt2x00dev, RT3883))
> >  		return 0;
> >
> >  	word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG);
> > @@ -9142,7 +9143,8 @@ static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev
> > *rt2x00dev)
> >  {
> >  	u16 word;
> >
> > -	if (rt2x00_rt(rt2x00dev, RT3593))
> > +	if (rt2x00_rt(rt2x00dev, RT3593) ||
> > +	    rt2x00_rt(rt2x00dev, RT3883))
> >  		return 0;
> >
> >  	word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A);
> > --
> > 2.7.5
> >
> >
> 
> Did someone actually verified this is correct?

I don't know if it was verified or not.

Stanislaw

^ permalink raw reply

* Re: gsmtap design/extensions?
From: Marcel Holtmann @ 2019-04-10  7:57 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Vadim Yanitskiy, Harald Welte, OpenBSC Mailing List,
	Sean Tranchetti, radiotap, Dan Williams, netdev,
	open list:NFC SUBSYSTEM, Aleksander Morgado,
	Subash Abhinov Kasiviswanathan, Bjørn Mork
In-Reply-To: <46474c61d7748042cc0a1f23773186786020638e.camel@sipsolutions.net>

Hi Johannes,

>> FYI, there already was a discussion about GSMTAPv3:
>> 
>> https://www.youtube.com/watch?v=vum9jzavZi0&list=PL07C78AF831FFE8F9&index=10
>> 
>> but unfortunately, nobody has invested time into this (yet?).
> 
> 2012! But, umm, I don't really have time for a whole video right now -
> anyone have the slides? :-)
> 
> But yeah, the first slides look sensible :-)
> 
>>> 1) Why the design with encapsulating it in UDP?
>> 
>> This gives us a possibility to "demux" multiple GSMTAP streams on the
>> receiving side, e.g. if you are running multiple processes.
> 
> Not sure I get this, but I also don't really care all that much. It's
> just a pretty strange design if the kernel were to output this, I'm not
> even sure how I'd do that properly. I don't want to be generating UDP
> packets there...
> 
> Perhaps we can define something (GSMTAPv3) to not really care how it's
> encapsulated, and for 'native' packet captures like what I want on Linux
> when integrated with the driver, actually use an ARPHDR_GSMTAP, and
> encapsulate in UDP when you create it in an application and want to send
> it elsewhere, rather than just writing it to a pcap file?

before you go all out and define this, it would suggest to understand what meta-data for the connection contexts you actually need as well. The data path itself is just a pipe and has not all the information attached with it. That goes via the control path and that is normally in user space and carries the real important information to make useful analysis of how the data path / context is setup.

From what I am seeing right now is that unless you have a method to also feed the control path into your GSMTAPv3, then this is rather useless. The majority of the debugging is really done for the control path. For oFono that is OFONO_DEBUG=1 environment variable and while it works it is not the most elegant solution. I would love to feed that into a generic debugging / tap that you can read out later.

As a side note, for Bluetooth we created a path where the bluetoothd can feed back its control debugging data back into the Bluetooth monitor in the kernel to allow combined userspace, mgmt and HCI tracing. Some really nasty issues could only be triaged by having all the meta data with a common timestamp.

Regards

Marcel


^ permalink raw reply

* [RFC V4 2/2] ath10k: add tx hw 802.11 encapusaltion offloading support
From: John Crispin @ 2019-04-10  7:35 UTC (permalink / raw)
  To: Johannes Berg, Kalle Valo
  Cc: linux-wireless, Srini Kode, Rajkumar Manoharan,
	Shashidhar Lakkavalli, Vasanthakumar Thiagarajan, John Crispin
In-Reply-To: <20190410073514.12794-1-john@phrozen.org>

From: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>

This patch adds support for ethernet rxtx mode to the driver. The feature
is enabled via a new module parameter. If enabled to driver will enable
the feature on a per vif basis if all other requirements were met.

Testing on a IPQ4019 based hardware shows a increase in TCP throughput
of ~20% when the feature is enabled.

Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
Signed-off-by: John Crispin <john@phrozen.org>
---
 drivers/net/wireless/ath/ath10k/core.c   | 11 +++++
 drivers/net/wireless/ath/ath10k/core.h   |  3 ++
 drivers/net/wireless/ath/ath10k/htt_tx.c | 24 +++++++----
 drivers/net/wireless/ath/ath10k/mac.c    | 70 +++++++++++++++++++++++++-------
 drivers/net/wireless/ath/ath10k/txrx.c   | 11 ++++-
 5 files changed, 94 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index ac2cf3f1c7b4..e3db98df806d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -30,6 +30,7 @@ static unsigned int ath10k_cryptmode_param;
 static bool uart_print;
 static bool skip_otp;
 static bool rawmode;
+static bool ethernetmode;
 
 unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) |
 				     BIT(ATH10K_FW_CRASH_DUMP_CE_DATA);
@@ -41,6 +42,7 @@ module_param(uart_print, bool, 0644);
 module_param(skip_otp, bool, 0644);
 module_param(rawmode, bool, 0644);
 module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444);
+module_param(ethernetmode, bool, 0644);
 
 MODULE_PARM_DESC(debug_mask, "Debugging mask");
 MODULE_PARM_DESC(uart_print, "Uart target debugging");
@@ -48,6 +50,7 @@ MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
 MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
 MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
 MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
+MODULE_PARM_DESC(ethernetmode, "Use ethernet frame datapath");
 
 static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 	{
@@ -2926,6 +2929,14 @@ static void ath10k_core_register_work(struct work_struct *work)
 	/* peer stats are enabled by default */
 	set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
 
+	if (ethernetmode && rawmode) {
+		ath10k_err(ar, "ethernet and raw mode cannot co-exist\n");
+		status = -EINVAL;
+		goto err;
+	}
+
+	ar->ethernetmode = ethernetmode;
+
 	status = ath10k_core_probe_fw(ar);
 	if (status) {
 		ath10k_err(ar, "could not probe fw (%d)\n", status);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 27ec5557de88..30199a2d66b4 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -109,6 +109,7 @@ enum ath10k_skb_flags {
 	ATH10K_SKB_F_MGMT = BIT(3),
 	ATH10K_SKB_F_QOS = BIT(4),
 	ATH10K_SKB_F_RAW_TX = BIT(5),
+	ATH10K_SKB_F_HW_80211_ENCAP = BIT(6),
 };
 
 struct ath10k_skb_cb {
@@ -1187,6 +1188,8 @@ struct ath10k {
 	struct work_struct radar_confirmation_work;
 	struct ath10k_bus_params bus_param;
 
+	bool ethernetmode;
+
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
 };
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index d8e9cc0bb772..ae4c48b8b706 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -1143,6 +1143,10 @@ static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
 
+	/* Firmware takes care of tid classification for ethernet format */
+	if (cb->flags & ATH10K_SKB_F_HW_80211_ENCAP)
+		return skb->priority % IEEE80211_QOS_CTL_TID_MASK;
+
 	if (!is_eth && ieee80211_is_mgmt(hdr->frame_control))
 		return HTT_DATA_TX_EXT_TID_MGMT;
 	else if (cb->flags & ATH10K_SKB_F_QOS)
@@ -1351,15 +1355,17 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
 	txbuf_paddr = htt->txbuf.paddr +
 		      (sizeof(struct ath10k_htt_txbuf_32) * msdu_id);
 
-	if ((ieee80211_is_action(hdr->frame_control) ||
-	     ieee80211_is_deauth(hdr->frame_control) ||
-	     ieee80211_is_disassoc(hdr->frame_control)) &&
-	     ieee80211_has_protected(hdr->frame_control)) {
-		skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
-	} else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
-		   txmode == ATH10K_HW_TXRX_RAW &&
-		   ieee80211_has_protected(hdr->frame_control)) {
-		skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+	if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)) {
+		if ((ieee80211_is_action(hdr->frame_control) ||
+		     ieee80211_is_deauth(hdr->frame_control) ||
+		     ieee80211_is_disassoc(hdr->frame_control)) &&
+		    ieee80211_has_protected(hdr->frame_control)) {
+			skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+		} else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
+			   txmode == ATH10K_HW_TXRX_RAW &&
+			   ieee80211_has_protected(hdr->frame_control)) {
+			skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+		}
 	}
 
 	skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b73c23d4ce86..893296152c22 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3386,12 +3386,16 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
 			   struct sk_buff *skb)
 {
 	const struct ieee80211_hdr *hdr = (void *)skb->data;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 	__le16 fc = hdr->frame_control;
 
 	if (!vif || vif->type == NL80211_IFTYPE_MONITOR)
 		return ATH10K_HW_TXRX_RAW;
 
+	if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
+		return ATH10K_HW_TXRX_ETHERNET;
+
 	if (ieee80211_is_mgmt(fc))
 		return ATH10K_HW_TXRX_MGMT;
 
@@ -3544,6 +3548,15 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
 			ieee80211_is_data_qos(hdr->frame_control);
 
 	cb->flags = 0;
+	cb->vif = vif;
+	cb->txq = txq;
+	cb->airtime_est = airtime;
+
+	if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
+		cb->flags |= ATH10K_SKB_F_HW_80211_ENCAP;
+		return;
+	}
+
 	if (!ath10k_tx_h_use_hwcrypto(vif, skb))
 		cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
 
@@ -3562,10 +3575,6 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
 		cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
 		cb->flags |= ATH10K_SKB_F_RAW_TX;
 	}
-
-	cb->vif = vif;
-	cb->txq = txq;
-	cb->airtime_est = airtime;
 }
 
 bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
@@ -3675,6 +3684,9 @@ static int ath10k_mac_tx(struct ath10k *ar,
 	const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 	int ret;
 
+	if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
+		goto skip_encap;
+
 	/* We should disable CCK RATE due to P2P */
 	if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
 		ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
@@ -3698,6 +3710,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
 		}
 	}
 
+skip_encap:
 	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
 		if (!ath10k_mac_tx_frm_has_freq(ar)) {
 			ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %pK\n",
@@ -3747,6 +3760,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
 	int ret;
 	unsigned long time_left;
 	bool tmp_peer_created = false;
+	struct ieee80211_tx_info *info;
 
 	/* FW requirement: We must create a peer before FW will send out
 	 * an offchannel frame. Otherwise the frame will be stuck and
@@ -3766,8 +3780,14 @@ void ath10k_offchan_tx_work(struct work_struct *work)
 		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK\n",
 			   skb);
 
-		hdr = (struct ieee80211_hdr *)skb->data;
-		peer_addr = ieee80211_get_DA(hdr);
+		info = IEEE80211_SKB_CB(skb);
+
+		if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
+			peer_addr = skb->data;
+		} else {
+			hdr = (struct ieee80211_hdr *)skb->data;
+			peer_addr = ieee80211_get_DA(hdr);
+		}
 
 		spin_lock_bh(&ar->data_lock);
 		vdev_id = ar->scan.vdev_id;
@@ -4295,7 +4315,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
 	struct ieee80211_vif *vif = info->control.vif;
 	struct ieee80211_sta *sta = control->sta;
 	struct ieee80211_txq *txq = NULL;
-	struct ieee80211_hdr *hdr = (void *)skb->data;
+	struct ieee80211_hdr *hdr;
 	enum ath10k_hw_txrx_mode txmode;
 	enum ath10k_mac_tx_path txpath;
 	bool is_htt;
@@ -4326,14 +4346,20 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
 			return;
 		}
 
-		ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt, is_presp);
-		if (ret) {
-			ath10k_dbg(ar, ATH10K_DBG_MAC, "failed to increase tx mgmt pending count: %d, dropping\n",
-				   ret);
-			ath10k_htt_tx_dec_pending(htt);
-			spin_unlock_bh(&ar->htt.tx_lock);
-			ieee80211_free_txskb(ar->hw, skb);
-			return;
+		if (is_mgmt) {
+			hdr = (struct ieee80211_hdr *)skb->data;
+			is_presp = ieee80211_is_probe_resp(hdr->frame_control);
+
+			ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt,
+							     is_presp);
+			if (ret) {
+				ath10k_dbg(ar, ATH10K_DBG_MAC, "failed to increase tx mgmt pending count: %d, dropping\n",
+					   ret);
+				ath10k_htt_tx_dec_pending(htt);
+				spin_unlock_bh(&ar->htt.tx_lock);
+				ieee80211_free_txskb(ar->hw, skb);
+				return;
+			}
 		}
 		spin_unlock_bh(&ar->htt.tx_lock);
 	}
@@ -5094,6 +5120,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 	struct ath10k_vif *arvif = (void *)vif->drv_priv;
 	struct ath10k_peer *peer;
 	enum wmi_sta_powersave_param param;
+	int hw_encap = 0;
 	int ret = 0;
 	u32 value;
 	int bit;
@@ -5185,6 +5212,17 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		break;
 	}
 
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_AP:
+		hw_encap = 1;
+		break;
+	default:
+		break;
+	}
+	ieee80211_set_hw_80211_encap(vif, ar->ethernetmode & hw_encap);
+
 	/* Using vdev_id as queue number will make it very easy to do per-vif
 	 * tx queue locking. This shouldn't wrap due to interface combinations
 	 * but do a modulo for correctness sake and prevent using offchannel tx
@@ -8602,6 +8640,8 @@ int ath10k_mac_register(struct ath10k *ar)
 	ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
 	ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
 	ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
+	if (ar->ethernetmode)
+		ieee80211_hw_set(ar->hw, SUPPORTS_80211_ENCAP);
 
 	if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
 		ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index c5818d28f55a..bad5e7335c0e 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -50,6 +50,8 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
 	struct ath10k_skb_cb *skb_cb;
 	struct ath10k_txq *artxq;
 	struct sk_buff *msdu;
+	struct ieee80211_vif *vif;
+	u8 flags;
 
 	ath10k_dbg(ar, ATH10K_DBG_HTT,
 		   "htt tx completion msdu_id %u status %d\n",
@@ -78,6 +80,9 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
 		artxq->num_fw_queued--;
 	}
 
+	flags = skb_cb->flags;
+	vif = skb_cb->vif;
+
 	ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
 	ath10k_htt_tx_dec_pending(htt);
 	if (htt->num_pending_tx == 0)
@@ -121,7 +126,11 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
 		info->status.is_valid_ack_signal = true;
 	}
 
-	ieee80211_tx_status(htt->ar->hw, msdu);
+	if (flags & ATH10K_SKB_F_HW_80211_ENCAP)
+		ieee80211_tx_status_8023(htt->ar->hw, vif, msdu);
+	else
+		ieee80211_tx_status(htt->ar->hw, msdu);
+
 	/* we do not own the msdu anymore */
 
 	return 0;
-- 
2.11.0


^ permalink raw reply related

* [RFC V4 1/2] mac80211: add hw 80211 encapsulation offloading support
From: John Crispin @ 2019-04-10  7:35 UTC (permalink / raw)
  To: Johannes Berg, Kalle Valo
  Cc: linux-wireless, Srini Kode, Rajkumar Manoharan,
	Shashidhar Lakkavalli, Vasanthakumar Thiagarajan, John Crispin
In-Reply-To: <20190410073514.12794-1-john@phrozen.org>

From: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>

This patch adds a new transmit path for hardware that supports 802.11
encapsulation offloading. In those cases 802.3a frames get passed
directly to the driver allowing to hardware to handle the encapsulation.

Certain features wont work and the patch masks these out.
* monitor interfaces are not supported if any of the vif is in encap mode.
* amsdu/non-linear frames wont work in encap offloading mode.
* TKIP countermeasures cannot be triggered and hence those keys are not
  accepted.

The patch defines a secondary netdev_ops struct that the device is assigned
to the device if 802.11 encap support is available and enabled. The driver
needs to enable the support on a per vif basis if it finds that all
pre-reqs are meet.

Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
Signed-off-by: John Crispin <john@phrozen.org>
---
 include/net/mac80211.h     |  25 ++++++
 net/mac80211/cfg.c         |   3 +
 net/mac80211/debugfs.c     |   1 +
 net/mac80211/ieee80211_i.h |  10 +++
 net/mac80211/iface.c       |  72 +++++++++++++++++
 net/mac80211/key.c         |   7 ++
 net/mac80211/main.c        |  10 ++-
 net/mac80211/status.c      |  79 +++++++++++++++++++
 net/mac80211/tx.c          | 189 +++++++++++++++++++++++++++++++++++++++++++--
 9 files changed, 387 insertions(+), 9 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ac2ed8ec662b..b9e77e295361 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -816,6 +816,7 @@ enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTRL_RATE_INJECT		= BIT(2),
 	IEEE80211_TX_CTRL_AMSDU			= BIT(3),
 	IEEE80211_TX_CTRL_FAST_XMIT		= BIT(4),
+	IEEE80211_TX_CTRL_HW_80211_ENCAP	= BIT(5),
 };
 
 /*
@@ -2243,6 +2244,9 @@ struct ieee80211_txq {
  * @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID
  *	only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set.
  *
+ * @IEEE80211_HW_SUPPORTS_80211_ENCAP: Hardware/driver supports 802.11
+ *	encap for data frames.
+ *
  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
  */
 enum ieee80211_hw_flags {
@@ -2294,6 +2298,7 @@ enum ieee80211_hw_flags {
 	IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN,
 	IEEE80211_HW_SUPPORTS_MULTI_BSSID,
 	IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
+	IEEE80211_HW_SUPPORTS_80211_ENCAP,
 
 	/* keep last, obviously */
 	NUM_IEEE80211_HW_FLAGS
@@ -4587,6 +4592,25 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
 				 struct sk_buff *skb);
 
 /**
+ * ieee80211_tx_status_8023 - transmit status callback for 802.3 frame format
+ *
+ * Call this function for all transmitted data frames after their transmit
+ * completion. This callback should only be called for data frames which
+ * are are using driver's (or hardware's) offload capability of encap/decap
+ * 802.11 frames.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @vif: the interface for which the frame was transmitted
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ */
+void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct sk_buff *skb);
+
+/**
  * ieee80211_report_low_ack - report non-responding station
  *
  * When operating in AP-mode, call this function to report a non-responding
@@ -6359,4 +6383,5 @@ void ieee80211_nan_func_match(struct ieee80211_vif *vif,
 			      struct cfg80211_nan_match_params *match,
 			      gfp_t gfp);
 
+int ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable);
 #endif /* MAC80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0a1f6e0a0548..029fb4a672de 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2379,6 +2379,9 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
 		ieee80211_check_fast_xmit_all(local);
 
+		if (ieee80211_is_hw_80211_encap(local))
+			return -EINVAL;
+
 		err = drv_set_frag_threshold(local, wiphy->frag_threshold);
 
 		if (err) {
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 2d43bc127043..a4df6bca192f 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -221,6 +221,7 @@ static const char *hw_flag_names[] = {
 	FLAG(TX_STATUS_NO_AMPDU_LEN),
 	FLAG(SUPPORTS_MULTI_BSSID),
 	FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
+	FLAG(SUPPORTS_80211_ENCAP),
 #undef FLAG
 };
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5d837d10fef7..f14da8d7a21b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -987,6 +987,8 @@ struct ieee80211_sub_if_data {
 	} debugfs;
 #endif
 
+	bool hw_80211_encap;
+
 	/* must be last, dynamically sized area in this! */
 	struct ieee80211_vif vif;
 };
@@ -1733,6 +1735,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 		     struct vif_params *params);
 int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
 			     enum nl80211_iftype type);
+bool ieee80211_is_hw_80211_encap(struct ieee80211_local *local);
 void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
 void ieee80211_remove_interfaces(struct ieee80211_local *local);
 u32 ieee80211_idle_off(struct ieee80211_local *local);
@@ -1760,6 +1763,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
 					 struct net_device *dev);
 netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 				       struct net_device *dev);
+netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+					    struct net_device *dev);
 void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 				  struct net_device *dev,
 				  u32 info_flags);
@@ -1935,6 +1940,11 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
 				 struct sk_buff *skb, int tid,
 				 enum nl80211_band band, u32 txdata_flags);
 
+/* sta_out needs to be checked for ERR_PTR() before using */
+int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
+			    struct sk_buff *skb,
+			    struct sta_info **sta_out);
+
 static inline void
 ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
 			  struct sk_buff *skb, int tid,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 4a6ff1482a9f..aa8f967f2b27 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1177,6 +1177,77 @@ static const struct net_device_ops ieee80211_dataif_ops = {
 	.ndo_get_stats64	= ieee80211_get_stats64,
 };
 
+static const struct net_device_ops ieee80211_dataif_8023_ops = {
+	.ndo_open		= ieee80211_open,
+	.ndo_stop		= ieee80211_stop,
+	.ndo_uninit		= ieee80211_uninit,
+	.ndo_start_xmit		= ieee80211_subif_start_xmit_8023,
+	.ndo_set_rx_mode	= ieee80211_set_multicast_list,
+	.ndo_set_mac_address	= ieee80211_change_mac,
+	.ndo_select_queue	= ieee80211_netdev_select_queue,
+	.ndo_get_stats64	= ieee80211_get_stats64,
+};
+
+int ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct ieee80211_local *local = sdata->local;
+
+	if (enable == sdata->hw_80211_encap)
+		return enable;
+
+	if (!sdata->dev)
+		return 0;
+
+	if (!ieee80211_hw_check(&local->hw, SUPPORTS_80211_ENCAP))
+		enable = 0;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		if (sdata->u.mgd.use_4addr)
+			enable = 0;
+		break;
+	case NL80211_IFTYPE_AP_VLAN:
+		if (sdata->wdev.use_4addr)
+			enable = 0;
+		break;
+	default:
+		break;
+	}
+
+	if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
+	    (local->hw.wiphy->frag_threshold != (u32)-1))
+		enable = 0;
+
+	if (enable) {
+		sdata->dev->netdev_ops = &ieee80211_dataif_8023_ops;
+		sdata->hw_80211_encap = true;
+	} else {
+		sdata->dev->netdev_ops = &ieee80211_dataif_ops;
+		sdata->hw_80211_encap = false;
+	}
+
+	return enable;
+}
+EXPORT_SYMBOL(ieee80211_set_hw_80211_encap);
+
+bool ieee80211_is_hw_80211_encap(struct ieee80211_local *local)
+{
+	struct ieee80211_sub_if_data *sdata;
+	bool offloaded = false;
+
+	mutex_lock(&local->iflist_mtx);
+	list_for_each_entry(sdata, &local->interfaces, list) {
+		if (sdata->hw_80211_encap) {
+			offloaded = true;
+			break;
+		}
+	}
+	mutex_unlock(&local->iflist_mtx);
+
+	return offloaded;
+}
+
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
 					  struct sk_buff *skb,
 					  struct net_device *sb_dev,
@@ -1409,6 +1480,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 	sdata->vif.bss_conf.idle = true;
 
 	sdata->noack_map = 0;
+	sdata->hw_80211_encap = false;
 
 	/* only monitor/p2p-device differ */
 	if (sdata->dev) {
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 4700718e010f..b43888556901 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -171,6 +171,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 			goto out_unsupported;
 	}
 
+	/* TKIP countermeasures wont work on encap offload mode */
+	if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
+		ieee80211_set_hw_80211_encap(&sdata->vif, 0);
+
 	ret = drv_set_key(key->local, SET_KEY, sdata,
 			  sta ? &sta->sta : NULL, &key->conf);
 
@@ -197,6 +201,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 			  key->conf.keyidx,
 			  sta ? sta->sta.addr : bcast_addr, ret);
 
+	if (sdata->hw_80211_encap)
+		return -EINVAL;
+
  out_unsupported:
 	switch (key->conf.cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 800e67615e2a..a49bcec3891e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1000,9 +1000,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 		hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
 	}
 
-	/* mac80211 always supports monitor */
-	hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
-	hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
+	if (ieee80211_hw_check(hw, SUPPORTS_80211_ENCAP)) {
+		/* mac80211 always supports monitor unless we do 802.11
+		 * encapsulation offloading.
+		 */
+		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
+		hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
+	}
 
 	/* mac80211 doesn't support more than one IBSS interface right now */
 	for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 5b9952b1caf3..8feafaab88a4 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -1019,6 +1019,85 @@ void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_tx_rate_update);
 
+void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif,
+			      struct sk_buff *skb)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct sta_info *sta;
+	int retry_count;
+	int rates_idx;
+	bool acked;
+
+	if (WARN_ON(!ieee80211_hw_check(hw, SUPPORTS_80211_ENCAP)))
+		goto skip_stats_update;
+
+	sdata = vif_to_sdata(vif);
+
+	acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
+	rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+
+	rcu_read_lock();
+
+	if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
+		rcu_read_unlock();
+		goto counters_update;
+	}
+
+	if (!sta || IS_ERR(sta)) {
+		rcu_read_unlock();
+		goto counters_update;
+	}
+
+	if (!acked)
+		sta->status_stats.retry_failed++;
+
+	if (rates_idx != -1)
+		sta->tx_stats.last_rate = info->status.rates[rates_idx];
+
+	sta->status_stats.retry_count += retry_count;
+
+	if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
+		if (acked && vif->type == NL80211_IFTYPE_STATION)
+			ieee80211_sta_reset_conn_monitor(sdata);
+
+		sta->status_stats.last_ack = jiffies;
+		if (info->flags & IEEE80211_TX_STAT_ACK) {
+			if (sta->status_stats.lost_packets)
+				sta->status_stats.lost_packets = 0;
+
+			if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
+				sta->status_stats.last_tdls_pkt_time = jiffies;
+		} else {
+			ieee80211_lost_packet(sta, info);
+		}
+	}
+
+	rcu_read_unlock();
+
+counters_update:
+	ieee80211_led_tx(local);
+
+	if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
+	    !(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED))
+		goto skip_stats_update;
+
+	I802_DEBUG_INC(local->dot11TransmittedFrameCount);
+	if (is_multicast_ether_addr(skb->data))
+		I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
+	if (retry_count > 0)
+		I802_DEBUG_INC(local->dot11RetryCount);
+	if (retry_count > 1)
+		I802_DEBUG_INC(local->dot11MultipleRetryCount);
+
+skip_stats_update:
+	ieee80211_report_used_skb(local, skb, false);
+	dev_kfree_skb(skb);
+}
+EXPORT_SYMBOL(ieee80211_tx_status_8023);
+
 void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
 {
 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8a49a74c0a37..fbd4b5267e04 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1253,7 +1253,8 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
 	    (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
 		return NULL;
 
-	if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
+	if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
+	    unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
 		if ((!ieee80211_is_mgmt(hdr->frame_control) ||
 		     ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
 		     vif->type == NL80211_IFTYPE_STATION) &&
@@ -2357,9 +2358,9 @@ static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
 	       skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
 }
 
-static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
-				   struct sk_buff *skb,
-				   struct sta_info **sta_out)
+int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
+			    struct sk_buff *skb,
+			    struct sta_info **sta_out)
 {
 	struct sta_info *sta;
 
@@ -2855,7 +2856,9 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	__le16 fc;
 
-	if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
+	/* check for driver support and ieee80211 encap offload */
+	if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) ||
+	    sdata->hw_80211_encap)
 		return;
 
 	/* Locking here protects both the pointer itself, and against concurrent
@@ -3573,6 +3576,9 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
 		goto begin;
 	}
 
+	if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
+		goto encap_out;
+
 	if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
 		info->flags |= IEEE80211_TX_CTL_AMPDU;
 	else
@@ -3634,8 +3640,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
 		break;
 	}
 
+encap_out:
 	IEEE80211_SKB_CB(skb)->control.vif = vif;
-
 out:
 	spin_unlock_bh(&fq->lock);
 
@@ -4003,6 +4009,167 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 	return NETDEV_TX_OK;
 }
 
+static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
+			      struct sk_buff *skb, int led_len,
+			      struct sta_info *sta,
+			      bool txpending)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_tx_control control = {};
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_sta *pubsta = NULL;
+	unsigned long flags;
+	int q = info->hw_queue;
+
+	if (ieee80211_queue_skb(local, sdata, sta, skb))
+		return true;
+
+	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+
+	if (local->queue_stop_reasons[q] ||
+	    (!txpending && !skb_queue_empty(&local->pending[q]))) {
+		if (txpending)
+			skb_queue_head(&local->pending[q], skb);
+		else
+			skb_queue_tail(&local->pending[q], skb);
+
+		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+
+		return false;
+	}
+
+	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+
+	if (sta && sta->uploaded)
+		pubsta = &sta->sta;
+
+	control.sta = pubsta;
+
+	drv_tx(local, &control, skb);
+
+	return true;
+}
+
+static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
+				struct net_device *dev, struct sta_info *sta,
+				struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ethhdr *ehdr = (struct ethhdr *)skb->data;
+	struct ieee80211_local *local = sdata->local;
+	bool authorized = false;
+	bool multicast;
+	bool tdls_peer;
+	unsigned char *ra = NULL;
+
+	if (IS_ERR(sta) || (sta && !sta->uploaded))
+		sta = NULL;
+
+	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+		tdls_peer = test_sta_flag(sta, WLAN_STA_TDLS_PEER);
+		if (tdls_peer)
+			ra = skb->data;
+		else
+			ra = sdata->u.mgd.bssid;
+	} else {
+		ra = ehdr->h_dest;
+	}
+
+	if (!ra)
+		goto out_free;
+	multicast = is_multicast_ether_addr(ra);
+
+	if (sta)
+		authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+
+	if (!multicast && !authorized &&
+	    ((ehdr->h_proto != sdata->control_port_protocol) ||
+	     !ether_addr_equal(sdata->vif.addr, ehdr->h_source)))
+		goto out_free;
+
+	if (multicast && sdata->vif.type == NL80211_IFTYPE_AP &&
+	    !atomic_read(&sdata->u.ap.num_mcast_sta))
+		goto out_free;
+
+	if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
+	    test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
+		goto out_free;
+
+	/* TODO: Handle frames requiring wifi tx status to be notified */
+
+	memset(info, 0, sizeof(*info));
+
+	if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) {
+		if (sdata->control_port_no_encrypt)
+			info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+		info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
+	}
+
+	if (multicast)
+		info->flags |= IEEE80211_TX_CTL_NO_ACK;
+
+	info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
+
+	ieee80211_tx_stats(dev, skb->len);
+
+	if (sta) {
+		sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
+		sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
+	}
+
+	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+		sdata = container_of(sdata->bss,
+				     struct ieee80211_sub_if_data, u.ap);
+
+	info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
+	info->control.vif = &sdata->vif;
+
+	ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
+
+	return;
+
+out_free:
+	kfree_skb(skb);
+}
+
+netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+					    struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct sta_info *sta;
+
+	if (WARN_ON(unlikely(!sdata->hw_80211_encap))) {
+		kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (unlikely(skb->len < ETH_HLEN)) {
+		kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (WARN_ON(dev->ieee80211_ptr->use_4addr)) {
+		kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	rcu_read_lock();
+
+	if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
+		goto out_free;
+
+	ieee80211_8023_xmit(sdata, dev, sta, skb);
+
+	goto out;
+
+out_free:
+	kfree_skb(skb);
+out:
+	rcu_read_unlock();
+
+	return NETDEV_TX_OK;
+}
+
 struct sk_buff *
 ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
 			      struct sk_buff *skb, u32 info_flags)
@@ -4081,6 +4248,16 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
 		}
 		info->band = chanctx_conf->def.chan->band;
 		result = ieee80211_tx(sdata, NULL, skb, true, 0);
+	} else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
+		if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
+			dev_kfree_skb(skb);
+			return true;
+		}
+
+		if (IS_ERR(sta) || (sta && !sta->uploaded))
+			sta = NULL;
+
+		result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true);
 	} else {
 		struct sk_buff_head skbs;
 
-- 
2.11.0


^ permalink raw reply related

* [RFC V4 0/2] mac80211: add 802.11 encapsulation offloading
From: John Crispin @ 2019-04-10  7:35 UTC (permalink / raw)
  To: Johannes Berg, Kalle Valo
  Cc: linux-wireless, Srini Kode, Rajkumar Manoharan,
	Shashidhar Lakkavalli, John Crispin

This series picks up prior work from QCA. The patch is currently shipped
inside QSDK as part of the wlan-open package.

The series tries to address all feedback from the V2
-> https://patchwork.kernel.org/patch/9602585/

Changes in V3
* rebase on latest kernel
* various code style clean ups
* give so eof the variables and functions more obvious names
* move the code that disables support for non linear frames to the core
* disable monitor and tkip support

Changes in V4
* disable encap when TKIP is used instead of refusing TKIP
* use a flag inside fx_info instead of an extra element
* move 4addr detection into ieee80211_set_hw_80211_encap()
* ieee80211_tx_dequeue() was dropping out to early

Vasanthakumar Thiagarajan (2):
  mac80211: add hw 80211 encapsulation offloading support
  ath10k: add tx hw 802.11 encapusaltion offloading support

 drivers/net/wireless/ath/ath10k/core.c   |  11 ++
 drivers/net/wireless/ath/ath10k/core.h   |   3 +
 drivers/net/wireless/ath/ath10k/htt_tx.c |  24 ++--
 drivers/net/wireless/ath/ath10k/mac.c    |  70 +++++++++---
 drivers/net/wireless/ath/ath10k/txrx.c   |  11 +-
 include/net/mac80211.h                   |  25 ++++
 net/mac80211/cfg.c                       |   3 +
 net/mac80211/debugfs.c                   |   1 +
 net/mac80211/ieee80211_i.h               |  10 ++
 net/mac80211/iface.c                     |  72 ++++++++++++
 net/mac80211/key.c                       |   7 ++
 net/mac80211/main.c                      |  10 +-
 net/mac80211/status.c                    |  79 +++++++++++++
 net/mac80211/tx.c                        | 189 ++++++++++++++++++++++++++++++-
 14 files changed, 481 insertions(+), 34 deletions(-)

-- 
2.11.0


^ permalink raw reply

* Re: [RFC V3 1/2] mac80211: add hw 80211 encapsulation offloading support
From: John Crispin @ 2019-04-10  7:28 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen
  Cc: linux-wireless, Shashidhar Lakkavalli, Vasanthakumar Thiagarajan
In-Reply-To: <87k1gcpwgy.fsf@toke.dk>


On 02/04/2019 11:50, Toke Høiland-Jørgensen wrote:
> ieee80211_queue_skb() calls ieee80211_get_txq() which treats skb->data
> like it contains an 802.11 header. That is probably not the intention
> here, is it?
>
> I guess we could augment the TXQ stuctures to also handle 802.3 frames
> (and introduce ieee80211_queue_skb_8023())? Or would it be better to
> have a qdisc on 802.3-mode interfaces and push packets back to that? I
> guess we'd still benefit from per-station queueing of packets even if
> they are Ethernet frames, which would mean amending the TXQs would be
> better?
>
> -Toke

Hi Toke

This patch guards the usage of the hdr pointer. hdr is only used for non 
data frames which are not relevant when doing encap mode. The code will 
then drop into the same path as for 80211 encapsulated frames. IMHO the 
patch is correct and we do not need an additional 
ieee80211_queue_skb_8023()  to benefit from per station TXQs. Let me 
know if i missed something.

     John



^ permalink raw reply

* Re: gsmtap design/extensions?
From: Johannes Berg @ 2019-04-10  7:23 UTC (permalink / raw)
  To: Vadim Yanitskiy
  Cc: Harald Welte, OpenBSC Mailing List, Sean Tranchetti, radiotap,
	Dan Williams, netdev, linux-wireless, Aleksander Morgado,
	Subash Abhinov Kasiviswanathan, Bjørn Mork
In-Reply-To: <CAPEnp=bHTVARr7WA9Qkq4=y7kk8_FLWhrkqKOEXubMO4X=BHCw@mail.gmail.com>

On Wed, 2019-04-10 at 13:35 +0700, Vadim Yanitskiy wrote:
> Hello Johannes,
> 
> FYI, there already was a discussion about GSMTAPv3:
> 
> https://www.youtube.com/watch?v=vum9jzavZi0&list=PL07C78AF831FFE8F9&index=10
> 
> but unfortunately, nobody has invested time into this (yet?).

2012! But, umm, I don't really have time for a whole video right now -
anyone have the slides? :-)

But yeah, the first slides look sensible :-)

> > 1) Why the design with encapsulating it in UDP?
> 
> This gives us a possibility to "demux" multiple GSMTAP streams on the
> receiving side, e.g. if you are running multiple processes.

Not sure I get this, but I also don't really care all that much. It's
just a pretty strange design if the kernel were to output this, I'm not
even sure how I'd do that properly. I don't want to be generating UDP
packets there...

Perhaps we can define something (GSMTAPv3) to not really care how it's
encapsulated, and for 'native' packet captures like what I want on Linux
when integrated with the driver, actually use an ARPHDR_GSMTAP, and
encapsulate in UDP when you create it in an application and want to send
it elsewhere, rather than just writing it to a pcap file?

johannes


^ permalink raw reply

* Re: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: Dan Carpenter @ 2019-04-10  6:56 UTC (permalink / raw)
  To: Alastair D'Silva
  Cc: alastair, linux-fbdev, Stanislaw Gruszka, Petr Mladek,
	David Airlie, Joonas Lahtinen, dri-devel, devel, linux-scsi,
	Jassi Brar, ath10k, intel-gfx, Jose Abreu, Tom Lendacky,
	James E.J. Bottomley, Jani Nikula, linux-fsdevel, Steven Rostedt,
	Rodrigo Vivi, Benson Leung, Kalle Valo, Karsten Keil,
	Martin K. Petersen, Greg Kroah-Hartman, linux-wireless,
	linux-kernel, Sergey Senozhatsky, Daniel Vetter, netdev,
	Enric Balletbo i Serra, Andrew Morton, David S. Miller,
	Alexander Viro
In-Reply-To: <20190410031720.11067-4-alastair@au1.ibm.com>

On Wed, Apr 10, 2019 at 01:17:19PM +1000, Alastair D'Silva wrote:
> @@ -107,7 +108,7 @@ EXPORT_SYMBOL(bin2hex);
>   * string if enough space had been available.
>   */
>  int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
> -		       char *linebuf, size_t linebuflen, bool ascii)
> +		       char *linebuf, size_t linebuflen, u64 flags)
>  {
>  	const u8 *ptr = buf;
>  	int ngroups;
> @@ -184,7 +185,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
>  		if (j)
>  			lx--;
>  	}
> -	if (!ascii)
> +	if (!flags & HEXDUMP_ASCII)
            ^^^^^^^^^^^^^^^^^^^^^^
This is a precedence bug.  It should be if (!(flags & HEXDUMP_ASCII)).


>  		goto nil;
>  

regards,
dan carpenter



^ permalink raw reply

* Re: gsmtap design/extensions?
From: Vadim Yanitskiy @ 2019-04-10  6:35 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Harald Welte, OpenBSC Mailing List, Sean Tranchetti, radiotap,
	Dan Williams, netdev, linux-wireless, Aleksander Morgado,
	Subash Abhinov Kasiviswanathan, Bjørn Mork
In-Reply-To: <cf07ae24c436f92769f9289d208f01846ebe8826.camel@sipsolutions.net>

Hello Johannes,

FYI, there already was a discussion about GSMTAPv3:

https://www.youtube.com/watch?v=vum9jzavZi0&list=PL07C78AF831FFE8F9&index=10

but unfortunately, nobody has invested time into this (yet?).

> 1) Why the design with encapsulating it in UDP?

This gives us a possibility to "demux" multiple GSMTAP streams on the
receiving side, e.g. if you are running multiple processes.

> 2) The format of gsmtap doesn't seem very extensible [...]

ACK. I definitely support the idea of using TLVs.

With best regards,
Vadim Yanitskiy.

^ permalink raw reply

* Re: [RFC/RFT] mac80211: Switch to a virtual time-based airtime scheduler
From: Yibo Zhao @ 2019-04-10  6:35 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen
  Cc: make-wifi-fast, linux-wireless, Felix Fietkau, Rajkumar Manoharan,
	Kan Yan, linux-wireless-owner
In-Reply-To: <877ec2ykrh.fsf@toke.dk>

On 2019-04-10 04:41, Toke Høiland-Jørgensen wrote:
> Yibo Zhao <yiboz@codeaurora.org> writes:
> 
>> On 2019-04-04 16:31, Toke Høiland-Jørgensen wrote:
>>> Yibo Zhao <yiboz@codeaurora.org> writes:
>>> 
>>>> On 2019-02-16 01:05, Toke Høiland-Jørgensen wrote:
>>>>> This switches the airtime scheduler in mac80211 to use a virtual
>>>>> time-based
>>>>> scheduler instead of the round-robin scheduler used before. This 
>>>>> has
>>>>> a
>>>>> couple of advantages:
>>>>> 
>>>>> - No need to sync up the round-robin scheduler in firmware/hardware
>>>>> with
>>>>>   the round-robin airtime scheduler.
>>>>> 
>>>>> - If several stations are eligible for transmission we can schedule
>>>>> both of
>>>>>   them; no need to hard-block the scheduling rotation until the 
>>>>> head
>>>>> of
>>>>> the
>>>>>   queue has used up its quantum.
>>>>> 
>>>>> - The check of whether a station is eligible for transmission 
>>>>> becomes
>>>>>   simpler (in ieee80211_txq_may_transmit()).
>>>>> 
>>>>> The drawback is that scheduling becomes slightly more expensive, as
>>>>> we
>>>>> need
>>>>> to maintain an rbtree of TXQs sorted by virtual time. This means 
>>>>> that
>>>>> ieee80211_register_airtime() becomes O(logN) in the number of
>>>>> currently
>>>>> scheduled TXQs. However, hopefully this number rarely grows too big
>>>>> (it's
>>>>> only TXQs currently backlogged, not all associated stations), so it
>>>>> shouldn't be too big of an issue.
>>>>> 
>>>>> @@ -1831,18 +1830,32 @@ void ieee80211_sta_register_airtime(struct
>>>>> ieee80211_sta *pubsta, u8 tid,
>>>>>  {
>>>>>  	struct sta_info *sta = container_of(pubsta, struct sta_info, 
>>>>> sta);
>>>>>  	struct ieee80211_local *local = sta->sdata->local;
>>>>> +	struct ieee80211_txq *txq = sta->sta.txq[tid];
>>>>>  	u8 ac = ieee80211_ac_from_tid(tid);
>>>>> -	u32 airtime = 0;
>>>>> +	u64 airtime = 0, weight_sum;
>>>>> +
>>>>> +	if (!txq)
>>>>> +		return;
>>>>> 
>>>>>  	if (sta->local->airtime_flags & AIRTIME_USE_TX)
>>>>>  		airtime += tx_airtime;
>>>>>  	if (sta->local->airtime_flags & AIRTIME_USE_RX)
>>>>>  		airtime += rx_airtime;
>>>>> 
>>>>> +	/* Weights scale so the unit weight is 256 */
>>>>> +	airtime <<= 8;
>>>>> +
>>>>>  	spin_lock_bh(&local->active_txq_lock[ac]);
>>>>> +
>>>>>  	sta->airtime[ac].tx_airtime += tx_airtime;
>>>>>  	sta->airtime[ac].rx_airtime += rx_airtime;
>>>>> -	sta->airtime[ac].deficit -= airtime;
>>>>> +
>>>>> +	weight_sum = local->airtime_weight_sum[ac] ?: 
>>>>> sta->airtime_weight;
>>>>> +
>>>>> +	local->airtime_v_t[ac] += airtime / weight_sum;
>>>> Hi Toke,
>>>> 
>>>> Please ignore the previous two broken emails regarding this new
>>>> proposal
>>>> from me.
>>>> 
>>>> It looks like local->airtime_v_t acts like a Tx criteria. Only the
>>>> stations with less airtime than that are valid for Tx. That means
>>>> there
>>>> are situations, like 50 clients, that some of the stations can be 
>>>> used
>>>> to Tx when putting next_txq in the loop. Am I right?
>>> 
>>> I'm not sure what you mean here. Are you referring to the case where
>>> new
>>> stations appear with a very low (zero) airtime_v_t? That is handled
>>> when
>>> the station is enqueued.
>> Hi Toke,
>> 
>> Sorry for the confusion. I am not referring to the case that you
>> mentioned though it can be solved by your subtle design, max(local vt,
>> sta vt). :-)
>> 
>> Actually, my concern is situation about putting next_txq in the loop.
>> Let me explain a little more and see below.
>> 
>>> @@ -3640,126 +3638,191 @@ EXPORT_SYMBOL(ieee80211_tx_dequeue);
>>>  struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8
>>> ac)
>>>  {
>>>  	struct ieee80211_local *local = hw_to_local(hw);
>>> +	struct rb_node *node = local->schedule_pos[ac];
>>>  	struct txq_info *txqi = NULL;
>>> +	bool first = false;
>>> 
>>>  	lockdep_assert_held(&local->active_txq_lock[ac]);
>>> 
>>> - begin:
>>> -	txqi = list_first_entry_or_null(&local->active_txqs[ac],
>>> -					struct txq_info,
>>> -					schedule_order);
>>> -	if (!txqi)
>>> +	if (!node) {
>>> +		node = rb_first_cached(&local->active_txqs[ac]);
>>> +		first = true;
>>> +	} else
>>> +		node = rb_next(node);
>> 
>> Consider below piece of code from ath10k_mac_schedule_txq:
>> 
>>          ieee80211_txq_schedule_start(hw, ac);
>>          while ((txq = ieee80211_next_txq(hw, ac))) {
>>                  while (ath10k_mac_tx_can_push(hw, txq)) {
>>                          ret = ath10k_mac_tx_push_txq(hw, txq);
>>                          if (ret < 0)
>>                                  break;
>>                  }
>>                  ieee80211_return_txq(hw, txq);
>>                  ath10k_htt_tx_txq_update(hw, txq);
>>                  if (ret == -EBUSY)
>>                          break;
>>          }
>>          ieee80211_txq_schedule_end(hw, ac);
>> 
>> If my understanding is right, local->schedule_pos is used to record 
>> the
>> last scheduled node and used for traversal rbtree for valid txq. There
>> is chance that an empty txq is feeded to return_txq and got removed 
>> from
>> rbtree. The empty txq will always be the rb_first node. Then in the
>> following next_txq, local->schedule_pos becomes meaningless since its
>> rb_next will return NULL and the loop break. Only rb_first get 
>> dequeued
>> during this loop.
>> 
>> 	if (!node || RB_EMPTY_NODE(node)) {
>> 		node = rb_first_cached(&local->active_txqs[ac]);
>> 		first = true;
>> 	} else
>> 		node = rb_next(node);
> 
> Ah, I see what you mean. Yes, that would indeed be a problem - nice
> catch! :)
> 
>> How about this? The nodes on the rbtree will be dequeued and removed
>> from rbtree one by one until HW is busy. Please note local vt and sta
>> vt will not be updated since txq lock is held during this time.
> 
> Insertion and removal from the rbtree are relatively expensive, so I'd
> rather not do that for every txq. I think a better way to solve this
> is to just defer the actual removal from the tree until
> ieee80211_txq_schedule_end()... Will fix that when I submit this again.

Do you mean we keep the empty txqs in the rbtree until loop finishes and 
remove them in ieee80211_txq_schedule_end(may be put return_txq in it)? 
If it is the case, I suppose a list is needed to store the empty txqs so 
as to dequeue them in ieee80211_txq_schedule_end.

And one more thing,

> +               if (sta->airtime[ac].v_t > local->airtime_v_t[ac]) {
> +                       if (first)
> +                               local->airtime_v_t[ac] = 
> sta->airtime[ac].v_t;
> +                       else
> +                               return NULL;

As local->airtime_v_t will not be updated during loop, we don't need to 
return NULL.

> 
> -Toke

-- 
Yibo

^ permalink raw reply

* Re: [PATCH v6 13/20] x86/split_lock: Enable split lock detection by default
From: Thomas Gleixner @ 2019-04-10  6:31 UTC (permalink / raw)
  To: Fenghua Yu
  Cc: Ingo Molnar, Borislav Petkov, H Peter Anvin, Dave Hansen,
	Paolo Bonzini, Ashok Raj, Peter Zijlstra, Kalle Valo, Xiaoyao Li,
	Michael Chan, Ravi V Shankar, linux-kernel, x86, linux-wireless,
	netdev, kvm
In-Reply-To: <20190410000229.GA209676@romley-ivt3.sc.intel.com>

On Tue, 9 Apr 2019, Fenghua Yu wrote:
> On Thu, Apr 04, 2019 at 08:07:57PM +0200, Thomas Gleixner wrote:
> > On Wed, 3 Apr 2019, Fenghua Yu wrote:
> > >  static void early_init_intel(struct cpuinfo_x86 *c)
> > >  {
> > >  	u64 misc_enable;
> > >  
> > > +	init_split_lock_detect(c);
> > 
> > so we have in early boot:
> > 
> > 	early_cpu_init()
> > 	  early_identify_cpu()
> > 	    this_cpu->c_early_init(c)
> > 	      early_init_intel() {
> > 	        init_split_lock_detect();
> > 	      }	
> >             ....
> >             cpu_set_core_cap_bits(c)
> > 	       set(FEATURE_SPLIT_LOCK)
> > 
> > I don't have to understand how init_split_lock_detect() will magically see
> > the feature bit which gets set afterwards, right? 
> 
> early_init_intel() is called twice on the boot CPU. Besides it's called
> in earl_cpu_init(), it's also called in:
> 	identify_boot_cpu()
> 		identify_cpu()
> 			init_intel()
> 				early_init_intel()
> 					init_split_lock_detect();
> 
> It's true that init_split_lock_detect() doesn't see the feature bit when
> it's called for the first time in early_cpu_init(). But it sees the feature
> bit when it's called for the second time in identify_boot_cpu().

That's hideous, really. 

> So is init_split_lock_detect() in the right place?

You're not seriously asking that?

It's obviously not the right place. We are not placing calls at random
points just because they happen to work by chance.

Thanks,

	tglx

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox