* Re: [PATCH 2/4] lib/hexdump.c: Optionally suppress lines of filler bytes
From: Alastair D'Silva @ 2019-04-10 3:32 UTC (permalink / raw)
To: Jani Nikula
Cc: 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-3-alastair@au1.ibm.com>
On Wed, 2019-04-10 at 13:17 +1000, Alastair D'Silva wrote:
> From: Alastair D'Silva <alastair@d-silva.org>
>
> Some buffers may only be partially filled with useful data, while the
> rest
> is padded (typically with 0x00 or 0xff).
>
This patch introduces flags which allow lines of padding bytes to be
> suppressed, making the output easier to interpret:
> HEXDUMP_SUPPRESS_0X00,
> HEXDUMP_SUPPRESS_0XFF
>
> The first and last lines are not suppressed by default, so the
> function
> always outputs something. This behaviour can be further controlled
> with
> the HEXDUMP_SUPPRESS_FIRST & HEXDUMP_SUPPRESS_LAST flags.
>
> An inline wrapper function is provided for backwards compatibility
> with
> existing code, which maintains the original behaviour.
>
> Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
> ---
>
<snip>
> diff --git a/lib/hexdump.c b/lib/hexdump.c
> index b8a164814744..2f3bafb55a44 100644
> --- a/lib/hexdump.c
> +++ b/lib/hexdump.c
> @@ -209,8 +209,21 @@ int hex_dump_to_buffer(const void *buf, size_t
> len, int rowsize, int groupsize,
> EXPORT_SYMBOL(hex_dump_to_buffer);
>
> #ifdef CONFIG_PRINTK
> +
> +static bool buf_is_all(const u8 *buf, size_t len, u8 val)
> +{
> + size_t i;
> +
> + for (i = 0; i < len; i++) {
> + if (buf[i] != val)
> + return false;
> + }
> +
> + return true;
> +}
> +
> /**
> - * print_hex_dump - print a text hex dump to syslog for a binary
> blob of data
> + * print_hex_dump_ext: dump a binary blob of data to syslog in
> hexadecimal
> * @level: kernel log level (e.g. KERN_DEBUG)
> * @prefix_str: string to prefix each line with;
> * caller supplies trailing spaces for alignment if desired
> @@ -221,42 +234,73 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
> * @buf: data blob to dump
> * @len: number of bytes in the @buf
> * @ascii: include ASCII after the hex output
This line should have been removed. I'll address it in V2.
> + * @flags: A bitwise OR of the following flags:
> + * HEXDUMP_ASCII: include ASCII after the hex output
> + * HEXDUMP_SUPPRESS_0X00: suppress lines that are all 0x00
> + * (other than first or last)
> + * HEXDUMP_SUPPRESS_0XFF: suppress lines that are all 0xff
> + * (other than first or last)
> + * HEXDUMP_SUPPRESS_FIRST: allows the first line to be
> suppressed
> + * HEXDUMP_SUPPRESS_LAST: allows the last line to be suppressed
> + * If the first and last line may be
> suppressed,
> + * an empty buffer will not produce any
> output
> *
> * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII
> dump
> * to the kernel log at the specified kernel log level, with an
> optional
> * leading prefix.
> *
> - * print_hex_dump() works on one "line" of output at a time, i.e.,
> + * print_hex_dump_ext() works on one "line" of output at a time,
> i.e.,
> * 16, 32 or 64 bytes of input data converted to hex + ASCII output.
> - * print_hex_dump() iterates over the entire input @buf, breaking it
> into
> + * print_hex_dump_ext() iterates over the entire input @buf,
> breaking it into
> * "line size" chunks to format and print.
> *
> * E.g.:
> - * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
> - * 16, 1, frame->data, frame->len, true);
> + * print_hex_dump_ext(KERN_DEBUG, "raw data: ",
> DUMP_PREFIX_ADDRESS,
> + * 16, 1, frame->data, frame->len, HEXDUMP_ASCII);
> *
> * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
> * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e
> 4f @ABCDEFGHIJKLMNO
> * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
> * ffffffff88089af0: 73727170 77767574 7b7a7978
> 7f7e7d7c pqrstuvwxyz{|}~.
> */
--
Alastair D'Silva mob: 0423 762 819
skype: alastair_dsilva
Twitter: @EvilDeece
blog: http://alastair.d-silva.org
^ permalink raw reply
* [PATCH 1/4] lib/hexdump.c: Allow 64 bytes per line
From: Alastair D'Silva @ 2019-04-10 3:17 UTC (permalink / raw)
To: alastair
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: <20190410031720.11067-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
With modern high resolution screens, we can display more data, which makes
life a bit easier when debugging.
Allow 64 bytes to be dumped per line.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
lib/hexdump.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 81b70ed37209..b8a164814744 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -80,14 +80,14 @@ EXPORT_SYMBOL(bin2hex);
* hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
* @buf: data blob to dump
* @len: number of bytes in the @buf
- * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @rowsize: number of bytes to print per line; must be 16, 32 or 64
* @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @linebuf: where to put the converted data
* @linebuflen: total size of @linebuf, including space for terminating NUL
* @ascii: include ASCII after the hex output
*
* hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
- * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * 16, 32 or 64 bytes of input data converted to hex + ASCII output.
*
* Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
* to a hex + ASCII dump at the supplied memory location.
@@ -116,7 +116,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
int ascii_column;
int ret;
- if (rowsize != 16 && rowsize != 32)
+ if (rowsize != 16 && rowsize != 32 && rowsize != 64)
rowsize = 16;
if (len > rowsize) /* limit to one line at a time */
@@ -216,7 +216,7 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
* caller supplies trailing spaces for alignment if desired
* @prefix_type: controls whether prefix of an offset, address, or none
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
- * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @rowsize: number of bytes to print per line; must be 16, 32 or 64
* @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @buf: data blob to dump
* @len: number of bytes in the @buf
@@ -227,7 +227,7 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
* leading prefix.
*
* print_hex_dump() works on one "line" of output at a time, i.e.,
- * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * 16, 32 or 64 bytes of input data converted to hex + ASCII output.
* print_hex_dump() iterates over the entire input @buf, breaking it into
* "line size" chunks to format and print.
*
@@ -246,9 +246,9 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
{
const u8 *ptr = buf;
int i, linelen, remaining = len;
- unsigned char linebuf[32 * 3 + 2 + 32 + 1];
+ unsigned char linebuf[64 * 3 + 2 + 64 + 1];
- if (rowsize != 16 && rowsize != 32)
+ if (rowsize != 16 && rowsize != 32 && rowsize != 64)
rowsize = 16;
for (i = 0; i < len; i += rowsize) {
--
2.20.1
^ permalink raw reply related
* [PATCH 0/4] Hexdump enhancements
From: Alastair D'Silva @ 2019-04-10 3:17 UTC (permalink / raw)
To: alastair
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
From: Alastair D'Silva <alastair@d-silva.org>
Apologies for the large CC list, it's a heads up for those responsible
for subsystems where a prototype change in generic code causes a change
in those subsystems.
This series enhances hexdump.
These improve the readability of the dumped data in certain situations
(eg. wide terminals are available, many lines of empty bytes exist, etc).
The default behaviour of hexdump is unchanged, however, the prototype
for hex_dump_to_buffer() has changed, and print_hex_dump() has been
renamed to print_hex_dump_ext(), with a wrapper replacing it for
compatibility with existing code, which would have been too invasive to
change.
Alastair D'Silva (4):
lib/hexdump.c: Allow 64 bytes per line
lib/hexdump.c: Optionally suppress lines of filler bytes
lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
lib/hexdump.c: Allow multiple groups to be separated by lines '|'
drivers/gpu/drm/i915/intel_engine_cs.c | 2 +-
drivers/isdn/hardware/mISDN/mISDNisar.c | 6 +-
drivers/mailbox/mailbox-test.c | 2 +-
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +-
.../net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +-
drivers/net/wireless/ath/ath10k/debug.c | 3 +-
.../net/wireless/intel/iwlegacy/3945-mac.c | 2 +-
drivers/platform/chrome/wilco_ec/debugfs.c | 3 +-
drivers/scsi/scsi_logging.c | 8 +-
drivers/staging/fbtft/fbtft-core.c | 2 +-
fs/seq_file.c | 3 +-
include/linux/printk.h | 38 ++++-
lib/hexdump.c | 143 ++++++++++++++----
lib/test_hexdump.c | 5 +-
14 files changed, 168 insertions(+), 53 deletions(-)
--
2.20.1
^ permalink raw reply
* [PATCH 3/4] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: Alastair D'Silva @ 2019-04-10 3:17 UTC (permalink / raw)
To: alastair
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: <20190410031720.11067-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
In order to support additional features in hex_dump_to_buffer, replace
the ascii bool parameter with flags.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
drivers/gpu/drm/i915/intel_engine_cs.c | 2 +-
drivers/isdn/hardware/mISDN/mISDNisar.c | 6 ++++--
drivers/mailbox/mailbox-test.c | 2 +-
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +-
drivers/net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +-
drivers/net/wireless/ath/ath10k/debug.c | 3 ++-
drivers/net/wireless/intel/iwlegacy/3945-mac.c | 2 +-
drivers/platform/chrome/wilco_ec/debugfs.c | 3 ++-
drivers/scsi/scsi_logging.c | 8 +++-----
drivers/staging/fbtft/fbtft-core.c | 2 +-
fs/seq_file.c | 3 ++-
include/linux/printk.h | 2 +-
lib/hexdump.c | 15 ++++++++-------
lib/test_hexdump.c | 5 +++--
14 files changed, 31 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 49fa43ff02ba..fb133e729f9a 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -1318,7 +1318,7 @@ static void hexdump(struct drm_printer *m, const void *buf, size_t len)
WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos,
rowsize, sizeof(u32),
line, sizeof(line),
- false) >= sizeof(line));
+ 0) >= sizeof(line));
drm_printf(m, "[%04zx] %s\n", pos, line);
prev = buf + pos;
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 386731ec2489..f13f34db6c17 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -84,7 +84,8 @@ send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg)
while (l < (int)len) {
hex_dump_to_buffer(msg + l, len - l, 32, 1,
- isar->log, 256, 1);
+ isar->log, 256,
+ HEXDUMP_ASCII);
pr_debug("%s: %s %02x: %s\n", isar->name,
__func__, l, isar->log);
l += 32;
@@ -113,7 +114,8 @@ rcv_mbox(struct isar_hw *isar, u8 *msg)
while (l < (int)isar->clsb) {
hex_dump_to_buffer(msg + l, isar->clsb - l, 32,
- 1, isar->log, 256, 1);
+ 1, isar->log, 256,
+ HEXDUMP_ASCII);
pr_debug("%s: %s %02x: %s\n", isar->name,
__func__, l, isar->log);
l += 32;
diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c
index 4e4ac4be6423..2f9a094d0259 100644
--- a/drivers/mailbox/mailbox-test.c
+++ b/drivers/mailbox/mailbox-test.c
@@ -213,7 +213,7 @@ static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
hex_dump_to_buffer(ptr,
MBOX_BYTES_PER_LINE,
MBOX_BYTES_PER_LINE, 1, touser + l,
- MBOX_HEXDUMP_LINE_LEN, true);
+ MBOX_HEXDUMP_LINE_LEN, HEXDUMP_ASCII);
ptr += MBOX_BYTES_PER_LINE;
l += MBOX_HEXDUMP_LINE_LEN;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 0cc911f928b1..e954a31cee0c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2992,7 +2992,7 @@ void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx)
unsigned int len = min(skb->len - i, 32U);
hex_dump_to_buffer(&skb->data[i], len, 32, 1,
- buffer, sizeof(buffer), false);
+ buffer, sizeof(buffer), 0);
netdev_dbg(netdev, " %#06x: %s\n", i, buffer);
}
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
index eb1c6b03c329..b80adfa1f890 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
@@ -349,7 +349,7 @@ void xlgmac_print_pkt(struct net_device *netdev,
unsigned int len = min(skb->len - i, 32U);
hex_dump_to_buffer(&skb->data[i], len, 32, 1,
- buffer, sizeof(buffer), false);
+ buffer, sizeof(buffer), 0);
netdev_dbg(netdev, " %#06x: %s\n", i, buffer);
}
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 32d967a31c65..4c99ea03226d 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -2662,7 +2662,8 @@ void ath10k_dbg_dump(struct ath10k *ar,
(unsigned int)(ptr - buf));
hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
linebuf + linebuflen,
- sizeof(linebuf) - linebuflen, true);
+ sizeof(linebuf) - linebuflen,
+ HEXDUMP_ASCII);
dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
}
}
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
index 271977f7fbb0..acbe26d22c34 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
@@ -3247,7 +3247,7 @@ il3945_show_measurement(struct device *d, struct device_attribute *attr,
while (size && PAGE_SIZE - len) {
hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
- PAGE_SIZE - len, true);
+ PAGE_SIZE - len, HEXDUMP_ASCII);
len = strlen(buf);
if (PAGE_SIZE - len)
buf[len++] = '\n';
diff --git a/drivers/platform/chrome/wilco_ec/debugfs.c b/drivers/platform/chrome/wilco_ec/debugfs.c
index c090db2cd5be..238ede4a26d8 100644
--- a/drivers/platform/chrome/wilco_ec/debugfs.c
+++ b/drivers/platform/chrome/wilco_ec/debugfs.c
@@ -174,7 +174,8 @@ static ssize_t raw_read(struct file *file, char __user *user_buf, size_t count,
fmt_len = hex_dump_to_buffer(debug_info->raw_data,
debug_info->response_size,
16, 1, debug_info->formatted_data,
- FORMATTED_BUFFER_SIZE, true);
+ FORMATTED_BUFFER_SIZE,
+ HEXDUMP_ASCII);
/* Only return response the first time it is read */
debug_info->response_size = 0;
}
diff --git a/drivers/scsi/scsi_logging.c b/drivers/scsi/scsi_logging.c
index bd70339c1242..fce542bb40e6 100644
--- a/drivers/scsi/scsi_logging.c
+++ b/drivers/scsi/scsi_logging.c
@@ -263,7 +263,7 @@ void scsi_print_command(struct scsi_cmnd *cmd)
"CDB[%02x]: ", k);
hex_dump_to_buffer(&cmd->cmnd[k], linelen,
16, 1, logbuf + off,
- logbuf_len - off, false);
+ logbuf_len - off, 0);
}
dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s",
logbuf);
@@ -274,8 +274,7 @@ void scsi_print_command(struct scsi_cmnd *cmd)
if (!WARN_ON(off > logbuf_len - 49)) {
off += scnprintf(logbuf + off, logbuf_len - off, " ");
hex_dump_to_buffer(cmd->cmnd, cmd->cmd_len, 16, 1,
- logbuf + off, logbuf_len - off,
- false);
+ logbuf + off, logbuf_len - off, 0);
}
out_printk:
dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf);
@@ -354,8 +353,7 @@ scsi_log_dump_sense(const struct scsi_device *sdev, const char *name, int tag,
off = sdev_format_header(logbuf, logbuf_len,
name, tag);
hex_dump_to_buffer(&sense_buffer[i], len, 16, 1,
- logbuf + off, logbuf_len - off,
- false);
+ logbuf + off, logbuf_len - off, 0);
dev_printk(KERN_INFO, &sdev->sdev_gendev, "%s", logbuf);
}
scsi_log_release_buffer(logbuf);
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 9b07badf4c6c..2e5df5cc9d61 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -61,7 +61,7 @@ void fbtft_dbg_hex(const struct device *dev, int groupsize,
va_end(args);
hex_dump_to_buffer(buf, len, 32, groupsize, text + text_len,
- 512 - text_len, false);
+ 512 - text_len, 0);
if (len > 32)
dev_info(dev, "%s ...\n", text);
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 1dea7a8a5255..a0213637af3e 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -873,7 +873,8 @@ void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type,
size = seq_get_buf(m, &buffer);
ret = hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
- buffer, size, ascii);
+ buffer, size,
+ ascii ? HEXDUMP_ASCII : 0);
seq_commit(m, ret < size ? ret : -1);
seq_putc(m, '\n');
diff --git a/include/linux/printk.h b/include/linux/printk.h
index c014e5573665..82975853c400 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -493,7 +493,7 @@ enum {
extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
int groupsize, char *linebuf, size_t linebuflen,
- bool ascii);
+ u64 flags);
#ifdef CONFIG_PRINTK
extern void print_hex_dump_ext(const char *level, const char *prefix_str,
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 2f3bafb55a44..79db784577e7 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -84,7 +84,8 @@ EXPORT_SYMBOL(bin2hex);
* @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @linebuf: where to put the converted data
* @linebuflen: total size of @linebuf, including space for terminating NUL
- * @ascii: include ASCII after the hex output
+ * @flags: A bitwise OR of the following flags:
+ * HEXDUMP_ASCII: include ASCII after the hex output
*
* hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
* 16, 32 or 64 bytes of input data converted to hex + ASCII output.
@@ -95,7 +96,7 @@ EXPORT_SYMBOL(bin2hex);
*
* E.g.:
* hex_dump_to_buffer(frame->data, frame->len, 16, 1,
- * linebuf, sizeof(linebuf), true);
+ * linebuf, sizeof(linebuf), HEXDUMP_ASCII);
*
* example output buffer:
* 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
@@ -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)
goto nil;
while (lx < ascii_column) {
@@ -204,7 +205,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
overflow2:
linebuf[lx++] = '\0';
overflow1:
- return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
+ return (flags & HEXDUMP_ASCII) ? ascii_column + len :
+ (groupsize * 2 + 1) * ngroups - 1;
}
EXPORT_SYMBOL(hex_dump_to_buffer);
@@ -299,8 +301,7 @@ void print_hex_dump_ext(const char *level, const char *prefix_str,
first_line = false;
hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
- linebuf, sizeof(linebuf),
- flags & HEXDUMP_ASCII);
+ linebuf, sizeof(linebuf), flags);
switch (prefix_type) {
case DUMP_PREFIX_ADDRESS:
diff --git a/lib/test_hexdump.c b/lib/test_hexdump.c
index 5144899d3c6b..16bdb483114d 100644
--- a/lib/test_hexdump.c
+++ b/lib/test_hexdump.c
@@ -132,7 +132,7 @@ static void __init test_hexdump(size_t len, int rowsize, int groupsize,
memset(real, FILL_CHAR, sizeof(real));
hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
- ascii);
+ ascii ? HEXDUMP_ASCII : 0);
memset(test, FILL_CHAR, sizeof(test));
test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
@@ -171,7 +171,8 @@ static void __init test_hexdump_overflow(size_t buflen, size_t len,
memset(buf, FILL_CHAR, sizeof(buf));
- r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii);
+ r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen,
+ ascii ? HEXDUMP_ASCII : 0);
/*
* Caller must provide the data length multiple of groupsize. The
--
2.20.1
^ permalink raw reply related
* [PATCH 4/4] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: Alastair D'Silva @ 2019-04-10 3:17 UTC (permalink / raw)
To: alastair
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: <20190410031720.11067-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
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 ........|........
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
include/linux/printk.h | 3 +++
lib/hexdump.c | 50 +++++++++++++++++++++++++++++++++++++-----
2 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 82975853c400..d9e407e59059 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -485,6 +485,9 @@ enum {
#define HEXDUMP_SUPPRESS_0XFF (1 << 2)
#define HEXDUMP_SUPPRESS_FIRST (1 << 3)
#define HEXDUMP_SUPPRESS_LAST (1 << 4)
+#define HEXDUMP_2_GRP_LINES (1 << 5)
+#define HEXDUMP_4_GRP_LINES (1 << 6)
+#define HEXDUMP_8_GRP_LINES (1 << 7)
#define HEXDUMP_QUIET (HEXDUMP_SUPPRESS_0X00 | \
HEXDUMP_SUPPRESS_0XFF | \
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 79db784577e7..d42f34b93b2c 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -76,6 +76,20 @@ char *bin2hex(char *dst, const void *src, size_t count)
}
EXPORT_SYMBOL(bin2hex);
+static const char *group_separator(int group, u64 flags)
+{
+ if ((flags & HEXDUMP_8_GRP_LINES) && ((group - 1) % 8))
+ return "|";
+
+ if ((flags & HEXDUMP_4_GRP_LINES) && ((group - 1) % 4))
+ return "|";
+
+ if ((flags & HEXDUMP_2_GRP_LINES) && ((group - 1) % 2))
+ return "|";
+
+ return " ";
+}
+
/**
* hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
* @buf: data blob to dump
@@ -86,6 +100,9 @@ EXPORT_SYMBOL(bin2hex);
* @linebuflen: total size of @linebuf, including space for terminating NUL
* @flags: A bitwise OR of the following flags:
* HEXDUMP_ASCII: include ASCII after the hex output
+ * HEXDUMP_2_GRP_LINES: insert a '|' after every 2 groups
+ * HEXDUMP_4_GRP_LINES: insert a '|' after every 4 groups
+ * HEXDUMP_8_GRP_LINES: insert a '|' after every 8 groups
*
* hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
* 16, 32 or 64 bytes of input data converted to hex + ASCII output.
@@ -116,6 +133,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
int j, lx = 0;
int ascii_column;
int ret;
+ int line_chars = 0;
if (rowsize != 16 && rowsize != 32 && rowsize != 64)
rowsize = 16;
@@ -141,7 +159,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
for (j = 0; j < ngroups; j++) {
ret = snprintf(linebuf + lx, linebuflen - lx,
- "%s%16.16llx", j ? " " : "",
+ "%s%16.16llx",
+ j ? group_separator(j, flags) : "",
get_unaligned(ptr8 + j));
if (ret >= linebuflen - lx)
goto overflow1;
@@ -152,7 +171,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
for (j = 0; j < ngroups; j++) {
ret = snprintf(linebuf + lx, linebuflen - lx,
- "%s%8.8x", j ? " " : "",
+ "%s%8.8x",
+ j ? group_separator(j, flags) : "",
get_unaligned(ptr4 + j));
if (ret >= linebuflen - lx)
goto overflow1;
@@ -163,7 +183,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
for (j = 0; j < ngroups; j++) {
ret = snprintf(linebuf + lx, linebuflen - lx,
- "%s%4.4x", j ? " " : "",
+ "%s%4.4x",
+ j ? group_separator(j, flags) : "",
get_unaligned(ptr2 + j));
if (ret >= linebuflen - lx)
goto overflow1;
@@ -193,11 +214,26 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
goto overflow2;
linebuf[lx++] = ' ';
}
+
+ if (flags & HEXDUMP_2_GRP_LINES)
+ line_chars = groupsize * 2;
+ if (flags & HEXDUMP_4_GRP_LINES)
+ line_chars = groupsize * 4;
+ if (flags & HEXDUMP_8_GRP_LINES)
+ line_chars = groupsize * 8;
+
for (j = 0; j < len; j++) {
if (linebuflen < lx + 2)
goto overflow2;
ch = ptr[j];
linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
+
+ if (line_chars && ((j + 1) < len) &&
+ ((j + 1) % line_chars == 0)) {
+ if (linebuflen < lx + 2)
+ goto overflow2;
+ linebuf[lx++] = '|';
+ }
}
nil:
linebuf[lx] = '\0';
@@ -205,7 +241,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
overflow2:
linebuf[lx++] = '\0';
overflow1:
- return (flags & HEXDUMP_ASCII) ? ascii_column + len :
+ return (flags & HEXDUMP_ASCII) ? ascii_column + len +
+ (len - 1) / line_chars :
(groupsize * 2 + 1) * ngroups - 1;
}
EXPORT_SYMBOL(hex_dump_to_buffer);
@@ -246,6 +283,9 @@ static bool buf_is_all(const u8 *buf, size_t len, u8 val)
* HEXDUMP_SUPPRESS_LAST: allows the last line to be suppressed
* If the first and last line may be suppressed,
* an empty buffer will not produce any output
+ * HEXDUMP_2_GRP_LINES: insert a '|' after every 2 groups
+ * HEXDUMP_4_GRP_LINES: insert a '|' after every 4 groups
+ * HEXDUMP_8_GRP_LINES: insert a '|' after every 8 groups
*
* Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
* to the kernel log at the specified kernel log level, with an optional
@@ -271,7 +311,7 @@ void print_hex_dump_ext(const char *level, const char *prefix_str,
{
const u8 *ptr = buf;
int i, remaining = len;
- unsigned char linebuf[64 * 3 + 2 + 64 + 1];
+ unsigned char linebuf[64 * 3 + 2 + 64 + 31 + 1];
bool first_line = true;
if (rowsize != 16 && rowsize != 32 && rowsize != 64)
--
2.20.1
^ permalink raw reply related
* [PATCH 2/4] lib/hexdump.c: Optionally suppress lines of filler bytes
From: Alastair D'Silva @ 2019-04-10 3:17 UTC (permalink / raw)
To: alastair
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: <20190410031720.11067-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
Some buffers may only be partially filled with useful data, while the rest
is padded (typically with 0x00 or 0xff).
This patch introduces flags which allow lines of padding bytes to be
suppressed, making the output easier to interpret: HEXDUMP_SUPPRESS_0X00,
HEXDUMP_SUPPRESS_0XFF
The first and last lines are not suppressed by default, so the function
always outputs something. This behaviour can be further controlled with
the HEXDUMP_SUPPRESS_FIRST & HEXDUMP_SUPPRESS_LAST flags.
An inline wrapper function is provided for backwards compatibility with
existing code, which maintains the original behaviour.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
include/linux/printk.h | 38 ++++++++++++++++++----
lib/hexdump.c | 72 ++++++++++++++++++++++++++++++++++--------
2 files changed, 89 insertions(+), 21 deletions(-)
diff --git a/include/linux/printk.h b/include/linux/printk.h
index d7c77ed1a4cb..c014e5573665 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -479,13 +479,26 @@ enum {
DUMP_PREFIX_ADDRESS,
DUMP_PREFIX_OFFSET
};
+
+#define HEXDUMP_ASCII (1 << 0)
+#define HEXDUMP_SUPPRESS_0X00 (1 << 1)
+#define HEXDUMP_SUPPRESS_0XFF (1 << 2)
+#define HEXDUMP_SUPPRESS_FIRST (1 << 3)
+#define HEXDUMP_SUPPRESS_LAST (1 << 4)
+
+#define HEXDUMP_QUIET (HEXDUMP_SUPPRESS_0X00 | \
+ HEXDUMP_SUPPRESS_0XFF | \
+ HEXDUMP_SUPPRESS_FIRST | \
+ HEXDUMP_SUPPRESS_LAST)
+
extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
int groupsize, char *linebuf, size_t linebuflen,
bool ascii);
+
#ifdef CONFIG_PRINTK
-extern void print_hex_dump(const char *level, const char *prefix_str,
- int prefix_type, int rowsize, int groupsize,
- const void *buf, size_t len, bool ascii);
+extern void print_hex_dump_ext(const char *level, const char *prefix_str,
+ int prefix_type, int rowsize, int groupsize,
+ const void *buf, size_t len, u64 flags);
#if defined(CONFIG_DYNAMIC_DEBUG)
#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \
dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true)
@@ -494,18 +507,29 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
const void *buf, size_t len);
#endif /* defined(CONFIG_DYNAMIC_DEBUG) */
#else
-static inline void print_hex_dump(const char *level, const char *prefix_str,
- int prefix_type, int rowsize, int groupsize,
- const void *buf, size_t len, bool ascii)
+static inline void print_hex_dump_ext(const char *level, const char *prefix_str,
+ int prefix_type, int rowsize,
+ int groupsize, const void *buf,
+ size_t len, u64 flags)
{
}
static inline void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
const void *buf, size_t len)
{
}
-
#endif
+static __always_inline void print_hex_dump(const char *level,
+ const char *prefix_str,
+ int prefix_type, int rowsize,
+ int groupsize, const void *buf,
+ size_t len, bool ascii)
+{
+ print_hex_dump_ext(level, prefix_str, prefix_type, rowsize, groupsize,
+ buf, len, ascii ? HEXDUMP_ASCII : 0);
+}
+
+
#if defined(CONFIG_DYNAMIC_DEBUG)
#define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \
groupsize, buf, len, ascii) \
diff --git a/lib/hexdump.c b/lib/hexdump.c
index b8a164814744..2f3bafb55a44 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -209,8 +209,21 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
EXPORT_SYMBOL(hex_dump_to_buffer);
#ifdef CONFIG_PRINTK
+
+static bool buf_is_all(const u8 *buf, size_t len, u8 val)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (buf[i] != val)
+ return false;
+ }
+
+ return true;
+}
+
/**
- * print_hex_dump - print a text hex dump to syslog for a binary blob of data
+ * print_hex_dump_ext: dump a binary blob of data to syslog in hexadecimal
* @level: kernel log level (e.g. KERN_DEBUG)
* @prefix_str: string to prefix each line with;
* caller supplies trailing spaces for alignment if desired
@@ -221,42 +234,73 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
* @buf: data blob to dump
* @len: number of bytes in the @buf
* @ascii: include ASCII after the hex output
+ * @flags: A bitwise OR of the following flags:
+ * HEXDUMP_ASCII: include ASCII after the hex output
+ * HEXDUMP_SUPPRESS_0X00: suppress lines that are all 0x00
+ * (other than first or last)
+ * HEXDUMP_SUPPRESS_0XFF: suppress lines that are all 0xff
+ * (other than first or last)
+ * HEXDUMP_SUPPRESS_FIRST: allows the first line to be suppressed
+ * HEXDUMP_SUPPRESS_LAST: allows the last line to be suppressed
+ * If the first and last line may be suppressed,
+ * an empty buffer will not produce any output
*
* Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
* to the kernel log at the specified kernel log level, with an optional
* leading prefix.
*
- * print_hex_dump() works on one "line" of output at a time, i.e.,
+ * print_hex_dump_ext() works on one "line" of output at a time, i.e.,
* 16, 32 or 64 bytes of input data converted to hex + ASCII output.
- * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * print_hex_dump_ext() iterates over the entire input @buf, breaking it into
* "line size" chunks to format and print.
*
* E.g.:
- * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
- * 16, 1, frame->data, frame->len, true);
+ * print_hex_dump_ext(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
+ * 16, 1, frame->data, frame->len, HEXDUMP_ASCII);
*
* Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
* 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
* Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
* ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
*/
-void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
- int rowsize, int groupsize,
- const void *buf, size_t len, bool ascii)
+void print_hex_dump_ext(const char *level, const char *prefix_str,
+ int prefix_type, int rowsize, int groupsize,
+ const void *buf, size_t len, u64 flags)
{
const u8 *ptr = buf;
- int i, linelen, remaining = len;
+ int i, remaining = len;
unsigned char linebuf[64 * 3 + 2 + 64 + 1];
+ bool first_line = true;
if (rowsize != 16 && rowsize != 32 && rowsize != 64)
rowsize = 16;
for (i = 0; i < len; i += rowsize) {
- linelen = min(remaining, rowsize);
+ bool skip = false;
+ int linelen = min(remaining, rowsize);
+
remaining -= rowsize;
+ if (flags & HEXDUMP_SUPPRESS_0X00)
+ skip = buf_is_all(ptr + i, linelen, 0x00);
+
+ if (!skip && (flags & HEXDUMP_SUPPRESS_0XFF))
+ skip = buf_is_all(ptr + i, linelen, 0xff);
+
+ if (first_line && !(flags & HEXDUMP_SUPPRESS_FIRST))
+ skip = false;
+
+ if (remaining <= 0 && !(flags & HEXDUMP_SUPPRESS_LAST))
+ skip = false;
+
+ if (skip)
+ continue;
+
+ first_line = false;
+
hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
- linebuf, sizeof(linebuf), ascii);
+ linebuf, sizeof(linebuf),
+ flags & HEXDUMP_ASCII);
switch (prefix_type) {
case DUMP_PREFIX_ADDRESS:
@@ -272,7 +316,7 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
}
}
}
-EXPORT_SYMBOL(print_hex_dump);
+EXPORT_SYMBOL(print_hex_dump_ext);
#if !defined(CONFIG_DYNAMIC_DEBUG)
/**
@@ -290,8 +334,8 @@ EXPORT_SYMBOL(print_hex_dump);
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
const void *buf, size_t len)
{
- print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
- buf, len, true);
+ print_hex_dump_ext(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
+ buf, len, HEXDUMP_ASCII);
}
EXPORT_SYMBOL(print_hex_dump_bytes);
#endif /* !defined(CONFIG_DYNAMIC_DEBUG) */
--
2.20.1
^ permalink raw reply related
* RE: [PATCH] ath10k: Remove ATH10K_STATE_RESTARTED in simulate fw crash
From: Wen Gong @ 2019-04-10 2:45 UTC (permalink / raw)
To: Brian Norris
Cc: Michał Kazior, Wen Gong, linux-wireless,
ath10k@lists.infradead.org
In-Reply-To: <CA+ASDXP1Ftpi93p=Bp2w1rRd3xVtNn_+diwkKTMXbTqK0B3ahA@mail.gmail.com>
> -----Original Message-----
> From: Brian Norris <briannorris@chromium.org>
> Sent: Wednesday, April 10, 2019 7:25 AM
> To: Wen Gong <wgong@qti.qualcomm.com>
> Cc: Michał Kazior <kazikcz@gmail.com>; Wen Gong
> <wgong@codeaurora.org>; linux-wireless <linux-wireless@vger.kernel.org>;
> ath10k@lists.infradead.org
> Subject: [EXT] Re: [PATCH] ath10k: Remove ATH10K_STATE_RESTARTED in
> simulate fw crash
>
> On Mon, Apr 8, 2019 at 10:09 PM Wen Gong <wgong@qti.qualcomm.com>
> wrote:
> > > From: Michał Kazior <kazikcz@gmail.com>
> > > To satisfy both I would suggest you either expose ar->state via
> > > debugfs and make your test procedure wait for that to get back into ON
> > > state before simulating a crash again, or to extend the set of current
> > > simulate_fw_crash commands (currently just: soft, hard, assert,
> > > hw-restart) to something that allows expressing the intent whether
> > > crash-in-crash prevention is intended (your case) or not (my original
> > > case).
> > >
> > > This could be for example something like this:
> > > echo soft wait-ready > simulate_fw_crash
> > >
> > > The "wait-ready" extra keyword would imply crash-in-crash prevention.
> > > This would keep existing tools working (both behavior and syntax) and
> > > would allow your test case to be implemented.
> > >
> > Is it easy to change your existing tools?
> > I want to change it to: echo soft skip-ready > simulate_fw_crash
> > The "skip-ready" extra keyword would imply crash-in-crash, *not*
> prevention.
> > My test tools is hard to change.
>
> In case you're talking about the test framework we run for ChromeOS
> validation, no, it's not hard at all to change. As long as there's a
> good reason.
>
> I haven't closely followed this, but judging by the above summary,
> it's probably more reasonable for our test framework to only simulate
> FW crashes after the driver returns to "ready" (or at least, if we do
> crash-in-crash, don't expect the driver to recover?). I expect we can
> work with whatever mechanism you implement for that (exposing the
> "state", or providing a new simulate_fw_crash mode).
>
If ChromeOS is easy to change tool,
I think I will change the mechanism of the simulate_fw_crash.
Then all tools will work normally.
> Brian
^ permalink raw reply
* Re: [PATCH v6 13/20] x86/split_lock: Enable split lock detection by default
From: Fenghua Yu @ 2019-04-10 0:02 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.1904041932500.1802@nanos.tec.linutronix.de>
On Thu, Apr 04, 2019 at 08:07:57PM +0200, Thomas Gleixner wrote:
> On Wed, 3 Apr 2019, Fenghua Yu wrote:
>
> > +static void init_split_lock_detect(struct cpuinfo_x86 *c)
> > +{
> > + if (cpu_has(c, X86_FEATURE_SPLIT_LOCK_DETECT)) {
> > + u32 l, h;
> > +
> > + mutex_lock(&split_lock_detect_mutex);
> > + rdmsr(MSR_TEST_CTL, l, h);
> > + l = new_sp_test_ctl_val(l);
> > + wrmsr(MSR_TEST_CTL, l, h);
> > + show_split_lock_detection_info();
> > + mutex_unlock(&split_lock_detect_mutex);
> > + }
> > +}
> > +
> > 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().
So is init_split_lock_detect() in the right place?
Thanks.
-Fenghua
^ permalink raw reply
* Re: [PATCH] ath10k: Remove ATH10K_STATE_RESTARTED in simulate fw crash
From: Brian Norris @ 2019-04-09 23:25 UTC (permalink / raw)
To: Wen Gong
Cc: Michał Kazior, Wen Gong, linux-wireless,
ath10k@lists.infradead.org
In-Reply-To: <1fec49e1b6794860a1eff2330bcdea28@aptaiexm02f.ap.qualcomm.com>
On Mon, Apr 8, 2019 at 10:09 PM Wen Gong <wgong@qti.qualcomm.com> wrote:
> > From: Michał Kazior <kazikcz@gmail.com>
> > To satisfy both I would suggest you either expose ar->state via
> > debugfs and make your test procedure wait for that to get back into ON
> > state before simulating a crash again, or to extend the set of current
> > simulate_fw_crash commands (currently just: soft, hard, assert,
> > hw-restart) to something that allows expressing the intent whether
> > crash-in-crash prevention is intended (your case) or not (my original
> > case).
> >
> > This could be for example something like this:
> > echo soft wait-ready > simulate_fw_crash
> >
> > The "wait-ready" extra keyword would imply crash-in-crash prevention.
> > This would keep existing tools working (both behavior and syntax) and
> > would allow your test case to be implemented.
> >
> Is it easy to change your existing tools?
> I want to change it to: echo soft skip-ready > simulate_fw_crash
> The "skip-ready" extra keyword would imply crash-in-crash, *not* prevention.
> My test tools is hard to change.
In case you're talking about the test framework we run for ChromeOS
validation, no, it's not hard at all to change. As long as there's a
good reason.
I haven't closely followed this, but judging by the above summary,
it's probably more reasonable for our test framework to only simulate
FW crashes after the driver returns to "ready" (or at least, if we do
crash-in-crash, don't expect the driver to recover?). I expect we can
work with whatever mechanism you implement for that (exposing the
"state", or providing a new simulate_fw_crash mode).
Brian
^ permalink raw reply
* Re: [RFC/RFT] mac80211: Switch to a virtual time-based airtime scheduler
From: Toke Høiland-Jørgensen @ 2019-04-09 20:41 UTC (permalink / raw)
To: Yibo Zhao
Cc: make-wifi-fast, linux-wireless, Felix Fietkau, Rajkumar Manoharan,
Kan Yan, linux-wireless-owner
In-Reply-To: <acd33756e87ea64c608e306e5ee60aa2@codeaurora.org>
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.
-Toke
^ permalink raw reply
* Re: [PATCH v2 0/4] Extended Key ID support
From: Alexander Wetzel @ 2019-04-09 19:39 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <98e1f8942056486669c6295323ef09763fd2ec0a.camel@sipsolutions.net>
Am 08.04.19 um 21:57 schrieb Johannes Berg:
> On Tue, 2019-03-19 at 21:34 +0100, Alexander Wetzel wrote:
>> 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.
But if you or someone else want to run some tests prior to that.
I've updated the patches available here with the ones I'm currently
using: https://www.awhome.eu/index.php/s/AJJXBLsZmzHdxpX
They are fully functional and I'm using them on my main AP and
workstation for months now.
They are on top of the current hostapd HEAD and should not cause any
regressions. They are also comparable simple to port between versions.
The code we touch here has not been changed in any relevant way since I
started working on the patches. Just really copy nl80211_copy.h from the
kernel...
A sad side note:
I'm pretty sure I've already found one broken Wlan implementation:
Samsung Galaxy Tap S3
This device seems to just copy the RSN Capability (bit) from the AP and
then fails when the AP rekeys the connection and starts using keyid 1...
But it's probably a Samsung specific bug, other Android devices -
including a Google Pixel 3 - don't "lie" in the RSN and are using
"legacy" key installs as they should.
>
> We briefly discussed this at the wireless workshop, and the general
> feeling seems to have been that the compat mode is probably not really
> worthwhile, but I haven't quite made up my mind on that.
I would like to be able to support Extended Key ID for the the Atheros
cards < ath10k... Maybe that gets the attention of someone who can fix
the ath10k firmware to also support it, hopefully in NATIVE mode:-)
But I see that the COMPAT mode may not be worth the added complexity in
the long term.
Which reminds me:
One potential follow up on the COMPAT code would be seamless Rx during
rekey even when not using Extended Key ID. It would need some slight of
hand but I think it's possible. Basically we just would have to try the
second key also if the first one did not decode the MPTU. So far I've
shelved any plans into that direction as too complex for too little
gain. And after all people should just start using Extended Key ID
instead. After all that's the point of having standards...
> Still, having tests and being able to check it out would help a lot,
> also as part of perhaps building a case for compat mode.
Besides some review of the patches with my improved 802.11/code
understanding the only thing missing in the current
wpa_supplicant/hostapd patches *are* the test cases.
The existing rekey tests are already working fine with Extended Key ID.
Separating Extended Key ID rekey from "legacy" rekeys tests is probably
half of the work here...
With the patches you merged and the linked hostapd/wpa_supplicant
patches any (WPA2) rekey test will use Extended Key ID. (They won't test
any of the really interesting code pathes in the kernel, trough. No
A-MPDU, no TX-Pull and of course no HW crypto or RX/TX fast path if I
remember it right.)
Thanks,
Alexander
^ permalink raw reply
* [PATCH 6/6] ath10k: sdio: replace skb_trim with explicit set of skb->len
From: Erik Stromdahl @ 2019-04-09 19:08 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <20190409190851.4557-1-erik.stromdahl@gmail.com>
This patch fixes a bug with padding of the skb data buffer.
Since skb_trim can only be used to reduce the skb len, it is useless when
we pad (increase the length of) the skb. Instead we must set skb->len
directly.
Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
drivers/net/wireless/ath/ath10k/sdio.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 3eb241cb8a25..989e3f563f3d 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1496,7 +1496,12 @@ static int ath10k_sdio_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
skb = items[i].transfer_context;
padded_len = ath10k_sdio_calc_txrx_padded_len(ar_sdio,
skb->len);
- skb_trim(skb, padded_len);
+ /* FIXME: unsure if just extending the skb len is the right
+ * thing to do since we might read outside the skb->data
+ * buffer. But we really don't want to realloc the skb just to
+ * pad the length.
+ */
+ skb->len = padded_len;
/* Write TX data to the end of the mbox address space */
address = ar_sdio->mbox_addr[eid] + ar_sdio->mbox_size[eid] -
--
2.19.1
^ permalink raw reply related
* [PATCH 3/6] ath10k: sdio: read RX packets in bundles
From: Erik Stromdahl @ 2019-04-09 19:08 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Alagu Sankar, Erik Stromdahl
In-Reply-To: <20190409190851.4557-1-erik.stromdahl@gmail.com>
From: Alagu Sankar <alagusankar@silex-india.com>
The existing implementation of initiating multiple sdio transfers for
receive bundling is slowing down the receive speed.
Instead of having one sdio transfer for each packet in the bundle, we
read all packets in one sdio transfer.
This results in significant performance improvement on some targets.
Co-developed-by: Erik Stromdahl <erik.stromdahl@gmail.com>
Signed-off-by: Alagu Sankar <alagusankar@silex-india.com>
Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
drivers/net/wireless/ath/ath10k/sdio.c | 66 +++++++++++++++++++++-----
drivers/net/wireless/ath/ath10k/sdio.h | 2 +
2 files changed, 55 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index fae56c67766f..295e1e7ec3b0 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -24,6 +24,8 @@
#include "trace.h"
#include "sdio.h"
+#define ATH10K_SDIO_READ_BUF_SIZE (32 * 1024)
+
/* inlined helper functions */
static inline int ath10k_sdio_calc_txrx_padded_len(struct ath10k_sdio *ar_sdio,
@@ -618,41 +620,68 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
return ret;
}
-static int ath10k_sdio_mbox_rx_packet(struct ath10k *ar,
- struct ath10k_sdio_rx_data *pkt)
+static int ath10k_sdio_mbox_rx_fetch(struct ath10k *ar)
{
struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_rx_data *pkt = &ar_sdio->rx_pkts[0];
struct sk_buff *skb = pkt->skb;
int ret;
- ret = ath10k_sdio_readsb(ar, ar_sdio->mbox_info.htc_addr,
- skb->data, pkt->alloc_len);
- pkt->status = ret;
- if (!ret)
+ ret = ath10k_sdio_read(ar, ar_sdio->mbox_info.htc_addr,
+ skb->data, pkt->alloc_len);
+ if (ret) {
+ ar_sdio->n_rx_pkts = 0;
+ ath10k_sdio_mbox_free_rx_pkt(pkt);
+ } else {
+ pkt->status = ret;
skb_put(skb, pkt->act_len);
+ }
return ret;
}
-static int ath10k_sdio_mbox_rx_fetch(struct ath10k *ar)
+static int ath10k_sdio_mbox_rx_fetch_bundle(struct ath10k *ar)
{
struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_rx_data *pkt;
int ret, i;
+ u32 pkt_offset = 0, pkt_bundle_len = 0;
+
+ for (i = 0; i < ar_sdio->n_rx_pkts; i++)
+ pkt_bundle_len += ar_sdio->rx_pkts[i].alloc_len;
+
+ if (pkt_bundle_len > ATH10K_SDIO_READ_BUF_SIZE) {
+ ret = -ENOMEM;
+ ath10k_err(ar, "bundle size (%d) exceeding limit %d\n",
+ pkt_bundle_len, ATH10K_SDIO_READ_BUF_SIZE);
+ goto err;
+ }
+
+ ret = ath10k_sdio_readsb(ar, ar_sdio->mbox_info.htc_addr,
+ ar_sdio->sdio_read_buf, pkt_bundle_len);
+ if (ret)
+ goto err;
for (i = 0; i < ar_sdio->n_rx_pkts; i++) {
- ret = ath10k_sdio_mbox_rx_packet(ar,
- &ar_sdio->rx_pkts[i]);
- if (ret)
- goto err;
+ struct sk_buff *skb = ar_sdio->rx_pkts[i].skb;
+
+ pkt = &ar_sdio->rx_pkts[i];
+ memcpy(skb->data, ar_sdio->sdio_read_buf + pkt_offset,
+ pkt->alloc_len);
+ pkt->status = 0;
+ skb_put(skb, pkt->act_len);
+ pkt_offset += pkt->alloc_len;
}
return 0;
err:
/* Free all packets that was not successfully fetched. */
- for (; i < ar_sdio->n_rx_pkts; i++)
+ for (i = 0; i < ar_sdio->n_rx_pkts; i++)
ath10k_sdio_mbox_free_rx_pkt(&ar_sdio->rx_pkts[i]);
+ ar_sdio->n_rx_pkts = 0;
+
return ret;
}
@@ -695,7 +724,10 @@ static int ath10k_sdio_mbox_rxmsg_pending_handler(struct ath10k *ar,
*/
*done = false;
- ret = ath10k_sdio_mbox_rx_fetch(ar);
+ if (ar_sdio->n_rx_pkts > 1)
+ ret = ath10k_sdio_mbox_rx_fetch_bundle(ar);
+ else
+ ret = ath10k_sdio_mbox_rx_fetch(ar);
/* Process fetched packets. This will potentially update
* n_lookaheads depending on if the packets contain lookahead
@@ -2001,6 +2033,14 @@ static int ath10k_sdio_probe(struct sdio_func *func,
goto err_core_destroy;
}
+ ar_sdio->sdio_read_buf = devm_kzalloc(ar->dev,
+ ATH10K_SDIO_READ_BUF_SIZE,
+ GFP_KERNEL);
+ if (!ar_sdio->sdio_read_buf) {
+ ret = -ENOMEM;
+ goto err_core_destroy;
+ }
+
ar_sdio->func = func;
sdio_set_drvdata(func, ar_sdio);
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h b/drivers/net/wireless/ath/ath10k/sdio.h
index b8c7ac0330bd..07e2cc6a3bd8 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.h
+++ b/drivers/net/wireless/ath/ath10k/sdio.h
@@ -196,6 +196,8 @@ struct ath10k_sdio {
struct ath10k *ar;
struct ath10k_sdio_irq_data irq_data;
+ u8 *sdio_read_buf;
+
/* temporary buffer for BMI requests */
u8 *bmi_buf;
--
2.19.1
^ permalink raw reply related
* [PATCH 5/6] ath10k: sdio: add missing error check
From: Erik Stromdahl @ 2019-04-09 19:08 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <20190409190851.4557-1-erik.stromdahl@gmail.com>
Although not likely, the bundle allocation might fail.
Add proper error check and warning print.
Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
drivers/net/wireless/ath/ath10k/sdio.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 295e1e7ec3b0..3eb241cb8a25 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -586,6 +586,11 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
act_len,
&bndl_cnt);
+ if (ret) {
+ ath10k_warn(ar, "alloc_bundle error %d\n", ret);
+ goto err;
+ }
+
n_lookaheads += bndl_cnt;
i += bndl_cnt;
/*Next buffer will be the last in the bundle */
--
2.19.1
^ permalink raw reply related
* [PATCH 4/6] ath10k: sdio: add MSDU ID allocation in HTT TX path
From: Erik Stromdahl @ 2019-04-09 19:08 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Alagu Sankar, Erik Stromdahl
In-Reply-To: <20190409190851.4557-1-erik.stromdahl@gmail.com>
From: Alagu Sankar <alagusankar@silex-india.com>
This makes the SDIO HTT TX path more similar to PCIe.
Transmit completion for SDIO is similar to PCIe, via the T2H message
HTT_T2H_MSG_TYPE_TX_COMPL_IND. This means that we will create a unique
MSDU ID for each transmitted frame just as we do in the PCIe case.
As a result of this, the TX skb will be freed when we receive the
HTT_T2H_MSG_TYPE_TX_COMPL_IND message. Thus, we must not free the skb in
the HTT ep_tx_complete handler in the SDIO case.
Co-developed-by: Erik Stromdahl <erik.stromdahl@gmail.com>
Signed-off-by: Alagu Sankar <alagusankar@silex-india.com>
Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
drivers/net/wireless/ath/ath10k/htt_rx.c | 4 +++-
drivers/net/wireless/ath/ath10k/htt_tx.c | 16 ++++++++++++++--
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index a20ea270d519..6e3331b96c0f 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2277,7 +2277,9 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
- if (!kfifo_put(&htt->txdone_fifo, tx_done)) {
+ if (ar->hif.bus == ATH10K_BUS_SDIO) {
+ ath10k_txrx_tx_unref(htt, &tx_done);
+ } else if (!kfifo_put(&htt->txdone_fifo, tx_done)) {
ath10k_warn(ar, "txdone fifo overrun, msdu_id %d status %d\n",
tx_done.msdu_id, tx_done.status);
ath10k_txrx_tx_unref(htt, &tx_done);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 619c2b87b8bb..e5e6e206a52f 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -543,7 +543,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
{
- dev_kfree_skb_any(skb);
+ if (!(ar->hif.bus == ATH10K_BUS_SDIO))
+ dev_kfree_skb_any(skb);
}
void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb)
@@ -1244,6 +1245,7 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm
u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);
u8 flags0 = 0;
u16 flags1 = 0;
+ u16 msdu_id = 0;
data_len = msdu->len;
@@ -1291,6 +1293,16 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm
}
}
+ if (ar->hif.bus == ATH10K_BUS_SDIO) {
+ flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
+ res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
+ if (res < 0) {
+ ath10k_err(ar, "msdu_id allocation failed %d\n", res);
+ goto out;
+ }
+ msdu_id = res;
+ }
+
skb_push(msdu, sizeof(*cmd_hdr));
skb_push(msdu, sizeof(*tx_desc));
cmd_hdr = (struct htt_cmd_hdr *)msdu->data;
@@ -1300,7 +1312,7 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm
tx_desc->flags0 = flags0;
tx_desc->flags1 = __cpu_to_le16(flags1);
tx_desc->len = __cpu_to_le16(data_len);
- tx_desc->id = 0;
+ tx_desc->id = __cpu_to_le16(msdu_id);
tx_desc->frags_paddr = 0; /* always zero */
/* Initialize peer_id to INVALID_PEER because this is NOT
* Reinjection path
--
2.19.1
^ permalink raw reply related
* [PATCH 2/6] ath10k: high latency fixes for beacon buffer
From: Erik Stromdahl @ 2019-04-09 19:08 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Alagu Sankar
In-Reply-To: <20190409190851.4557-1-erik.stromdahl@gmail.com>
From: Alagu Sankar <alagusankar@silex-india.com>
Beacon buffer for high latency devices does not use DMA. other similar
buffer allocation methods in the driver have already been modified for
high latency path. Fix the beacon buffer allocation left out in the
earlier high latency changes.
Signed-off-by: Alagu Sankar <alagusankar@silex-india.com>
---
drivers/net/wireless/ath/ath10k/mac.c | 31 ++++++++++++++++++++-------
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index c9e700b844f8..2dd99ce44453 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -953,8 +953,12 @@ static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif)
ath10k_mac_vif_beacon_free(arvif);
if (arvif->beacon_buf) {
- dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
- arvif->beacon_buf, arvif->beacon_paddr);
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ kfree(arvif->beacon_buf);
+ else
+ dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
+ arvif->beacon_buf,
+ arvif->beacon_paddr);
arvif->beacon_buf = NULL;
}
}
@@ -5210,10 +5214,17 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_AP) {
- arvif->beacon_buf = dma_alloc_coherent(ar->dev,
- IEEE80211_MAX_FRAME_LEN,
- &arvif->beacon_paddr,
- GFP_ATOMIC);
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL) {
+ arvif->beacon_buf = kmalloc(IEEE80211_MAX_FRAME_LEN,
+ GFP_KERNEL);
+ arvif->beacon_paddr = (dma_addr_t)arvif->beacon_buf;
+ } else {
+ arvif->beacon_buf =
+ dma_alloc_coherent(ar->dev,
+ IEEE80211_MAX_FRAME_LEN,
+ &arvif->beacon_paddr,
+ GFP_ATOMIC);
+ }
if (!arvif->beacon_buf) {
ret = -ENOMEM;
ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
@@ -5424,8 +5435,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
err:
if (arvif->beacon_buf) {
- dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
- arvif->beacon_buf, arvif->beacon_paddr);
+ if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ kfree(arvif->beacon_buf);
+ else
+ dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
+ arvif->beacon_buf,
+ arvif->beacon_paddr);
arvif->beacon_buf = NULL;
}
--
2.19.1
^ permalink raw reply related
* [PATCH 1/6] ath10k: use clean packet headers
From: Erik Stromdahl @ 2019-04-09 19:08 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Alagu Sankar
In-Reply-To: <20190409190851.4557-1-erik.stromdahl@gmail.com>
From: Alagu Sankar <alagusankar@silex-india.com>
HTC header carries junk values that may be interpreted by the firmware
differently. Enable credit update only if flow control is enabled for
the corresponding endpoint.
PLL clock setting sequence does not mask the PLL_CONTROL
register value. Side effect of not masking the values is not known as
the entire pll clock setting sequence is undocumented.
Signed-off-by: Alagu Sankar <alagusankar@silex-india.com>
---
drivers/net/wireless/ath/ath10k/htc.c | 1 +
drivers/net/wireless/ath/ath10k/hw.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 805a7f8a04f2..1d4d1a1992fe 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -73,6 +73,7 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
struct ath10k_htc_hdr *hdr;
hdr = (struct ath10k_htc_hdr *)skb->data;
+ memset(hdr, 0, sizeof(struct ath10k_htc_hdr));
hdr->eid = ep->eid;
hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr));
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index ad082b7d7643..cfc232f1fdbc 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -814,6 +814,8 @@ static int ath10k_hw_qca6174_enable_pll_clock(struct ath10k *ar)
if (ret)
return -EINVAL;
+ reg_val &= ~(WLAN_PLL_CONTROL_REFDIV_MASK | WLAN_PLL_CONTROL_DIV_MASK |
+ WLAN_PLL_CONTROL_NOPWD_MASK);
reg_val |= (SM(hw_clk->refdiv, WLAN_PLL_CONTROL_REFDIV) |
SM(hw_clk->div, WLAN_PLL_CONTROL_DIV) |
SM(1, WLAN_PLL_CONTROL_NOPWD));
--
2.19.1
^ permalink raw reply related
* [PATCH 0/6] ath10k: SDIO and high latency patches from Silex
From: Erik Stromdahl @ 2019-04-09 19:08 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
This series adds a few more fixes for SDIO and high latency devices.
I have had these on my private tree for quite some time now so they
should be considered fairly well tested.
4 out of 6 patches are from Alagu Sankar at Silex.
I have made some adjustments to some of them in order to make them
smaller and easier to review.
Alagu Sankar (4):
ath10k: use clean packet headers
ath10k: high latency fixes for beacon buffer
ath10k: sdio: read RX packets in bundles
ath10k: sdio: add MSDU ID allocation in HTT TX path
Erik Stromdahl (2):
ath10k: sdio: add missing error check
ath10k: sdio: replace skb_trim with explicit set of skb->len
drivers/net/wireless/ath/ath10k/htc.c | 1 +
drivers/net/wireless/ath/ath10k/htt_rx.c | 4 +-
drivers/net/wireless/ath/ath10k/htt_tx.c | 16 ++++-
drivers/net/wireless/ath/ath10k/hw.c | 2 +
drivers/net/wireless/ath/ath10k/mac.c | 31 +++++++---
drivers/net/wireless/ath/ath10k/sdio.c | 78 +++++++++++++++++++-----
drivers/net/wireless/ath/ath10k/sdio.h | 2 +
7 files changed, 109 insertions(+), 25 deletions(-)
--
2.19.1
^ permalink raw reply
* Re: pull-request: mac80211 2019-04-09
From: David Miller @ 2019-04-09 17:57 UTC (permalink / raw)
To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <20190409114537.19171-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes@sipsolutions.net>
Date: Tue, 9 Apr 2019 13:45:36 +0200
> Here's a set of fixes for the current cycle. Mostly all over,
> but some focus from Felix on the mac80211 internal TXQs.
>
> Please pull and let me know if there's any problem.
Pulled, thanks.
^ permalink raw reply
* [PATCHv3 2/2] mac80211: Implement API to configure station specific rssi threshold
From: Tamizh chelvam @ 2019-04-09 17:38 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1554831488-27065-1-git-send-email-tamizhr@codeaurora.org>
Implement set_sta_mon_rssi_config API to configure station
specific rssi threshold value to monitor change in connected
station's signal strength. RSSI low and high threshold values
will be calculated as per the station's current signal strength,
if the configuration needs to be a fixed threshold then the user
given value will be chosen as low and high threshold.
And this patch triggers cfg80211_sta_mon_rssi_notify with the
corresponding event when station signal goes out of configured threshold.
It uses rx data signal to check against rssi threshold configured by the user.
And update the lower and upper RSSI threshold for the station if it is not
configured as a fixed threshold.
This event will be useful for the application like steering to take
decision on any station depends on its current link quality.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/mac80211.h | 7 +++
net/mac80211/cfg.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/rx.c | 56 +++++++++++++++++++++++-
net/mac80211/sta_info.c | 1 +
net/mac80211/sta_info.h | 31 ++++++++++++++
5 files changed, 202 insertions(+), 1 deletion(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d66fbfe..6893cb9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -873,6 +873,13 @@ enum mac80211_rate_control_flags {
};
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
+
/* there are 40 bytes if you don't need the rateset to be kept */
#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ba6e408..b460051 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3938,6 +3938,113 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
return drv_abort_pmsr(local, sdata, request);
}
+void sta_mon_rssi_config_free(struct sta_info *sta)
+{
+ struct sta_mon_rssi_config *old_rssi_config;
+
+ if (sta->rssi_config) {
+ old_rssi_config = sta->rssi_config;
+ RCU_INIT_POINTER(sta->rssi_config, NULL);
+ kfree_rcu(old_rssi_config, rcu_head);
+ }
+}
+
+void ieee80211_update_rssi_config(struct sta_info *sta)
+{
+ s32 last;
+ u32 hyst;
+ int i, n;
+
+ if (!sta->rssi_config || sta->rssi_config->fixed_thold)
+ return;
+
+ if (!sta->rssi_config->last_value)
+ sta->rssi_config->last_value =
+ -ewma_signal_read(&sta->rx_stats_avg.signal);
+
+ last = sta->rssi_config->last_value;
+ hyst = sta->rssi_config->hyst;
+ n = sta->rssi_config->n_thresholds;
+
+ for (i = 0; i < n; i++)
+ if (last < sta->rssi_config->thresholds[i])
+ break;
+
+ sta->rssi_config->low =
+ i > 0 ? (sta->rssi_config->thresholds[i - 1] - hyst) : S32_MIN;
+ sta->rssi_config->high =
+ i < n ? (sta->rssi_config->thresholds[i] + hyst - 1) : S32_MAX;
+}
+
+static int
+ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *mac_addr,
+ const struct cfg80211_sta_mon *sta_mon_cfg)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+ struct sta_mon_rssi_config *rssi_config;
+ struct sta_info *sta;
+ int ret = 0;
+
+ mutex_lock(&local->sta_mtx);
+ rcu_read_lock();
+
+ if (mac_addr) {
+ sta = sta_info_get_bss(sdata, mac_addr);
+ if (!sta) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ if (sta_mon_cfg->fixed_thold &&
+ sta_mon_cfg->n_tholds > 2) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ rssi_config = kzalloc(sizeof(*rssi_config) +
+ sta_mon_cfg->n_tholds * sizeof(s32),
+ GFP_KERNEL);
+ if (!rssi_config) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rssi_config->hyst = sta_mon_cfg->rssi_hyst;
+ if (sta_mon_cfg->fixed_thold) {
+ sta_mon_rssi_config_free(sta);
+ if (sta_mon_cfg->n_tholds == 1) {
+ rssi_config->low = sta_mon_cfg->rssi_tholds[0];
+ rssi_config->high = sta_mon_cfg->rssi_tholds[0];
+ } else {
+ rssi_config->low = sta_mon_cfg->rssi_tholds[0];
+ rssi_config->high = sta_mon_cfg->rssi_tholds[1];
+ }
+ rssi_config->fixed_thold = sta_mon_cfg->fixed_thold;
+ rssi_config->hyst = sta_mon_cfg->rssi_hyst;
+ rssi_config->n_thresholds = sta_mon_cfg->n_tholds;
+ sta->rssi_config = rssi_config;
+ } else {
+ sta_mon_rssi_config_free(sta);
+ rssi_config->n_thresholds = sta_mon_cfg->n_tholds;
+ memcpy(rssi_config->thresholds,
+ sta_mon_cfg->rssi_tholds,
+ rssi_config->n_thresholds * sizeof(s32));
+ rssi_config->hyst = sta_mon_cfg->rssi_hyst;
+ sta->rssi_config = rssi_config;
+ /* Calculate low and high RSSI thresholds */
+ ieee80211_update_rssi_config(sta);
+ }
+ }
+
+out:
+ rcu_read_unlock();
+ mutex_unlock(&local->sta_mtx);
+ return ret;
+}
+
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -4035,4 +4142,5 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
.get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
.start_pmsr = ieee80211_start_pmsr,
.abort_pmsr = ieee80211_abort_pmsr,
+ .set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
};
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 4a03c18..de27a6f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1732,6 +1732,57 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
return RX_CONTINUE;
}
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+ struct sta_info *sta = rx->sta;
+ struct ieee80211_bss_conf *bss_conf = &rx->sdata->vif.bss_conf;
+ bool rssi_cross = false;
+
+ if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+ NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
+ return;
+
+ if (!sta->rssi_config)
+ return;
+
+ rcu_read_lock();
+ sta->rssi_config->count_rx_signal++;
+ if (sta->rssi_config->count_rx_signal <
+ IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+ return;
+
+ if (sta->rssi_config->low && bss_conf->enable_beacon) {
+ int last_event = sta->rssi_config->last_value;
+ int sig = -ewma_signal_read(&sta->rx_stats_avg.signal);
+ int low = sta->rssi_config->low;
+ int high = sta->rssi_config->high;
+
+ if (sig < low &&
+ (last_event == 0 || last_event >= low)) {
+ sta->rssi_config->last_value = sig;
+ cfg80211_sta_mon_rssi_notify(
+ rx->sdata->dev, sta->addr,
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+ sig, GFP_ATOMIC);
+ rssi_cross = true;
+ } else if (sig > high &&
+ (last_event == 0 || last_event <= high)) {
+ sta->rssi_config->last_value = sig;
+ cfg80211_sta_mon_rssi_notify(
+ rx->sdata->dev, sta->addr,
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+ sig, GFP_ATOMIC);
+ rssi_cross = true;
+ }
+ }
+
+ if (rssi_cross) {
+ ieee80211_update_rssi_config(sta);
+ rssi_cross = false;
+ }
+ rcu_read_unlock();
+}
+
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
{
@@ -1787,6 +1838,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal);
+ ieee80211_sta_rx_signal_thold_check(rx);
}
if (status->chains) {
@@ -4219,9 +4271,11 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
/* statistics part of ieee80211_rx_h_sta_process() */
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
- if (!fast_rx->uses_rss)
+ if (!fast_rx->uses_rss) {
ewma_signal_add(&sta->rx_stats_avg.signal,
-status->signal);
+ ieee80211_sta_rx_signal_thold_check(rx);
+ }
}
if (status->chains) {
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a4932ee..ea22c2d 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1029,6 +1029,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
rate_control_remove_sta_debugfs(sta);
ieee80211_sta_debugfs_remove(sta);
+ sta_mon_rssi_config_free(sta);
cleanup_single_sta(sta);
}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 71f7e49..7f32708 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -427,6 +427,33 @@ struct ieee80211_sta_rx_stats {
u64 msdu[IEEE80211_NUM_TIDS + 1];
};
+/**
+ * struct sta_mon_rssi_config - Monitor station's signal strength
+ * @rcu_head: rcu head for freeing structure
+ * @n_rssi_tholds: Number of thresholds passed by user
+ * @low: RSSI lower threshold for this station, a zero value implies
+ * disabled
+ * @high: RSSI upper threshold for this station
+ * @hyst: RSSI hysteresis for this station
+ * @last_value: Last RSSI value for this station triggered the
+ * RSSI cross event
+ * @fixed_thold - Indicate whether to use fixed thresholds limit or not
+ * @threholds: RSSI threshold limit passed by the user
+ * @count_rx_signal: Number of data frames used in averaging station signal.
+ * This can be used to avoid generating less reliable station rssi cross
+ * events that would be based only on couple of received frames
+ */
+struct sta_mon_rssi_config {
+ struct rcu_head rcu_head;
+ int n_thresholds;
+ s32 low, high;
+ u32 hyst;
+ s32 last_value;
+ u8 fixed_thold;
+ unsigned int count_rx_signal;
+ s32 thresholds[0];
+};
+
/*
* The bandwidth threshold below which the per-station CoDel parameters will be
* scaled to be more lenient (to prevent starvation of slow stations). This
@@ -496,6 +523,7 @@ struct ieee80211_sta_rx_stats {
* @fast_rx: RX fastpath information
* @tdls_chandef: a TDLS peer can have a wider chandef that is compatible to
* the BSS one.
+ * @rssi_config: RSSI threshold config parameters for this station
* @tx_stats: TX statistics
* @tx_stats.packets: # of packets transmitted
* @tx_stats.bytes: # of bytes in all packets transmitted
@@ -623,6 +651,7 @@ struct sta_info {
struct cfg80211_chan_def tdls_chandef;
+ struct sta_mon_rssi_config *rssi_config;
/* keep last! */
struct ieee80211_sta sta;
};
@@ -760,6 +789,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
const u8 *addr);
int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
const u8 *addr);
+void sta_mon_rssi_config_free(struct sta_info *sta);
void sta_info_recalc_tim(struct sta_info *sta);
@@ -792,6 +822,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
unsigned long exp_time);
u8 sta_info_tx_streams(struct sta_info *sta);
+void ieee80211_update_rssi_config(struct sta_info *sta);
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
--
1.7.9.5
^ permalink raw reply related
* [PATCHv3 1/2] cfg80211: Add support to configure station specific RSSI threshold for AP mode
From: Tamizh chelvam @ 2019-04-09 17:38 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1554831488-27065-1-git-send-email-tamizhr@codeaurora.org>
Add infrastructure to configure station specific RSSI threshold
configuration to monitor station's signal strength variation.
This configuration will be useful for the application like
steering which requires change in the station's current signal
strength.
New NL80211_CMD_STA_MON introduced to configure the RSSI threshold
using NL80211_ATTR_CQM nested attributes. The MAC address of
a station is passed in NL80211_ATTR_MAC. And NL80211_ATTR_STA_MON_FIXED_THOLD
introduced to have this RSSI threshold as a fixed(not modifying the
low and high threshold upon crossing the threshold) or moving(modifying
low and high threshold upon crossing the threshold) thresholds.
Depends on the application's use case user can have either fixed or
moving RSSI range thresholds.
cfg80211_sta_mon_rssi_notify introduced to notify change in the
station's signal stregnth cross event using NL80211_CMD_NOTIFY_STA_MON.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG feature flag.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/cfg80211.h | 39 +++++++++
include/uapi/linux/nl80211.h | 21 +++++
net/wireless/nl80211.c | 179 ++++++++++++++++++++++++++++++++++++------
net/wireless/rdev-ops.h | 13 +++
net/wireless/trace.h | 21 +++++
5 files changed, 247 insertions(+), 26 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2ea04e9..cb8ba5a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3161,6 +3161,20 @@ struct cfg80211_update_owe_info {
};
/**
+ * struct cfg80211_sta_mon - Configure station monitor parameters
+ * @rssi_tholds - array of RSSI thresholds for the station
+ * @rssi_hyst - RSSI hysterisis
+ * @n_tholds - Number of configuration thresholds
+ * @fixed_thold - Fixed thresholds limit used for the station
+ */
+struct cfg80211_sta_mon {
+ s32 *rssi_tholds;
+ u32 rssi_hyst;
+ int n_tholds;
+ u8 fixed_thold;
+};
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -3501,6 +3515,12 @@ struct cfg80211_update_owe_info {
* @update_owe_info: Provide updated OWE info to driver. Driver implementing SME
* but offloading OWE processing to the user space will get the updated
* DH IE through this interface.
+ *
+ * @set_sta_mon_rssi_config: Configure RSSI threshold for a station.
+ * After configuration, the driver should (soon) send an event indicating
+ * the current level of a station is above/below the configured threshold;
+ * this may need some care when the configuration is changed
+ * (without first being disabled.)
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3817,6 +3837,9 @@ struct cfg80211_ops {
struct cfg80211_pmsr_request *request);
int (*update_owe_info)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_owe_info *owe_info);
+ int (*set_sta_mon_rssi_config)(struct wiphy *wiphy,
+ struct net_device *dev, const u8 *addr,
+ const struct cfg80211_sta_mon *sta_mon_cfg);
};
/*
@@ -6620,6 +6643,22 @@ bool cfg80211_rx_control_port(struct net_device *dev,
struct sk_buff *skb, bool unencrypted);
/**
+ * cfg80211_sta_mon_rssi_notify - Station's rssi out of range event
+ * @dev: network device
+ * @peer: Station's mac address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured rssi threshold reached event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+ enum nl80211_cqm_rssi_threshold_event rssi_event,
+ s32 rssi_level, gfp_t gfp);
+
+/**
* cfg80211_cqm_rssi_notify - connection quality monitoring rssi event
* @dev: network device
* @rssi_event: the triggered RSSI event
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 25f70dd..cbe5866 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1070,6 +1070,12 @@
* OWE AKM by the host drivers that implement SME but rely
* on the user space for the cryptographic/DH IE processing in AP mode.
*
+ * @NL80211_CMD_SET_STA_MON: This command is used to configure station's
+ * connection monitoring notification trigger levels. This uses nested
+ * attribute %NL80211_ATTR_CQM with %NL80211_ATTR_CQM_* sub-attributes.
+ * @NL80211_CMD_NOTIFY_STA_MON: This is used as an event to notify
+ * the user space that a trigger level was reached for a station.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1292,6 +1298,9 @@ enum nl80211_commands {
NL80211_CMD_UPDATE_OWE_INFO,
+ NL80211_CMD_SET_STA_MON,
+ NL80211_CMD_NOTIFY_STA_MON,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -2324,6 +2333,12 @@ enum nl80211_commands {
* should be picking up the lowest tx power, either tx power per-interface
* or per-station.
*
+ * @NL80211_ATTR_STA_MON_FIXED_THOLD: This u8 attribute is used with
+ * %NL80211_CMD_SET_STA_MON to indicate driver that the monitoring
+ * threshold is fixed(not modifying the low and high threshold upon
+ * crossing the threshold) or moving(modifying low and high threshold
+ * upon crossing the threshold) thresholds.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2777,6 +2792,8 @@ enum nl80211_attrs {
NL80211_ATTR_STA_TX_POWER_SETTING,
NL80211_ATTR_STA_TX_POWER,
+ NL80211_ATTR_STA_MON_FIXED_THOLD,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -5405,6 +5422,9 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power
* to a station.
*
+ * @NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG: Driver supports monitoring
+ * station's RSSI threshold value should adveritise this flag.
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -5449,6 +5469,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
NL80211_EXT_FEATURE_EXT_KEY_ID,
NL80211_EXT_FEATURE_STA_TX_PWR,
+ NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 846d25d..78657c0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -280,6 +280,17 @@ static int validate_ie_attr(const struct nlattr *attr,
NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy),
};
+static const struct nla_policy
+nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
+ [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
+ [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
+ [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
+ [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
+ [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
+ [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
+ [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
+};
+
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
@@ -395,7 +406,8 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
NL80211_PS_DISABLED,
NL80211_PS_ENABLED),
- [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
+ [NL80211_ATTR_CQM] =
+ NLA_POLICY_NESTED(nl80211_attr_cqm_policy),
[NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
[NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
[NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
@@ -546,6 +558,7 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_ATTR_PEER_MEASUREMENTS] =
NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
[NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
+ [NL80211_ATTR_STA_MON_FIXED_THOLD] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -10498,17 +10511,6 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
return err;
}
-static const struct nla_policy
-nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
- [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
- [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
- [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
- [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
- [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
- [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
- [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
-};
-
static int nl80211_set_cqm_txe(struct genl_info *info,
u32 rate, u32 pkts, u32 intvl)
{
@@ -10589,14 +10591,9 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
}
-static int nl80211_set_cqm_rssi(struct genl_info *info,
- const s32 *thresholds, int n_thresholds,
- u32 hysteresis)
+static int nl80211_validate_rssi_tholds(const s32 *thresholds, int n_thresholds)
{
- struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- int i, err;
+ int i;
s32 prev = S32_MIN;
/* Check all values negative and sorted */
@@ -10606,6 +10603,21 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
prev = thresholds[i];
}
+ return 0;
+}
+
+static int nl80211_set_cqm_rssi(struct genl_info *info,
+ const s32 *thresholds, int n_thresholds,
+ u32 hysteresis)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ err = nl80211_validate_rssi_tholds(thresholds, n_thresholds);
+ if (err)
+ return err;
if (wdev->iftype != NL80211_IFTYPE_STATION &&
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
@@ -10668,7 +10680,7 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm,
- nl80211_attr_cqm_policy, info->extack);
+ NULL, NULL);
if (err)
return err;
@@ -13405,6 +13417,78 @@ static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
return rdev_update_owe_info(rdev, dev, &owe_info);
}
+static int nl80211_set_sta_mon(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
+ struct cfg80211_sta_mon sta_mon_config = {};
+ struct nlattr *sta_mon;
+ u8 *addr = NULL;
+ int err;
+
+ if (wdev->iftype != NL80211_IFTYPE_AP &&
+ wdev->iftype != NL80211_IFTYPE_P2P_GO)
+ return -ENOTSUPP;
+
+ wdev_lock(wdev);
+ sta_mon = info->attrs[NL80211_ATTR_CQM];
+ if (!sta_mon || !info->attrs[NL80211_ATTR_MAC]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, sta_mon,
+ NULL, NULL);
+ if (err) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ sta_mon_config.fixed_thold =
+ nla_get_flag(info->attrs[NL80211_ATTR_STA_MON_FIXED_THOLD]);
+
+ if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
+ attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
+ int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
+
+ sta_mon_config.rssi_tholds =
+ nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
+ sta_mon_config.rssi_hyst =
+ nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
+
+ if (!rdev->ops->set_sta_mon_rssi_config ||
+ !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG)) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (len % 4) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ sta_mon_config.n_tholds = len / 4;
+ err = nl80211_validate_rssi_tholds(sta_mon_config.rssi_tholds,
+ sta_mon_config.n_tholds);
+ if (err) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = rdev_set_sta_mon_rssi_config(rdev, dev, addr,
+ &sta_mon_config);
+ goto out;
+ }
+
+out:
+ wdev_unlock(wdev);
+ return err;
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -14242,6 +14326,13 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_SET_STA_MON,
+ .doit = nl80211_set_sta_mon,
+ .flags = GENL_UNS_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
static struct genl_family nl80211_fam __ro_after_init = {
@@ -15443,7 +15534,8 @@ bool cfg80211_rx_control_port(struct net_device *dev,
EXPORT_SYMBOL(cfg80211_rx_control_port);
static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
- const char *mac, gfp_t gfp)
+ const char *mac, gfp_t gfp,
+ enum nl80211_commands cmd)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
@@ -15455,7 +15547,7 @@ static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
cb = (void **)msg->cb;
- cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
+ cb[0] = nl80211hdr_put(msg, 0, 0, 0, cmd);
if (!cb[0]) {
nlmsg_free(msg);
return NULL;
@@ -15517,7 +15609,7 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
rssi_level = wdev->cqm_config->last_rssi_event_value;
}
- msg = cfg80211_prepare_cqm(dev, NULL, gfp);
+ msg = cfg80211_prepare_cqm(dev, NULL, gfp, NL80211_CMD_NOTIFY_CQM);
if (!msg)
return;
@@ -15538,13 +15630,48 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
}
EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
+void
+cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+ enum nl80211_cqm_rssi_threshold_event rssi_event,
+ s32 rssi_level, gfp_t gfp)
+{
+ struct sk_buff *msg;
+
+ trace_cfg80211_sta_mon_rssi_notify(dev, peer, rssi_event, rssi_level);
+ if (WARN_ON(!peer))
+ return;
+
+ if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
+ rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
+ return;
+
+ msg = cfg80211_prepare_cqm(dev, peer, gfp, NL80211_CMD_NOTIFY_STA_MON);
+ if (!msg)
+ return;
+
+ if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
+ rssi_event))
+ goto nla_put_failure;
+
+ if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
+ rssi_level))
+ goto nla_put_failure;
+
+ cfg80211_send_cqm(msg, gfp);
+ return;
+
+ nla_put_failure:
+ nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_sta_mon_rssi_notify);
+
void cfg80211_cqm_txe_notify(struct net_device *dev,
const u8 *peer, u32 num_packets,
u32 rate, u32 intvl, gfp_t gfp)
{
struct sk_buff *msg;
- msg = cfg80211_prepare_cqm(dev, peer, gfp);
+ msg = cfg80211_prepare_cqm(dev, peer, gfp, NL80211_CMD_NOTIFY_CQM);
if (!msg)
return;
@@ -15572,7 +15699,7 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
- msg = cfg80211_prepare_cqm(dev, peer, gfp);
+ msg = cfg80211_prepare_cqm(dev, peer, gfp, NL80211_CMD_NOTIFY_CQM);
if (!msg)
return;
@@ -15591,7 +15718,7 @@ void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
{
struct sk_buff *msg;
- msg = cfg80211_prepare_cqm(dev, NULL, gfp);
+ msg = cfg80211_prepare_cqm(dev, NULL, gfp, NL80211_CMD_NOTIFY_CQM);
if (!msg)
return;
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 18437a9..8d36745 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1286,4 +1286,17 @@ static inline int rdev_update_owe_info(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int
+rdev_set_sta_mon_rssi_config(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *addr,
+ const struct cfg80211_sta_mon *sta_mon_config)
+{
+ int ret = -EOPNOTSUPP;
+
+ ret = rdev->ops->set_sta_mon_rssi_config(&rdev->wiphy, dev,
+ addr, sta_mon_config);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 488ef2ce..113cd45 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3421,6 +3421,27 @@
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
);
+TRACE_EVENT(cfg80211_sta_mon_rssi_notify,
+ TP_PROTO(struct net_device *netdev, const u8 *addr,
+ enum nl80211_cqm_rssi_threshold_event rssi_event,
+ s32 rssi_level),
+ TP_ARGS(netdev, addr, rssi_event, rssi_level),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(addr)
+ __field(enum nl80211_cqm_rssi_threshold_event, rssi_event)
+ __field(s32, rssi_level)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(addr, addr);
+ __entry->rssi_event = rssi_event;
+ __entry->rssi_level = rssi_level;
+ ),
+ TP_printk(NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
+ ", rssi event: %d, level: %d", NETDEV_PR_ARG,
+ MAC_PR_ARG(addr), __entry->rssi_event, __entry->rssi_level)
+);
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
--
1.7.9.5
^ permalink raw reply related
* [PATCHv3 0/2] cfg80211/mac80211: Add support to configure and monitor station's rssi threshold
From: Tamizh chelvam @ 2019-04-09 17:38 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Tamizh chelvam
This patchsets introduced new NL command and api to support
configuring rssi for the connected stations and api to notify
userspace application upon crossing the configured threshold.
This will be useful for the application which requires
station's current signal strength change information.
Monitoring station's signal strength through station dump command
will unnecessarily increase the system overhead. This event based
mechanism will reduce the system overhead and helps application to
take a decision for the station for which event received.
Tamizh chelvam (2):
cfg80211: Add support to configure station specific RSSI threshold
for AP mode
mac80211: Implement API to configure station specific rssi threshold
v3:
* Addressed Johannes comments
v2:
* Combined patchset 2 and 3 as single patch and addressed Johannes comments.
include/net/cfg80211.h | 39 +++++++++
include/net/mac80211.h | 7 ++
include/uapi/linux/nl80211.h | 21 +++++
net/mac80211/cfg.c | 108 +++++++++++++++++++++++++
net/mac80211/rx.c | 56 ++++++++++++-
net/mac80211/sta_info.c | 1 +
net/mac80211/sta_info.h | 31 ++++++++
net/wireless/nl80211.c | 179 ++++++++++++++++++++++++++++++++++++------
net/wireless/rdev-ops.h | 13 +++
net/wireless/trace.h | 21 +++++
10 files changed, 449 insertions(+), 27 deletions(-)
--
1.7.9.5
^ permalink raw reply
* Re: [PATCH] NFC: st21nfca: Fix a couple of fall-through warnings
From: Kees Cook @ 2019-04-09 16:30 UTC (permalink / raw)
To: Gustavo A. R. Silva; +Cc: Samuel Ortiz, linux-wireless, LKML
In-Reply-To: <20190212173902.GA6829@embeddedor>
On Tue, Feb 12, 2019 at 9:39 AM Gustavo A. R. Silva
<gustavo@embeddedor.com> wrote:
>
> In preparation to enabling -Wimplicit-fallthrough, mark switch
> cases where we are expecting to fall through.
>
> This patch fixes the following warnings by adding a missing break
> and a fall-through annotation:
>
> drivers/nfc/st21nfca/dep.c: In function ‘st21nfca_tm_event_send_data’:
> drivers/nfc/st21nfca/dep.c:391:3: warning: this statement may fall through [-Wimplicit-fallthrough=]
> switch (cmd1) {
> ^~~~~~
> drivers/nfc/st21nfca/dep.c:404:2: note: here
> default:
> ^~~~~~~
> In file included from ./include/linux/kernel.h:15,
> from ./include/linux/skbuff.h:17,
> from ./include/net/nfc/hci.h:21,
> from drivers/nfc/st21nfca/dep.c:17:
> drivers/nfc/st21nfca/dep.c: In function ‘st21nfca_im_recv_dep_res_cb’:
> ./include/linux/printk.h:303:2: warning: this statement may fall through [-Wimplicit-fallthrough=]
> printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/nfc/st21nfca/dep.c:622:4: note: in expansion of macro ‘pr_err’
> pr_err("Received a ACK/NACK PDU\n");
> ^~~~~~
> drivers/nfc/st21nfca/dep.c:623:3: note: here
> case ST21NFCA_NFC_DEP_PFB_I_PDU:
> ^~~~
>
> Warning level 3 was used: -Wimplicit-fallthrough=3
>
> This patch is part of the ongoing efforts to enable
> -Wimplicit-fallthrough.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
--
Kees Cook
^ permalink raw reply
* Re: [PATCH] NFC: pn533: mark expected switch fall-throughs
From: Kees Cook @ 2019-04-09 16:29 UTC (permalink / raw)
To: Gustavo A. R. Silva; +Cc: Samuel Ortiz, linux-wireless, LKML
In-Reply-To: <20190213185741.GA5047@embeddedor>
On Wed, Feb 13, 2019 at 10:57 AM Gustavo A. R. Silva
<gustavo@embeddedor.com> wrote:
>
> In preparation to enabling -Wimplicit-fallthrough, mark switch
> cases where we are expecting to fall through.
>
> This patch fixes the following warnings:
>
> drivers/nfc/pn533/pn533.c: In function ‘pn533_transceive’:
> drivers/nfc/pn533/pn533.c:2142:6: warning: this statement may fall through [-Wimplicit-fallthrough=]
> if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
> ^
> drivers/nfc/pn533/pn533.c:2150:2: note: here
> default:
> ^~~~~~~
> drivers/nfc/pn533/pn533.c: In function ‘pn533_wq_mi_recv’:
> drivers/nfc/pn533/pn533.c:2267:6: warning: this statement may fall through [-Wimplicit-fallthrough=]
> if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
> ^
> drivers/nfc/pn533/pn533.c:2276:2: note: here
> default:
> ^~~~~~~
>
> Warning level 3 was used: -Wimplicit-fallthrough=3
>
> This patch is part of the ongoing efforts to enable
> -Wimplicit-fallthrough.
>
> Addresses-Coverity-ID: 1230487 ("Missing break in switch")
> Addresses-Coverity-ID: 1230488 ("Missing break in switch")
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
--
Kees Cook
^ permalink raw reply
* Re: [PATCH 15/21] rt2x00: rt2800lib: hardcode txmixer gain values to zero for RT3883
From: Tom Psyborg @ 2019-04-09 15:26 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: linux-wireless, Daniel Golle, Felix Fietkau, Mathias Kresin,
Gabor Juhos
In-Reply-To: <1554809828-13500-16-git-send-email-sgruszka@redhat.com>
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?
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox