* Re: [PATCH v1 net-next] net: stmmac: enable clause 45 mdio support
From: Andrew Lunn @ 2019-07-05 4:52 UTC (permalink / raw)
To: Voon, Weifeng
Cc: David S. Miller, Maxime Coquelin, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, Jose Abreu, Giuseppe Cavallaro,
Florian Fainelli, Alexandre Torgue, biao huang, Ong, Boon Leong,
Kweh, Hock Leong
In-Reply-To: <D6759987A7968C4889FDA6FA91D5CBC814738B36@PGSMSX103.gar.corp.intel.com>
> If the community prefers readability
Readability nearly always comes first. There is nothing performance
critical here, MDIO is a slow bus. So the code should be readable,
simple to understand.
, I will suggest to do the c45 setup in
> both stmmac_mdio_read() and stmmac_mdio_write() 's if(C45) condition rather
> than splitting into 2 new c45_read() and c45_write() functions.
Fine.
Andrew
^ permalink raw reply
* Re: [PATCH bpf-next] tools: bpftool: add "prog run" subcommand to test-run programs
From: Y Song @ 2019-07-05 5:49 UTC (permalink / raw)
To: Quentin Monnet
Cc: Alexei Starovoitov, Daniel Borkmann, bpf, netdev, oss-drivers
In-Reply-To: <20190704085646.12406-1-quentin.monnet@netronome.com>
On Thu, Jul 4, 2019 at 1:58 AM Quentin Monnet
<quentin.monnet@netronome.com> wrote:
>
> Add a new "bpftool prog run" subcommand to run a loaded program on input
> data (and possibly with input context) passed by the user.
>
> Print output data (and output context if relevant) into a file or into
> the console. Print return value and duration for the test run into the
> console.
>
> A "repeat" argument can be passed to run the program several times in a
> row.
>
> The command does not perform any kind of verification based on program
> type (Is this program type allowed to use an input context?) or on data
> consistency (Can I work with empty input data?), this is left to the
> kernel.
>
> Example invocation:
>
> # perl -e 'print "\x0" x 14' | ./bpftool prog run \
> pinned /sys/fs/bpf/sample_ret0 \
> data_in - data_out - repeat 5
> 0000000 0000 0000 0000 0000 0000 0000 0000 | ........ ......
> Return value: 0, duration (average): 260ns
>
> When one of data_in or ctx_in is "-", bpftool reads from standard input,
> in binary format. Other formats (JSON, hexdump) might be supported (via
> an optional command line keyword like "data_fmt_in") in the future if
> relevant, but this would require doing more parsing in bpftool.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> ---
> .../bpftool/Documentation/bpftool-prog.rst | 34 ++
> tools/bpf/bpftool/bash-completion/bpftool | 28 +-
> tools/bpf/bpftool/main.c | 29 ++
> tools/bpf/bpftool/main.h | 1 +
> tools/bpf/bpftool/prog.c | 348 +++++++++++++++++-
> tools/include/linux/sizes.h | 48 +++
> 6 files changed, 485 insertions(+), 3 deletions(-)
> create mode 100644 tools/include/linux/sizes.h
>
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> index 1df637f85f94..7a374b3c851d 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> @@ -29,6 +29,7 @@ PROG COMMANDS
> | **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*]
> | **bpftool** **prog detach** *PROG* *ATTACH_TYPE* [*MAP*]
> | **bpftool** **prog tracelog**
> +| **bpftool** **prog run** *PROG* **data_in** *FILE* [**data_out** *FILE* [**data_size_out** *L*]] [**ctx_in** *FILE* [**ctx_out** *FILE* [**ctx_size_out** *M*]]] [**repeat** *N*]
> | **bpftool** **prog help**
> |
> | *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
> @@ -146,6 +147,39 @@ DESCRIPTION
> streaming data from BPF programs to user space, one can use
> perf events (see also **bpftool-map**\ (8)).
>
> + **bpftool prog run** *PROG* **data_in** *FILE* [**data_out** *FILE* [**data_size_out** *L*]] [**ctx_in** *FILE* [**ctx_out** *FILE* [**ctx_size_out** *M*]]] [**repeat** *N*]
> + Run BPF program *PROG* in the kernel testing infrastructure
> + for BPF, meaning that the program works on the data and
> + context provided by the user, and not on actual packets or
> + monitored functions etc. Return value and duration for the
> + test run are printed out to the console.
> +
> + Input data is read from the *FILE* passed with **data_in**.
> + If this *FILE* is "**-**", input data is read from standard
> + input. Input context, if any, is read from *FILE* passed with
> + **ctx_in**. Again, "**-**" can be used to read from standard
> + input, but only if standard input is not already in use for
> + input data. If a *FILE* is passed with **data_out**, output
> + data is written to that file. Similarly, output context is
> + written to the *FILE* passed with **ctx_out**. For both
> + output flows, "**-**" can be used to print to the standard
> + output (as plain text, or JSON if relevant option was
> + passed). If output keywords are omitted, output data and
> + context are discarded. Keywords **data_size_out** and
> + **ctx_size_out** are used to pass the size (in bytes) for the
> + output buffers to the kernel, although the default of 32 kB
> + should be more than enough for most cases.
> +
> + Keyword **repeat** is used to indicate the number of
> + consecutive runs to perform. Note that output data and
> + context printed to files correspond to the last of those
> + runs. The duration printed out at the end of the runs is an
> + average over all runs performed by the command.
> +
> + Not all program types support test run. Among those which do,
> + not all of them can take the **ctx_in**/**ctx_out**
> + arguments. bpftool does not perform checks on program types.
> +
> **bpftool prog help**
> Print short help message.
>
> diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
> index ba37095e1f62..965a8658cca3 100644
> --- a/tools/bpf/bpftool/bash-completion/bpftool
> +++ b/tools/bpf/bpftool/bash-completion/bpftool
> @@ -408,10 +408,34 @@ _bpftool()
> tracelog)
> return 0
> ;;
> + run)
> + if [[ ${#words[@]} -lt 5 ]]; then
> + _filedir
> + return 0
> + fi
> + case $prev in
> + id)
> + _bpftool_get_prog_ids
> + return 0
> + ;;
> + data_in|data_out|ctx_in|ctx_out)
> + _filedir
> + return 0
> + ;;
> + repeat|data_size_out|ctx_size_out)
> + return 0
> + ;;
> + *)
> + _bpftool_once_attr 'data_in data_out data_size_out \
> + ctx_in ctx_out ctx_size_out repeat'
> + return 0
> + ;;
> + esac
> + ;;
> *)
> [[ $prev == $object ]] && \
> - COMPREPLY=( $( compgen -W 'dump help pin attach detach load \
> - show list tracelog' -- "$cur" ) )
> + COMPREPLY=( $( compgen -W 'dump help pin attach detach \
> + load show list tracelog run' -- "$cur" ) )
> ;;
> esac
> ;;
> diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
> index 4879f6395c7e..e916ff25697f 100644
> --- a/tools/bpf/bpftool/main.c
> +++ b/tools/bpf/bpftool/main.c
> @@ -117,6 +117,35 @@ bool is_prefix(const char *pfx, const char *str)
> return !memcmp(str, pfx, strlen(pfx));
> }
>
> +/* Last argument MUST be NULL pointer */
> +int detect_common_prefix(const char *arg, ...)
> +{
> + unsigned int count = 0;
> + const char *ref;
> + char msg[256];
> + va_list ap;
> +
> + snprintf(msg, sizeof(msg), "ambiguous prefix: '%s' could be '", arg);
> + va_start(ap, arg);
> + while ((ref = va_arg(ap, const char *))) {
> + if (!is_prefix(arg, ref))
> + continue;
> + count++;
> + if (count > 1)
> + strncat(msg, "' or '", sizeof(msg) - strlen(msg) - 1);
> + strncat(msg, ref, sizeof(msg) - strlen(msg) - 1);
> + }
> + va_end(ap);
> + strncat(msg, "'", sizeof(msg) - strlen(msg) - 1);
> +
> + if (count >= 2) {
> + p_err(msg);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
> {
> unsigned char *data = arg;
> diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
> index 9c5d9c80f71e..3ef0d9051e10 100644
> --- a/tools/bpf/bpftool/main.h
> +++ b/tools/bpf/bpftool/main.h
> @@ -101,6 +101,7 @@ void p_err(const char *fmt, ...);
> void p_info(const char *fmt, ...);
>
> bool is_prefix(const char *pfx, const char *str);
> +int detect_common_prefix(const char *arg, ...);
> void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep);
> void usage(void) __noreturn;
>
> diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
> index 9b0db5d14e31..8dcbaa0a8ab1 100644
> --- a/tools/bpf/bpftool/prog.c
> +++ b/tools/bpf/bpftool/prog.c
> @@ -15,6 +15,7 @@
> #include <sys/stat.h>
>
> #include <linux/err.h>
> +#include <linux/sizes.h>
>
> #include <bpf.h>
> #include <btf.h>
> @@ -748,6 +749,344 @@ static int do_detach(int argc, char **argv)
> return 0;
> }
>
> +static int check_single_stdin(char *file_in, char *other_file_in)
> +{
> + if (file_in && other_file_in &&
> + !strcmp(file_in, "-") && !strcmp(other_file_in, "-")) {
> + p_err("cannot use standard input for both data_in and ctx_in");
The error message says data_in and ctx_in.
Maybe the input parameter should be file_data_in and file_ctx_in?
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int get_run_data(const char *fname, void **data_ptr, unsigned int *size)
> +{
> + size_t block_size = 256;
> + size_t buf_size = block_size;
> + size_t nb_read = 0;
> + void *tmp;
> + FILE *f;
> +
> + if (!fname) {
> + *data_ptr = NULL;
> + *size = 0;
> + return 0;
> + }
> +
> + if (!strcmp(fname, "-"))
> + f = stdin;
> + else
> + f = fopen(fname, "r");
> + if (!f) {
> + p_err("failed to open %s: %s", fname, strerror(errno));
> + return -1;
> + }
> +
> + *data_ptr = malloc(block_size);
> + if (!*data_ptr) {
> + p_err("failed to allocate memory for data_in/ctx_in: %s",
> + strerror(errno));
> + goto err_fclose;
> + }
> +
> + while ((nb_read += fread(*data_ptr + nb_read, 1, block_size, f))) {
> + if (feof(f))
> + break;
> + if (ferror(f)) {
> + p_err("failed to read data_in/ctx_in from %s: %s",
> + fname, strerror(errno));
> + goto err_free;
> + }
> + if (nb_read > buf_size - block_size) {
> + if (buf_size == UINT32_MAX) {
> + p_err("data_in/ctx_in is too long (max: %d)",
> + UINT32_MAX);
> + goto err_free;
> + }
> + /* No space for fread()-ing next chunk; realloc() */
> + buf_size *= 2;
> + tmp = realloc(*data_ptr, buf_size);
> + if (!tmp) {
> + p_err("failed to reallocate data_in/ctx_in: %s",
> + strerror(errno));
> + goto err_free;
> + }
> + *data_ptr = tmp;
> + }
> + }
> + if (f != stdin)
> + fclose(f);
> +
> + *size = nb_read;
> + return 0;
> +
> +err_free:
> + free(*data_ptr);
> + *data_ptr = NULL;
> +err_fclose:
> + if (f != stdin)
> + fclose(f);
> + return -1;
> +}
> +
> +static void hex_print(void *data, unsigned int size, FILE *f)
> +{
> + size_t i, j;
> + char c;
> +
> + for (i = 0; i < size; i += 16) {
> + /* Row offset */
> + fprintf(f, "%07zx\t", i);
> +
> + /* Hexadecimal values */
> + for (j = i; j < i + 16 && j < size; j++)
> + fprintf(f, "%02x%s", *(uint8_t *)(data + j),
> + j % 2 ? " " : "");
> + for (; j < i + 16; j++)
> + fprintf(f, " %s", j % 2 ? " " : "");
> +
> + /* ASCII values (if relevant), '.' otherwise */
> + fprintf(f, "| ");
> + for (j = i; j < i + 16 && j < size; j++) {
> + c = *(char *)(data + j);
> + if (c < ' ' || c > '~')
> + c = '.';
> + fprintf(f, "%c%s", c, j == i + 7 ? " " : "");
> + }
> +
> + fprintf(f, "\n");
> + }
> +}
> +
> +static int
> +print_run_output(void *data, unsigned int size, const char *fname,
> + const char *json_key)
> +{
> + size_t nb_written;
> + FILE *f;
> +
> + if (!fname)
> + return 0;
> +
> + if (!strcmp(fname, "-")) {
> + f = stdout;
> + if (json_output) {
> + jsonw_name(json_wtr, json_key);
> + print_data_json(data, size);
> + } else {
> + hex_print(data, size, f);
> + }
> + return 0;
> + }
> +
> + f = fopen(fname, "w");
> + if (!f) {
> + p_err("failed to open %s: %s", fname, strerror(errno));
> + return -1;
> + }
> +
> + nb_written = fwrite(data, 1, size, f);
> + fclose(f);
> + if (nb_written != size) {
> + p_err("failed to write output data/ctx: %s", strerror(errno));
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int alloc_run_data(void **data_ptr, unsigned int size_out)
> +{
> + *data_ptr = calloc(size_out, 1);
> + if (!*data_ptr) {
> + p_err("failed to allocate memory for output data/ctx: %s",
> + strerror(errno));
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int do_run(int argc, char **argv)
> +{
> + char *data_fname_in = NULL, *data_fname_out = NULL;
> + char *ctx_fname_in = NULL, *ctx_fname_out = NULL;
> + struct bpf_prog_test_run_attr test_attr = {0};
> + const unsigned int default_size = SZ_32K;
> + void *data_in = NULL, *data_out = NULL;
> + void *ctx_in = NULL, *ctx_out = NULL;
> + unsigned int repeat = 1;
> + int fd, err;
> +
> + if (!REQ_ARGS(4))
> + return -1;
> +
> + fd = prog_parse_fd(&argc, &argv);
> + if (fd < 0)
> + return -1;
> +
> + while (argc) {
> + if (detect_common_prefix(*argv, "data_in", "data_out",
> + "data_size_out", NULL))
> + return -1;
> + if (detect_common_prefix(*argv, "ctx_in", "ctx_out",
> + "ctx_size_out", NULL))
> + return -1;
> +
> + if (is_prefix(*argv, "data_in")) {
> + NEXT_ARG();
> + if (!REQ_ARGS(1))
> + return -1;
> +
> + data_fname_in = GET_ARG();
> + if (check_single_stdin(data_fname_in, ctx_fname_in))
> + return -1;
> + } else if (is_prefix(*argv, "data_out")) {
Here, we all use is_prefix() to match "data_in", "data_out",
"data_size_out" etc.
That means users can use "data_i" instead of "data_in" as below
... | ./bpftool prog run id 283 data_i - data_out - repeat 5
is this expected?
> + NEXT_ARG();
> + if (!REQ_ARGS(1))
> + return -1;
> +
> + data_fname_out = GET_ARG();
> + } else if (is_prefix(*argv, "data_size_out")) {
> + char *endptr;
> +
> + NEXT_ARG();
> + if (!REQ_ARGS(1))
> + return -1;
> +
> + test_attr.data_size_out = strtoul(*argv, &endptr, 0);
> + if (*endptr) {
> + p_err("can't parse %s as output data size",
> + *argv);
> + return -1;
> + }
> + NEXT_ARG();
> + } else if (is_prefix(*argv, "ctx_in")) {
> + NEXT_ARG();
> + if (!REQ_ARGS(1))
> + return -1;
> +
> + ctx_fname_in = GET_ARG();
> + if (check_single_stdin(ctx_fname_in, data_fname_in))
> + return -1;
> + } else if (is_prefix(*argv, "ctx_out")) {
> + NEXT_ARG();
> + if (!REQ_ARGS(1))
> + return -1;
> +
> + ctx_fname_out = GET_ARG();
> + } else if (is_prefix(*argv, "ctx_size_out")) {
> + char *endptr;
> +
> + NEXT_ARG();
> + if (!REQ_ARGS(1))
> + return -1;
> +
> + test_attr.ctx_size_out = strtoul(*argv, &endptr, 0);
> + if (*endptr) {
> + p_err("can't parse %s as output context size",
> + *argv);
> + return -1;
> + }
> + NEXT_ARG();
> + } else if (is_prefix(*argv, "repeat")) {
> + char *endptr;
> +
> + NEXT_ARG();
> + if (!REQ_ARGS(1))
> + return -1;
> +
> + repeat = strtoul(*argv, &endptr, 0);
> + if (*endptr) {
> + p_err("can't parse %s as repeat number",
> + *argv);
> + return -1;
> + }
> + NEXT_ARG();
> + } else {
> + p_err("expected no more arguments, 'data_in', 'data_out', 'data_size_out', 'ctx_in', 'ctx_out', 'ctx_size_out' or 'repeat', got: '%s'?",
> + *argv);
> + return -1;
> + }
> + }
> +
[...]
^ permalink raw reply
* RE: [PATCH v2] let proc net directory inodes reflect to active net namespace
From: Hallsmark, Per @ 2019-07-05 6:02 UTC (permalink / raw)
To: Alexey Dobriyan
Cc: David S. Miller, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <20190704073200.GA2165@avx2>
Hello Alexey,
Sounds excellent! Could you please drop a notifier of such?
For our usecase, the ipv6 is statically linked (=y) and then this happens way before
userland starts (thus no access to procfs) so I believe we should be able to continue
as is until we can replace with your proper patch. Agree?
Also still wonder about the others that creates directories in procfs net, that do not
call proc_net_mkdir().
My second patch changed to use proc_net_mkdir for dev_snmp6 directory, so if proc_net_mkdir is fixed
it should cover at least the ipv6 snmp counters. But I think there's other that could benefit of same?
Like :
net/netfilter/xt_hashlimit.c: hashlimit_net->ipt_hashlimit = proc_mkdir("ipt_hashlimit", net->proc_net);
net/netfilter/xt_hashlimit.c: hashlimit_net->ip6t_hashlimit = proc_mkdir("ip6t_hashlimit", net->proc_net);
Wouldn't those also want to be reflected by a net namespace change?
Just an example, there are others too.
BR,
Per
--
Per Hallsmark per.hallsmark@windriver.com
Senior Member Technical Staff Wind River AB
Mobile: +46733249340 Office: +46859461127
Torshamnsgatan 27 164 40 Kista
________________________________________
From: Alexey Dobriyan [adobriyan@gmail.com]
Sent: Thursday, July 04, 2019 09:32
To: Hallsmark, Per
Cc: David S. Miller; linux-kernel@vger.kernel.org; netdev@vger.kernel.org
Subject: Re: [PATCH v2] let proc net directory inodes reflect to active net namespace
On Mon, Jul 01, 2019 at 11:06:34AM +0000, Hallsmark, Per wrote:
> +struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
> + struct proc_dir_entry *parent)
> +{
> + struct proc_dir_entry *pde;
> +
> + pde = proc_mkdir_data(name, 0, parent, net);
> + if (!pde)
> + return NULL;
> + pde->proc_dops = &proc_net_dentry_ops;
OK, this is buggy in a different way:
once proc_mkdir_data() returns, proc entry is live and should be fully
ready, so dentry operations should be glued before that.
I'll send proper patch.
^ permalink raw reply
* [PATCH] net: hisilicon: Add an tx_desc to adapt HI13X1_GMAC
From: Jiangfeng Xiao @ 2019-07-05 6:10 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
HI13X1 changed the offsets and bitmaps for tx_desc
registers in the same peripheral device on different
models of the hip04_eth.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 34 +++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 780fc46..6256357 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -76,8 +76,15 @@
/* TX descriptor config */
#define TX_FREE_MEM BIT(0)
#define TX_READ_ALLOC_L3 BIT(1)
-#define TX_FINISH_CACHE_INV BIT(2)
+#if defined(CONFIG_HI13X1_GMAC)
+#define TX_CLEAR_WB BIT(7)
+#define TX_RELEASE_TO_PPE BIT(4)
+#define TX_FINISH_CACHE_INV BIT(6)
+#define TX_POOL_SHIFT 16
+#else
#define TX_CLEAR_WB BIT(4)
+#define TX_FINISH_CACHE_INV BIT(2)
+#endif
#define TX_L3_CHECKSUM BIT(5)
#define TX_LOOP_BACK BIT(11)
@@ -124,6 +131,7 @@
/* buf unit size is cache_line_size, which is 64, so the shift is 6 */
#define PPE_BUF_SIZE_SHIFT 6
#define PPE_TX_BUF_HOLD BIT(31)
+#define CACHE_LINE_MASK 0x3F
#else
#define PPE_CFG_QOS_VMID_GRP_SHIFT 8
#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 11
@@ -163,11 +171,22 @@
#define HIP04_MIN_TX_COALESCE_FRAMES 100
struct tx_desc {
+#if defined(CONFIG_HI13X1_GMAC)
+ u32 reserved1[2];
+ u32 send_addr;
+ u16 send_size;
+ u16 data_offset;
+ u32 reserved2[7];
+ u32 cfg;
+ u32 wb_addr;
+ u32 reserved3[3];
+#else
u32 send_addr;
u32 send_size;
u32 next_addr;
u32 cfg;
u32 wb_addr;
+#endif
} __aligned(64);
struct rx_desc {
@@ -505,11 +524,20 @@ static void hip04_start_tx_timer(struct hip04_priv *priv)
priv->tx_skb[tx_head] = skb;
priv->tx_phys[tx_head] = phys;
- desc->send_addr = (__force u32)cpu_to_be32(phys);
+
desc->send_size = (__force u32)cpu_to_be32(skb->len);
+#if defined(CONFIG_HI13X1_GMAC)
+ desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV
+ | TX_RELEASE_TO_PPE | priv->port << TX_POOL_SHIFT);
+ desc->data_offset = (__force u32)cpu_to_be32(phys & CACHE_LINE_MASK);
+ desc->send_addr = (__force u32)cpu_to_be32(phys & ~CACHE_LINE_MASK);
+#else
desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV);
+ desc->send_addr = (__force u32)cpu_to_be32(phys);
+#endif
phys = priv->tx_desc_dma + tx_head * sizeof(struct tx_desc);
- desc->wb_addr = (__force u32)cpu_to_be32(phys);
+ desc->wb_addr = (__force u32)cpu_to_be32(phys +
+ offsetof(struct tx_desc, send_addr));
skb_tx_timestamp(skb);
hip04_set_xmit_desc(priv, phys);
--
1.8.5.6
^ permalink raw reply related
* [PATCH 01/10] net: hisilicon: Add support for HI13X1 to hip04_eth
From: Jiangfeng Xiao @ 2019-07-05 6:10 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
Extend the hip04_eth driver to support HI13X1_GMAC.
Enable it with CONFIG_HI13X1_GMAC option.
HI13X1 changed the offsets and bitmaps for registers
in the same peripheral device on different models of
the hip04_eth.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/Kconfig | 10 ++++++++
drivers/net/ethernet/hisilicon/hip04_eth.c | 37 ++++++++++++++++++++++++------
2 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index a0d780c..3892a20 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -46,6 +46,16 @@ config HIP04_ETH
If you wish to compile a kernel for a hardware with hisilicon p04 SoC and
want to use the internal ethernet then you should answer Y to this.
+config HI13X1_GMAC
+ bool "Hisilicon HI13X1 Network Device Support"
+ depends on HIP04_ETH
+ help
+ If you wish to compile a kernel for a hardware with hisilicon hi13x1_gamc
+ then you should answer Y to this. This makes this driver suitable for use
+ on certain boards such as the HI13X1.
+
+ If you are unsure, say N.
+
config HNS_MDIO
tristate
select PHYLIB
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index e1f2978..2b5112b 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -33,10 +33,23 @@
#define GE_MODE_CHANGE_REG 0x1b4
#define GE_RECV_CONTROL_REG 0x1e0
#define GE_STATION_MAC_ADDRESS 0x210
-#define PPE_CFG_CPU_ADD_ADDR 0x580
-#define PPE_CFG_MAX_FRAME_LEN_REG 0x408
+
#define PPE_CFG_BUS_CTRL_REG 0x424
#define PPE_CFG_RX_CTRL_REG 0x428
+
+#if defined(CONFIG_HI13X1_GMAC)
+#define PPE_CFG_CPU_ADD_ADDR 0x6D0
+#define PPE_CFG_MAX_FRAME_LEN_REG 0x500
+#define PPE_CFG_RX_PKT_MODE_REG 0x504
+#define PPE_CFG_QOS_VMID_GEN 0x520
+#define PPE_CFG_RX_PKT_INT 0x740
+#define PPE_INTEN 0x700
+#define PPE_INTSTS 0x708
+#define PPE_RINT 0x704
+#define PPE_CFG_STS_MODE 0x880
+#else
+#define PPE_CFG_CPU_ADD_ADDR 0x580
+#define PPE_CFG_MAX_FRAME_LEN_REG 0x408
#define PPE_CFG_RX_PKT_MODE_REG 0x438
#define PPE_CFG_QOS_VMID_GEN 0x500
#define PPE_CFG_RX_PKT_INT 0x538
@@ -44,6 +57,8 @@
#define PPE_INTSTS 0x608
#define PPE_RINT 0x604
#define PPE_CFG_STS_MODE 0x700
+#endif /* CONFIG_HI13X1_GMAC */
+
#define PPE_HIS_RX_PKT_CNT 0x804
/* REG_INTERRUPT */
@@ -93,18 +108,26 @@
#define GE_RX_PORT_EN BIT(1)
#define GE_TX_PORT_EN BIT(2)
-#define PPE_CFG_STS_RX_PKT_CNT_RC BIT(12)
-
#define PPE_CFG_RX_PKT_ALIGN BIT(18)
-#define PPE_CFG_QOS_VMID_MODE BIT(14)
+
+#if defined(CONFIG_HI13X1_GMAC)
+#define PPE_CFG_QOS_VMID_GRP_SHIFT 4
+#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 7
+#define PPE_CFG_STS_RX_PKT_CNT_RC BIT(0)
+#define PPE_CFG_QOS_VMID_MODE BIT(15)
+#define PPE_CFG_BUS_LOCAL_REL (BIT(9) | BIT(15) | BIT(19) | BIT(23))
+#else
#define PPE_CFG_QOS_VMID_GRP_SHIFT 8
+#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 11
+#define PPE_CFG_STS_RX_PKT_CNT_RC BIT(12)
+#define PPE_CFG_QOS_VMID_MODE BIT(14)
+#define PPE_CFG_BUS_LOCAL_REL BIT(14)
+#endif /* CONFIG_HI13X1_GMAC */
#define PPE_CFG_RX_FIFO_FSFU BIT(11)
#define PPE_CFG_RX_DEPTH_SHIFT 16
#define PPE_CFG_RX_START_SHIFT 0
-#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 11
-#define PPE_CFG_BUS_LOCAL_REL BIT(14)
#define PPE_CFG_BUS_BIG_ENDIEN BIT(0)
#define RX_DESC_NUM 128
--
1.8.5.6
^ permalink raw reply related
* [PATCH 02/10] net: hisilicon: Cleanup for got restricted __be32
From: Jiangfeng Xiao @ 2019-07-05 6:10 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
This patch fixes the following warning from sparse:
hip04_eth.c:468:25: warning: incorrect type in assignment
hip04_eth.c:468:25: expected unsigned int [usertype] send_addr
hip04_eth.c:468:25: got restricted __be32 [usertype]
hip04_eth.c:469:25: warning: incorrect type in assignment
hip04_eth.c:469:25: expected unsigned int [usertype] send_size
hip04_eth.c:469:25: got restricted __be32 [usertype]
hip04_eth.c:470:19: warning: incorrect type in assignment
hip04_eth.c:470:19: expected unsigned int [usertype] cfg
hip04_eth.c:470:19: got restricted __be32 [usertype]
hip04_eth.c:472:23: warning: incorrect type in assignment
hip04_eth.c:472:23: expected unsigned int [usertype] wb_addr
hip04_eth.c:472:23: got restricted __be32 [usertype]
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 2b5112b..31f13cf 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -465,11 +465,11 @@ static void hip04_start_tx_timer(struct hip04_priv *priv)
priv->tx_skb[tx_head] = skb;
priv->tx_phys[tx_head] = phys;
- desc->send_addr = cpu_to_be32(phys);
- desc->send_size = cpu_to_be32(skb->len);
- desc->cfg = cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV);
+ desc->send_addr = (__force u32)cpu_to_be32(phys);
+ desc->send_size = (__force u32)cpu_to_be32(skb->len);
+ desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV);
phys = priv->tx_desc_dma + tx_head * sizeof(struct tx_desc);
- desc->wb_addr = cpu_to_be32(phys);
+ desc->wb_addr = (__force u32)cpu_to_be32(phys);
skb_tx_timestamp(skb);
hip04_set_xmit_desc(priv, phys);
--
1.8.5.6
^ permalink raw reply related
* [PATCH 03/10] net: hisilicon: Cleanup for cast to restricted __be32
From: Jiangfeng Xiao @ 2019-07-05 6:10 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
This patch fixes the following warning from sparse:
hip04_eth.c:533:23: warning: cast to restricted __be16
hip04_eth.c:533:23: warning: cast to restricted __be16
hip04_eth.c:533:23: warning: cast to restricted __be16
hip04_eth.c:533:23: warning: cast to restricted __be16
hip04_eth.c:534:23: warning: cast to restricted __be32
hip04_eth.c:534:23: warning: cast to restricted __be32
hip04_eth.c:534:23: warning: cast to restricted __be32
hip04_eth.c:534:23: warning: cast to restricted __be32
hip04_eth.c:534:23: warning: cast to restricted __be32
hip04_eth.c:534:23: warning: cast to restricted __be32
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 31f13cf..d8f0619 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -530,8 +530,8 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
priv->rx_phys[priv->rx_head] = 0;
desc = (struct rx_desc *)skb->data;
- len = be16_to_cpu(desc->pkt_len);
- err = be32_to_cpu(desc->pkt_err);
+ len = be16_to_cpu((__force __be16)desc->pkt_len);
+ err = be32_to_cpu((__force __be32)desc->pkt_err);
if (0 == len) {
dev_kfree_skb_any(skb);
--
1.8.5.6
^ permalink raw reply related
* [PATCH 1/2] forcedeth: add recv cache make nic work steadily
From: Zhu Yanjun @ 2019-07-05 6:19 UTC (permalink / raw)
To: yanjun.zhu, netdev, davem
In-Reply-To: <1562307568-21549-1-git-send-email-yanjun.zhu@oracle.com>
A recv cache is added. The size of recv cache is 1000Mb / skb_length.
When the system memory is not enough, this recv cache can make nic work
steadily.
When nic is up, this recv cache and work queue are created. When nic
is down, this recv cache will be destroyed and delayed workqueue is
canceled.
When nic is polled or rx interrupt is triggerred, rx handler will
get a skb from recv cache. Then the state of recv cache is checked.
If recv cache is not in filling up state, a work is queued to fill
up recv cache.
When skb size is changed, the old recv cache is destroyed and new recv
cache is created.
When the system memory is not enough, the allocation of skb failed.
recv cache will continue allocate skb until the recv cache is filled up.
When the system memory is not enough, this can make nic work steadily.
Becase of recv cache, the performance of nic is enhanced.
CC: Joe Jin <joe.jin@oracle.com>
CC: Junxiao Bi <junxiao.bi@oracle.com>
Signed-off-by: Zhu Yanjun <yanjun.zhu@oracle.com>
---
drivers/net/ethernet/nvidia/forcedeth.c | 100 +++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index b327b29..a673005 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -674,6 +674,11 @@ struct nv_ethtool_stats {
u64 tx_broadcast;
};
+/* 1000Mb is 125M bytes, 125 * 1024 * 1024 bytes
+ * The length of recv cache is 125M / skb_length
+ */
+#define RECV_CACHE_LIST_LENGTH (125 * 1024 * 1024 / np->rx_buf_sz)
+
#define NV_DEV_STATISTICS_V3_COUNT (sizeof(struct nv_ethtool_stats)/sizeof(u64))
#define NV_DEV_STATISTICS_V2_COUNT (NV_DEV_STATISTICS_V3_COUNT - 3)
#define NV_DEV_STATISTICS_V1_COUNT (NV_DEV_STATISTICS_V2_COUNT - 6)
@@ -844,8 +849,18 @@ struct fe_priv {
char name_rx[IFNAMSIZ + 3]; /* -rx */
char name_tx[IFNAMSIZ + 3]; /* -tx */
char name_other[IFNAMSIZ + 6]; /* -other */
+
+ /* This is to schedule work */
+ struct delayed_work recv_cache_work;
+ /* This list is to store skb queue for recv */
+ struct sk_buff_head recv_list;
+ unsigned long nv_recv_list_state;
};
+/* This is recv list state to fill up recv cache */
+enum recv_list_state {
+ RECV_LIST_ALLOCATE
+};
/*
* Maximum number of loops until we assume that a bit in the irq mask
* is stuck. Overridable with module param.
@@ -1804,7 +1819,11 @@ static int nv_alloc_rx(struct net_device *dev)
less_rx = np->last_rx.orig;
while (np->put_rx.orig != less_rx) {
- struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz + NV_RX_ALLOC_PAD);
+ struct sk_buff *skb = skb_dequeue(&np->recv_list);
+
+ if (!test_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state))
+ schedule_delayed_work(&np->recv_cache_work, 0);
+
if (likely(skb)) {
np->put_rx_ctx->skb = skb;
np->put_rx_ctx->dma = dma_map_single(&np->pci_dev->dev,
@@ -1845,7 +1864,11 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
less_rx = np->last_rx.ex;
while (np->put_rx.ex != less_rx) {
- struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz + NV_RX_ALLOC_PAD);
+ struct sk_buff *skb = skb_dequeue(&np->recv_list);
+
+ if (!test_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state))
+ schedule_delayed_work(&np->recv_cache_work, 0);
+
if (likely(skb)) {
np->put_rx_ctx->skb = skb;
np->put_rx_ctx->dma = dma_map_single(&np->pci_dev->dev,
@@ -1957,6 +1980,40 @@ static void nv_init_tx(struct net_device *dev)
}
}
+static void nv_init_recv_cache(struct net_device *dev)
+{
+ struct fe_priv *np = netdev_priv(dev);
+
+ skb_queue_head_init(&np->recv_list);
+ while (skb_queue_len(&np->recv_list) < RECV_CACHE_LIST_LENGTH) {
+ struct sk_buff *skb = netdev_alloc_skb(dev,
+ np->rx_buf_sz + NV_RX_ALLOC_PAD);
+ /* skb is null. This indicates that memory is not
+ * enough.
+ */
+ if (unlikely(!skb)) {
+ ndelay(3);
+ continue;
+ }
+
+ skb_queue_tail(&np->recv_list, skb);
+ }
+}
+
+static void nv_destroy_recv_cache(struct net_device *dev)
+{
+ struct sk_buff *skb;
+ struct fe_priv *np = netdev_priv(dev);
+
+ cancel_delayed_work_sync(&np->recv_cache_work);
+ WARN_ON(delayed_work_pending(&np->recv_cache_work));
+
+ while ((skb = skb_dequeue(&np->recv_list)))
+ kfree_skb(skb);
+
+ WARN_ON(skb_queue_len(&np->recv_list));
+}
+
static int nv_init_ring(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
@@ -3047,6 +3104,8 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
nv_drain_rxtx(dev);
/* reinit driver view of the rx queue */
set_bufsize(dev);
+ nv_destroy_recv_cache(dev);
+ nv_init_recv_cache(dev);
if (nv_init_ring(dev)) {
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
@@ -4074,6 +4133,32 @@ static void nv_free_irq(struct net_device *dev)
}
}
+static void nv_recv_cache_worker(struct work_struct *work)
+{
+ struct fe_priv *np = container_of(work, struct fe_priv,
+ recv_cache_work.work);
+
+ set_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state);
+ while (skb_queue_len(&np->recv_list) < RECV_CACHE_LIST_LENGTH) {
+ struct sk_buff *skb = netdev_alloc_skb(np->dev,
+ np->rx_buf_sz + NV_RX_ALLOC_PAD);
+ /* skb is null. This indicates that memory is not
+ * enough.
+ * When the system memory is not enough, the kernel
+ * will compact memory or drop caches. At that time,
+ * if memory allocation fails, it had better wait some
+ * time for memory.
+ */
+ if (unlikely(!skb)) {
+ ndelay(3);
+ continue;
+ }
+
+ skb_queue_tail(&np->recv_list, skb);
+ }
+ clear_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state);
+}
+
static void nv_do_nic_poll(struct timer_list *t)
{
struct fe_priv *np = from_timer(np, t, nic_poll);
@@ -4129,6 +4214,8 @@ static void nv_do_nic_poll(struct timer_list *t)
nv_drain_rxtx(dev);
/* reinit driver view of the rx queue */
set_bufsize(dev);
+ nv_destroy_recv_cache(dev);
+ nv_init_recv_cache(dev);
if (nv_init_ring(dev)) {
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
@@ -4681,6 +4768,8 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
if (netif_running(dev)) {
/* reinit driver view of the queues */
set_bufsize(dev);
+ nv_destroy_recv_cache(dev);
+ nv_init_recv_cache(dev);
if (nv_init_ring(dev)) {
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
@@ -5402,6 +5491,10 @@ static int nv_open(struct net_device *dev)
/* initialize descriptor rings */
set_bufsize(dev);
+ nv_init_recv_cache(dev);
+
+ INIT_DELAYED_WORK(&np->recv_cache_work, nv_recv_cache_worker);
+ clear_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state);
oom = nv_init_ring(dev);
writel(0, base + NvRegLinkSpeed);
@@ -5583,6 +5676,9 @@ static int nv_close(struct net_device *dev)
nv_txrx_gate(dev, true);
}
+ /* free all SKBs in recv cache */
+ nv_destroy_recv_cache(dev);
+
/* FIXME: power down nic */
return 0;
--
2.7.4
^ permalink raw reply related
* [PATCH 04/10] net: hisilicon: HI13X1_GMAX skip write LOCAL_PAGE_REG
From: Jiangfeng Xiao @ 2019-07-05 6:11 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
HI13X1_GMAC changed the offsets and bitmaps for
GE_TX_LOCAL_PAGE_REG registers in the same peripheral
device on different models of the hip04_eth. With the
default configuration, HI13X1_GMAC can also work without
any writes to the GE_TX_LOCAL_PAGE_REG register.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index d8f0619..fe61b01 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -308,8 +308,10 @@ static void hip04_config_fifo(struct hip04_priv *priv)
val |= GE_RX_STRIP_PAD | GE_RX_PAD_EN;
writel_relaxed(val, priv->base + GE_RECV_CONTROL_REG);
+#ifndef CONFIG_HI13X1_GMAC
val = GE_AUTO_NEG_CTL;
writel_relaxed(val, priv->base + GE_TX_LOCAL_PAGE_REG);
+#endif
}
static void hip04_mac_enable(struct net_device *ndev)
--
1.8.5.6
^ permalink raw reply related
* [PATCH 0/2] forcedeth: recv cache support
From: Zhu Yanjun @ 2019-07-05 6:19 UTC (permalink / raw)
To: yanjun.zhu, netdev, davem
This recv cache is to make NIC work steadily when the system memory is
not enough.
From long time testing, the NIC worked very well when the system memory
is not enough. And the NIC performance is better from about 920M to
about 940M.
Some simple tests are made:
ip link set forcedeth_nic down/up
modprobe/rmmod forcedeth
ip link set mtu 1500 dev forcedeth_nic
ethtool -G forcedeth_nic tx 512 rx 1024
And other tests, the NIC with the recv cache can work well.
Since the recv cache will reserve 125M memory for NIC, normally this recv
cache is disabled by default.
Zhu Yanjun (2):
forcedeth: add recv cache make nic work steadily
forcedeth: disable recv cache by default
drivers/net/ethernet/nvidia/Kconfig | 11 +++
drivers/net/ethernet/nvidia/Makefile | 1 +
drivers/net/ethernet/nvidia/forcedeth.c | 128 +++++++++++++++++++++++++++++++-
3 files changed, 138 insertions(+), 2 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH 05/10] net: hisilicon: HI13X1_GMAX need dreq reset at first
From: Jiangfeng Xiao @ 2019-07-05 6:11 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
HI13X1_GMAC delete request for soft reset at first,
otherwise, the subsequent initialization will not
take effect.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index fe61b01..19d8cfd 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -16,6 +16,8 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
+#define SC_PPE_RESET_DREQ 0x026C
+
#define PPE_CFG_RX_ADDR 0x100
#define PPE_CFG_POOL_GRP 0x300
#define PPE_CFG_RX_BUF_SIZE 0x400
@@ -61,6 +63,8 @@
#define PPE_HIS_RX_PKT_CNT 0x804
+#define RESET_DREQ_ALL 0xffffffff
+
/* REG_INTERRUPT */
#define RCV_INT BIT(10)
#define RCV_NOBUF BIT(8)
@@ -168,6 +172,9 @@ struct rx_desc {
struct hip04_priv {
void __iomem *base;
+#if defined(CONFIG_HI13X1_GMAC)
+ void __iomem *sysctrl_base;
+#endif
int phy_mode;
int chan;
unsigned int port;
@@ -244,6 +251,13 @@ static void hip04_config_port(struct net_device *ndev, u32 speed, u32 duplex)
writel_relaxed(val, priv->base + GE_MODE_CHANGE_REG);
}
+static void hip04_reset_dreq(struct hip04_priv *priv)
+{
+#if defined(CONFIG_HI13X1_GMAC)
+ writel_relaxed(RESET_DREQ_ALL, priv->sysctrl_base + SC_PPE_RESET_DREQ);
+#endif
+}
+
static void hip04_reset_ppe(struct hip04_priv *priv)
{
u32 val, tmp, timeout = 0;
@@ -853,6 +867,15 @@ static int hip04_mac_probe(struct platform_device *pdev)
goto init_fail;
}
+#if defined(CONFIG_HI13X1_GMAC)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->sysctrl_base = devm_ioremap_resource(d, res);
+ if (IS_ERR(priv->sysctrl_base)) {
+ ret = PTR_ERR(priv->sysctrl_base);
+ goto init_fail;
+ }
+#endif
+
ret = of_parse_phandle_with_fixed_args(node, "port-handle", 2, 0, &arg);
if (ret < 0) {
dev_warn(d, "no port-handle\n");
@@ -921,6 +944,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
ndev->irq = irq;
netif_napi_add(ndev, &priv->napi, hip04_rx_poll, NAPI_POLL_WEIGHT);
+ hip04_reset_dreq(priv);
hip04_reset_ppe(priv);
if (priv->phy_mode == PHY_INTERFACE_MODE_MII)
hip04_config_port(ndev, SPEED_100, DUPLEX_FULL);
--
1.8.5.6
^ permalink raw reply related
* [PATCH 06/10] net: hisilicon: dt-bindings: Add an field of port-handle
From: Jiangfeng Xiao @ 2019-07-05 6:11 UTC (permalink / raw)
To: robh+dt, mark.rutland, yisen.zhuang, salil.mehta, dingtianhong,
xiaojiangfeng
Cc: davem, netdev, devicetree, linux-kernel, leeyou.li, xiekunxun,
jianping.liu, nixiaoming
In general, group is the same as the port, but some
boards specify a special group for better load
balancing of each processing unit.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
Documentation/devicetree/bindings/net/hisilicon-hip04-net.txt | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/hisilicon-hip04-net.txt b/Documentation/devicetree/bindings/net/hisilicon-hip04-net.txt
index d1df8a0..464c0da 100644
--- a/Documentation/devicetree/bindings/net/hisilicon-hip04-net.txt
+++ b/Documentation/devicetree/bindings/net/hisilicon-hip04-net.txt
@@ -10,6 +10,7 @@ Required properties:
phandle, specifies a reference to the syscon ppe node
port, port number connected to the controller
channel, recv channel start from channel * number (RX_DESC_NUM)
+ group, field in the pkg desc, in general, it is the same as the port.
- phy-mode: see ethernet.txt [1].
Optional properties:
@@ -66,7 +67,7 @@ Example:
reg = <0x28b0000 0x10000>;
interrupts = <0 413 4>;
phy-mode = "mii";
- port-handle = <&ppe 31 0>;
+ port-handle = <&ppe 31 0 31>;
};
ge0: ethernet@2800000 {
@@ -74,7 +75,7 @@ Example:
reg = <0x2800000 0x10000>;
interrupts = <0 402 4>;
phy-mode = "sgmii";
- port-handle = <&ppe 0 1>;
+ port-handle = <&ppe 0 1 0>;
phy-handle = <&phy0>;
};
@@ -83,6 +84,6 @@ Example:
reg = <0x2880000 0x10000>;
interrupts = <0 410 4>;
phy-mode = "sgmii";
- port-handle = <&ppe 8 2>;
+ port-handle = <&ppe 8 2 8>;
phy-handle = <&phy1>;
};
--
1.8.5.6
^ permalink raw reply related
* [PATCH 07/10] net: hisilicon: Add group field to adapt HI13X1_GMAC
From: Jiangfeng Xiao @ 2019-07-05 6:12 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
In general, group is the same as the port, but some
boards specify a special group for better load
balancing of each processing unit.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 19d8cfd..5328219 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -178,6 +178,7 @@ struct hip04_priv {
int phy_mode;
int chan;
unsigned int port;
+ unsigned int group;
unsigned int speed;
unsigned int duplex;
unsigned int reg_inten;
@@ -278,10 +279,10 @@ static void hip04_config_fifo(struct hip04_priv *priv)
val |= PPE_CFG_STS_RX_PKT_CNT_RC;
writel_relaxed(val, priv->base + PPE_CFG_STS_MODE);
- val = BIT(priv->port);
+ val = BIT(priv->group);
regmap_write(priv->map, priv->port * 4 + PPE_CFG_POOL_GRP, val);
- val = priv->port << PPE_CFG_QOS_VMID_GRP_SHIFT;
+ val = priv->group << PPE_CFG_QOS_VMID_GRP_SHIFT;
val |= PPE_CFG_QOS_VMID_MODE;
writel_relaxed(val, priv->base + PPE_CFG_QOS_VMID_GEN);
@@ -876,7 +877,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
}
#endif
- ret = of_parse_phandle_with_fixed_args(node, "port-handle", 2, 0, &arg);
+ ret = of_parse_phandle_with_fixed_args(node, "port-handle", 3, 0, &arg);
if (ret < 0) {
dev_warn(d, "no port-handle\n");
goto init_fail;
@@ -884,6 +885,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
priv->port = arg.args[0];
priv->chan = arg.args[1] * RX_DESC_NUM;
+ priv->group = arg.args[2];
hrtimer_init(&priv->tx_coalesce_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
--
1.8.5.6
^ permalink raw reply related
* [PATCH 08/10] net: hisilicon: Offset buf address to adapt HI13X1_GMAC
From: Jiangfeng Xiao @ 2019-07-05 6:12 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
The buf unit size of HI13X1_GMAC is cache_line_size,
which is 64, so the address we write to the buf register
needs to be shifted right by 6 bits.
The 31st bit of the PPE_CFG_CPU_ADD_ADDR register
of HI13X1_GMAC indicates whether to release the buffer
of the message, and the low indicates that it is valid.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 5328219..c578934 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -120,12 +120,20 @@
#define PPE_CFG_STS_RX_PKT_CNT_RC BIT(0)
#define PPE_CFG_QOS_VMID_MODE BIT(15)
#define PPE_CFG_BUS_LOCAL_REL (BIT(9) | BIT(15) | BIT(19) | BIT(23))
+
+/* buf unit size is cache_line_size, which is 64, so the shift is 6 */
+#define PPE_BUF_SIZE_SHIFT 6
+#define PPE_TX_BUF_HOLD BIT(31)
#else
#define PPE_CFG_QOS_VMID_GRP_SHIFT 8
#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 11
#define PPE_CFG_STS_RX_PKT_CNT_RC BIT(12)
#define PPE_CFG_QOS_VMID_MODE BIT(14)
#define PPE_CFG_BUS_LOCAL_REL BIT(14)
+
+/* buf unit size is 1, so the shift is 6 */
+#define PPE_BUF_SIZE_SHIFT 0
+#define PPE_TX_BUF_HOLD 0
#endif /* CONFIG_HI13X1_GMAC */
#define PPE_CFG_RX_FIFO_FSFU BIT(11)
@@ -286,7 +294,7 @@ static void hip04_config_fifo(struct hip04_priv *priv)
val |= PPE_CFG_QOS_VMID_MODE;
writel_relaxed(val, priv->base + PPE_CFG_QOS_VMID_GEN);
- val = RX_BUF_SIZE;
+ val = RX_BUF_SIZE >> PPE_BUF_SIZE_SHIFT;
regmap_write(priv->map, priv->port * 4 + PPE_CFG_RX_BUF_SIZE, val);
val = RX_DESC_NUM << PPE_CFG_RX_DEPTH_SHIFT;
@@ -369,12 +377,18 @@ static void hip04_mac_disable(struct net_device *ndev)
static void hip04_set_xmit_desc(struct hip04_priv *priv, dma_addr_t phys)
{
- writel(phys, priv->base + PPE_CFG_CPU_ADD_ADDR);
+ u32 val;
+
+ val = phys >> PPE_BUF_SIZE_SHIFT | PPE_TX_BUF_HOLD;
+ writel(val, priv->base + PPE_CFG_CPU_ADD_ADDR);
}
static void hip04_set_recv_desc(struct hip04_priv *priv, dma_addr_t phys)
{
- regmap_write(priv->map, priv->port * 4 + PPE_CFG_RX_ADDR, phys);
+ u32 val;
+
+ val = phys >> PPE_BUF_SIZE_SHIFT;
+ regmap_write(priv->map, priv->port * 4 + PPE_CFG_RX_ADDR, val);
}
static u32 hip04_recv_cnt(struct hip04_priv *priv)
--
1.8.5.6
^ permalink raw reply related
* [PATCH 09/10] net: hisilicon: Add an rx_desc to adapt HI13X1_GMAC
From: Jiangfeng Xiao @ 2019-07-05 6:12 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
HI13X1 changed the offsets and bitmaps for rx_desc
registers in the same peripheral device on different
models of the hip04_eth.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index c578934..780fc46 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -171,11 +171,20 @@ struct tx_desc {
} __aligned(64);
struct rx_desc {
+#if defined(CONFIG_HI13X1_GMAC)
+ u32 reserved1[3];
+ u16 pkt_len;
+ u16 reserved_16;
+ u32 reserved2[6];
+ u32 pkt_err;
+ u32 reserved3[5];
+#else
u16 reserved_16;
u16 pkt_len;
u32 reserve1[3];
u32 pkt_err;
u32 reserve2[4];
+#endif
};
struct hip04_priv {
--
1.8.5.6
^ permalink raw reply related
* [PATCH 10/10] net: hisilicon: Add an tx_desc to adapt HI13X1_GMAC
From: Jiangfeng Xiao @ 2019-07-05 6:12 UTC (permalink / raw)
To: yisen.zhuang, salil.mehta, dingtianhong, xiaojiangfeng
Cc: davem, robh+dt, mark.rutland, netdev, devicetree, linux-kernel,
leeyou.li, xiekunxun, jianping.liu, nixiaoming
HI13X1 changed the offsets and bitmaps for tx_desc
registers in the same peripheral device on different
models of the hip04_eth.
Signed-off-by: Jiangfeng Xiao <xiaojiangfeng@huawei.com>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 34 +++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 780fc46..6256357 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -76,8 +76,15 @@
/* TX descriptor config */
#define TX_FREE_MEM BIT(0)
#define TX_READ_ALLOC_L3 BIT(1)
-#define TX_FINISH_CACHE_INV BIT(2)
+#if defined(CONFIG_HI13X1_GMAC)
+#define TX_CLEAR_WB BIT(7)
+#define TX_RELEASE_TO_PPE BIT(4)
+#define TX_FINISH_CACHE_INV BIT(6)
+#define TX_POOL_SHIFT 16
+#else
#define TX_CLEAR_WB BIT(4)
+#define TX_FINISH_CACHE_INV BIT(2)
+#endif
#define TX_L3_CHECKSUM BIT(5)
#define TX_LOOP_BACK BIT(11)
@@ -124,6 +131,7 @@
/* buf unit size is cache_line_size, which is 64, so the shift is 6 */
#define PPE_BUF_SIZE_SHIFT 6
#define PPE_TX_BUF_HOLD BIT(31)
+#define CACHE_LINE_MASK 0x3F
#else
#define PPE_CFG_QOS_VMID_GRP_SHIFT 8
#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 11
@@ -163,11 +171,22 @@
#define HIP04_MIN_TX_COALESCE_FRAMES 100
struct tx_desc {
+#if defined(CONFIG_HI13X1_GMAC)
+ u32 reserved1[2];
+ u32 send_addr;
+ u16 send_size;
+ u16 data_offset;
+ u32 reserved2[7];
+ u32 cfg;
+ u32 wb_addr;
+ u32 reserved3[3];
+#else
u32 send_addr;
u32 send_size;
u32 next_addr;
u32 cfg;
u32 wb_addr;
+#endif
} __aligned(64);
struct rx_desc {
@@ -505,11 +524,20 @@ static void hip04_start_tx_timer(struct hip04_priv *priv)
priv->tx_skb[tx_head] = skb;
priv->tx_phys[tx_head] = phys;
- desc->send_addr = (__force u32)cpu_to_be32(phys);
+
desc->send_size = (__force u32)cpu_to_be32(skb->len);
+#if defined(CONFIG_HI13X1_GMAC)
+ desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV
+ | TX_RELEASE_TO_PPE | priv->port << TX_POOL_SHIFT);
+ desc->data_offset = (__force u32)cpu_to_be32(phys & CACHE_LINE_MASK);
+ desc->send_addr = (__force u32)cpu_to_be32(phys & ~CACHE_LINE_MASK);
+#else
desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV);
+ desc->send_addr = (__force u32)cpu_to_be32(phys);
+#endif
phys = priv->tx_desc_dma + tx_head * sizeof(struct tx_desc);
- desc->wb_addr = (__force u32)cpu_to_be32(phys);
+ desc->wb_addr = (__force u32)cpu_to_be32(phys +
+ offsetof(struct tx_desc, send_addr));
skb_tx_timestamp(skb);
hip04_set_xmit_desc(priv, phys);
--
1.8.5.6
^ permalink raw reply related
* [PATCH 2/2] forcedeth: disable recv cache by default
From: Zhu Yanjun @ 2019-07-05 6:19 UTC (permalink / raw)
To: yanjun.zhu, netdev, davem
In-Reply-To: <1562307568-21549-1-git-send-email-yanjun.zhu@oracle.com>
The recv cache is to allocate 125MiB memory to reserve for NIC.
In the past time, this recv cache works very well. When the memory
is not enough, this recv cache reserves memory for NIC.
And the communications through this NIC is not affected by the
memory shortage. And the performance of NIC is better because of
this recv cache.
But this recv cache reserves 125MiB memory for one NIC port. Normally
there are 2 NIC ports in one card. So in a host, there are about 250
MiB memory reserved for NIC ports. To a host on which communications
are not mandatory, it is not necessary to reserve memory.
So this recv cache is disabled by default.
CC: Joe Jin <joe.jin@oracle.com>
CC: Junxiao Bi <junxiao.bi@oracle.com>
Signed-off-by: Zhu Yanjun <yanjun.zhu@oracle.com>
---
drivers/net/ethernet/nvidia/Kconfig | 11 +++++++++++
drivers/net/ethernet/nvidia/Makefile | 1 +
drivers/net/ethernet/nvidia/forcedeth.c | 34 ++++++++++++++++++++++++++++++---
3 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/nvidia/Kconfig b/drivers/net/ethernet/nvidia/Kconfig
index faacbd1..9a9f42a 100644
--- a/drivers/net/ethernet/nvidia/Kconfig
+++ b/drivers/net/ethernet/nvidia/Kconfig
@@ -26,4 +26,15 @@ config FORCEDETH
To compile this driver as a module, choose M here. The module
will be called forcedeth.
+config FORCEDETH_RECV_CACHE
+ bool "nForce Ethernet recv cache support"
+ depends on FORCEDETH
+ default n
+ ---help---
+ The recv cache can make nic work steadily when the system memory is
+ not enough. And it can also enhance nic performance. But to a host
+ on which the communications are not mandatory, it is not necessary
+ to reserve 125MiB memory for NIC.
+ So recv cache is disabled by default.
+
endif # NET_VENDOR_NVIDIA
diff --git a/drivers/net/ethernet/nvidia/Makefile b/drivers/net/ethernet/nvidia/Makefile
index 8935699..40c055e 100644
--- a/drivers/net/ethernet/nvidia/Makefile
+++ b/drivers/net/ethernet/nvidia/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_FORCEDETH) += forcedeth.o
+ccflags-$(CONFIG_FORCEDETH_RECV_CACHE) := -DFORCEDETH_RECV_CACHE
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index a673005..59f813b 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -674,10 +674,12 @@ struct nv_ethtool_stats {
u64 tx_broadcast;
};
+#ifdef FORCEDETH_RECV_CACHE
/* 1000Mb is 125M bytes, 125 * 1024 * 1024 bytes
* The length of recv cache is 125M / skb_length
*/
#define RECV_CACHE_LIST_LENGTH (125 * 1024 * 1024 / np->rx_buf_sz)
+#endif
#define NV_DEV_STATISTICS_V3_COUNT (sizeof(struct nv_ethtool_stats)/sizeof(u64))
#define NV_DEV_STATISTICS_V2_COUNT (NV_DEV_STATISTICS_V3_COUNT - 3)
@@ -850,17 +852,22 @@ struct fe_priv {
char name_tx[IFNAMSIZ + 3]; /* -tx */
char name_other[IFNAMSIZ + 6]; /* -other */
+#ifdef FORCEDETH_RECV_CACHE
/* This is to schedule work */
struct delayed_work recv_cache_work;
/* This list is to store skb queue for recv */
struct sk_buff_head recv_list;
unsigned long nv_recv_list_state;
+#endif
};
+#ifdef FORCEDETH_RECV_CACHE
/* This is recv list state to fill up recv cache */
enum recv_list_state {
RECV_LIST_ALLOCATE
};
+#endif
+
/*
* Maximum number of loops until we assume that a bit in the irq mask
* is stuck. Overridable with module param.
@@ -1819,11 +1826,15 @@ static int nv_alloc_rx(struct net_device *dev)
less_rx = np->last_rx.orig;
while (np->put_rx.orig != less_rx) {
+#ifdef FORCEDETH_RECV_CACHE
struct sk_buff *skb = skb_dequeue(&np->recv_list);
if (!test_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state))
schedule_delayed_work(&np->recv_cache_work, 0);
-
+#else
+ struct sk_buff *skb = netdev_alloc_skb(np->dev,
+ np->rx_buf_sz + NV_RX_ALLOC_PAD);
+#endif
if (likely(skb)) {
np->put_rx_ctx->skb = skb;
np->put_rx_ctx->dma = dma_map_single(&np->pci_dev->dev,
@@ -1864,11 +1875,15 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
less_rx = np->last_rx.ex;
while (np->put_rx.ex != less_rx) {
+#ifdef FORCEDETH_RECV_CACHE
struct sk_buff *skb = skb_dequeue(&np->recv_list);
if (!test_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state))
schedule_delayed_work(&np->recv_cache_work, 0);
-
+#else
+ struct sk_buff *skb = netdev_alloc_skb(np->dev,
+ np->rx_buf_sz + NV_RX_ALLOC_PAD);
+#endif
if (likely(skb)) {
np->put_rx_ctx->skb = skb;
np->put_rx_ctx->dma = dma_map_single(&np->pci_dev->dev,
@@ -1980,6 +1995,7 @@ static void nv_init_tx(struct net_device *dev)
}
}
+#ifdef FORCEDETH_RECV_CACHE
static void nv_init_recv_cache(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
@@ -2013,6 +2029,7 @@ static void nv_destroy_recv_cache(struct net_device *dev)
WARN_ON(skb_queue_len(&np->recv_list));
}
+#endif
static int nv_init_ring(struct net_device *dev)
{
@@ -3104,8 +3121,10 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
nv_drain_rxtx(dev);
/* reinit driver view of the rx queue */
set_bufsize(dev);
+#ifdef FORCEDETH_RECV_CACHE
nv_destroy_recv_cache(dev);
nv_init_recv_cache(dev);
+#endif
if (nv_init_ring(dev)) {
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
@@ -4133,6 +4152,7 @@ static void nv_free_irq(struct net_device *dev)
}
}
+#ifdef FORCEDETH_RECV_CACHE
static void nv_recv_cache_worker(struct work_struct *work)
{
struct fe_priv *np = container_of(work, struct fe_priv,
@@ -4158,6 +4178,7 @@ static void nv_recv_cache_worker(struct work_struct *work)
}
clear_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state);
}
+#endif
static void nv_do_nic_poll(struct timer_list *t)
{
@@ -4214,8 +4235,10 @@ static void nv_do_nic_poll(struct timer_list *t)
nv_drain_rxtx(dev);
/* reinit driver view of the rx queue */
set_bufsize(dev);
+#ifdef FORCEDETH_RECV_CACHE
nv_destroy_recv_cache(dev);
nv_init_recv_cache(dev);
+#endif
if (nv_init_ring(dev)) {
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
@@ -4768,8 +4791,10 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
if (netif_running(dev)) {
/* reinit driver view of the queues */
set_bufsize(dev);
+#ifdef FORCEDETH_RECV_CACHE
nv_destroy_recv_cache(dev);
nv_init_recv_cache(dev);
+#endif
if (nv_init_ring(dev)) {
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
@@ -5491,10 +5516,12 @@ static int nv_open(struct net_device *dev)
/* initialize descriptor rings */
set_bufsize(dev);
+#ifdef FORCEDETH_RECV_CACHE
nv_init_recv_cache(dev);
INIT_DELAYED_WORK(&np->recv_cache_work, nv_recv_cache_worker);
clear_bit(RECV_LIST_ALLOCATE, &np->nv_recv_list_state);
+#endif
oom = nv_init_ring(dev);
writel(0, base + NvRegLinkSpeed);
@@ -5676,9 +5703,10 @@ static int nv_close(struct net_device *dev)
nv_txrx_gate(dev, true);
}
+#ifdef FORCEDETH_RECV_CACHE
/* free all SKBs in recv cache */
nv_destroy_recv_cache(dev);
-
+#endif
/* FIXME: power down nic */
return 0;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH bpf-next] Enable zext optimization for more RV64G ALU ops
From: Björn Töpel @ 2019-07-05 6:31 UTC (permalink / raw)
To: Luke Nelson
Cc: LKML, Luke Nelson, Song Liu, Jiong Wang, Xi Wang, Palmer Dabbelt,
Albert Ou, Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau,
Song Liu, Yonghong Song, Netdev, linux-riscv, bpf
In-Reply-To: <20190705001803.30094-1-luke.r.nels@gmail.com>
On Fri, 5 Jul 2019 at 02:18, Luke Nelson <lukenels@cs.washington.edu> wrote:
>
> commit 66d0d5a854a6 ("riscv: bpf: eliminate zero extension code-gen")
> added the new zero-extension optimization for some BPF ALU operations.
>
> Since then, bugs in the JIT that have been fixed in the bpf tree require
> this optimization to be added to other operations: commit 1e692f09e091
> ("bpf, riscv: clear high 32 bits for ALU32 add/sub/neg/lsh/rsh/arsh"),
> and commit fe121ee531d1 ("bpf, riscv: clear target register high 32-bits
> for and/or/xor on ALU32")
>
> Now that these have been merged to bpf-next, the zext optimization can
> be enabled for the fixed operations.
>
Thanks for the patch, Luke!
Acked-by: Björn Töpel <bjorn.topel@gmail.com>
> Cc: Song Liu <liu.song.a23@gmail.com>
> Cc: Jiong Wang <jiong.wang@netronome.com>
> Cc: Xi Wang <xi.wang@gmail.com>
> Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
> ---
> arch/riscv/net/bpf_jit_comp.c | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/arch/riscv/net/bpf_jit_comp.c b/arch/riscv/net/bpf_jit_comp.c
> index 876cb9c705ce..5451ef3845f2 100644
> --- a/arch/riscv/net/bpf_jit_comp.c
> +++ b/arch/riscv/net/bpf_jit_comp.c
> @@ -757,31 +757,31 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> case BPF_ALU | BPF_ADD | BPF_X:
> case BPF_ALU64 | BPF_ADD | BPF_X:
> emit(is64 ? rv_add(rd, rd, rs) : rv_addw(rd, rd, rs), ctx);
> - if (!is64)
> + if (!is64 && !aux->verifier_zext)
> emit_zext_32(rd, ctx);
> break;
> case BPF_ALU | BPF_SUB | BPF_X:
> case BPF_ALU64 | BPF_SUB | BPF_X:
> emit(is64 ? rv_sub(rd, rd, rs) : rv_subw(rd, rd, rs), ctx);
> - if (!is64)
> + if (!is64 && !aux->verifier_zext)
> emit_zext_32(rd, ctx);
> break;
> case BPF_ALU | BPF_AND | BPF_X:
> case BPF_ALU64 | BPF_AND | BPF_X:
> emit(rv_and(rd, rd, rs), ctx);
> - if (!is64)
> + if (!is64 && !aux->verifier_zext)
> emit_zext_32(rd, ctx);
> break;
> case BPF_ALU | BPF_OR | BPF_X:
> case BPF_ALU64 | BPF_OR | BPF_X:
> emit(rv_or(rd, rd, rs), ctx);
> - if (!is64)
> + if (!is64 && !aux->verifier_zext)
> emit_zext_32(rd, ctx);
> break;
> case BPF_ALU | BPF_XOR | BPF_X:
> case BPF_ALU64 | BPF_XOR | BPF_X:
> emit(rv_xor(rd, rd, rs), ctx);
> - if (!is64)
> + if (!is64 && !aux->verifier_zext)
> emit_zext_32(rd, ctx);
> break;
> case BPF_ALU | BPF_MUL | BPF_X:
> @@ -811,13 +811,13 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> case BPF_ALU | BPF_RSH | BPF_X:
> case BPF_ALU64 | BPF_RSH | BPF_X:
> emit(is64 ? rv_srl(rd, rd, rs) : rv_srlw(rd, rd, rs), ctx);
> - if (!is64)
> + if (!is64 && !aux->verifier_zext)
> emit_zext_32(rd, ctx);
> break;
> case BPF_ALU | BPF_ARSH | BPF_X:
> case BPF_ALU64 | BPF_ARSH | BPF_X:
> emit(is64 ? rv_sra(rd, rd, rs) : rv_sraw(rd, rd, rs), ctx);
> - if (!is64)
> + if (!is64 && !aux->verifier_zext)
> emit_zext_32(rd, ctx);
> break;
>
> @@ -826,7 +826,7 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> case BPF_ALU64 | BPF_NEG:
> emit(is64 ? rv_sub(rd, RV_REG_ZERO, rd) :
> rv_subw(rd, RV_REG_ZERO, rd), ctx);
> - if (!is64)
> + if (!is64 && !aux->verifier_zext)
> emit_zext_32(rd, ctx);
> break;
>
> --
> 2.20.1
>
^ permalink raw reply
* Re: [PATCH bpf] xdp: fix possible cq entry leak
From: Björn Töpel @ 2019-07-05 6:42 UTC (permalink / raw)
To: Ilya Maximets
Cc: Netdev, LKML, bpf, Xdp, David S. Miller, Björn Töpel,
Magnus Karlsson, Jonathan Lemon, Jakub Kicinski,
Alexei Starovoitov, Daniel Borkmann
In-Reply-To: <20190704142503.23501-1-i.maximets@samsung.com>
On Thu, 4 Jul 2019 at 16:25, Ilya Maximets <i.maximets@samsung.com> wrote:
>
> Completion queue address reservation could not be undone.
> In case of bad 'queue_id' or skb allocation failure, reserved entry
> will be leaked reducing the total capacity of completion queue.
>
> Fix that by moving reservation to the point where failure is not
> possible. Additionally, 'queue_id' checking moved out from the loop
> since there is no point to check it there.
>
Good catch, Ilya! Thanks for the patch!
Acked-by: Björn Töpel <bjorn.topel@intel.com>
> Fixes: 35fcde7f8deb ("xsk: support for Tx")
> Signed-off-by: Ilya Maximets <i.maximets@samsung.com>
> ---
> net/xdp/xsk.c | 11 ++++-------
> 1 file changed, 4 insertions(+), 7 deletions(-)
>
> diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
> index f53a6ef7c155..703cf5ea448b 100644
> --- a/net/xdp/xsk.c
> +++ b/net/xdp/xsk.c
> @@ -226,6 +226,9 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
>
> mutex_lock(&xs->mutex);
>
> + if (xs->queue_id >= xs->dev->real_num_tx_queues)
> + goto out;
> +
> while (xskq_peek_desc(xs->tx, &desc)) {
> char *buffer;
> u64 addr;
> @@ -236,12 +239,6 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
> goto out;
> }
>
> - if (xskq_reserve_addr(xs->umem->cq))
> - goto out;
> -
> - if (xs->queue_id >= xs->dev->real_num_tx_queues)
> - goto out;
> -
> len = desc.len;
> skb = sock_alloc_send_skb(sk, len, 1, &err);
> if (unlikely(!skb)) {
> @@ -253,7 +250,7 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
> addr = desc.addr;
> buffer = xdp_umem_get_data(xs->umem, addr);
> err = skb_store_bits(skb, 0, buffer, len);
> - if (unlikely(err)) {
> + if (unlikely(err) || xskq_reserve_addr(xs->umem->cq)) {
> kfree_skb(skb);
> goto out;
> }
> --
> 2.17.1
>
^ permalink raw reply
* RE: [PATCH v1 net-next] net: stmmac: enable clause 45 mdio support
From: Voon, Weifeng @ 2019-07-05 6:43 UTC (permalink / raw)
To: Andrew Lunn
Cc: David S. Miller, Maxime Coquelin, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, Jose Abreu, Giuseppe Cavallaro,
Florian Fainelli, Alexandre Torgue, biao huang, Ong, Boon Leong,
Kweh, Hock Leong
In-Reply-To: <20190705045242.GB30115@lunn.ch>
> > If the community prefers readability
>
> Readability nearly always comes first. There is nothing performance
> critical here, MDIO is a slow bus. So the code should be readable,
> simple to understand.
>
Noted and thanks for the comments.
>
> , I will suggest to do the c45 setup in
> > both stmmac_mdio_read() and stmmac_mdio_write() 's if(C45) condition
> rather
> > than splitting into 2 new c45_read() and c45_write() functions.
>
> Fine.
>
> Andrew
I will start preparing v2. Thanks.
Weifeng
^ permalink raw reply
* [PATCH net-next v3 1/3] net: stmmac: Implement RX Coalesce Frames setting
From: Jose Abreu @ 2019-07-05 7:22 UTC (permalink / raw)
To: linux-kernel, netdev, linux-stm32, linux-arm-kernel
Cc: Jose Abreu, Joao Pinto, David S . Miller, Giuseppe Cavallaro,
Alexandre Torgue, Jakub Kicinski
In-Reply-To: <cover.1562311299.git.joabreu@synopsys.com>
Add support for coalescing RX path by specifying number of frames which
don't need to have interrupt on completion bit set.
This is only available when RX Watchdog is enabled.
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Cc: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 7 +++++--
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 18 ++++++++++++------
4 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 2403a65167b2..dfd47fdfa447 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -252,6 +252,7 @@ struct stmmac_safety_stats {
#define STMMAC_MAX_COAL_TX_TICK 100000
#define STMMAC_TX_MAX_FRAMES 256
#define STMMAC_TX_FRAMES 1
+#define STMMAC_RX_FRAMES 25
/* Packets types */
enum packets_types {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 123898235cb0..513f4e2df5f6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -55,6 +55,7 @@ struct stmmac_tx_queue {
};
struct stmmac_rx_queue {
+ u32 rx_count_frames;
u32 queue_index;
struct stmmac_priv *priv_data;
struct dma_extended_desc *dma_erx;
@@ -110,6 +111,7 @@ struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
u32 tx_coal_frames;
u32 tx_coal_timer;
+ u32 rx_coal_frames;
int tx_coalesce;
int hwts_tx_en;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index cfd93eefb50e..6efb66820d4c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -701,8 +701,10 @@ static int stmmac_get_coalesce(struct net_device *dev,
ec->tx_coalesce_usecs = priv->tx_coal_timer;
ec->tx_max_coalesced_frames = priv->tx_coal_frames;
- if (priv->use_riwt)
+ if (priv->use_riwt) {
+ ec->rx_max_coalesced_frames = priv->rx_coal_frames;
ec->rx_coalesce_usecs = stmmac_riwt2usec(priv->rx_riwt, priv);
+ }
return 0;
}
@@ -715,7 +717,7 @@ static int stmmac_set_coalesce(struct net_device *dev,
unsigned int rx_riwt;
/* Check not supported parameters */
- if ((ec->rx_max_coalesced_frames) || (ec->rx_coalesce_usecs_irq) ||
+ if ((ec->rx_coalesce_usecs_irq) ||
(ec->rx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) ||
(ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) ||
(ec->pkt_rate_low) || (ec->rx_coalesce_usecs_low) ||
@@ -749,6 +751,7 @@ static int stmmac_set_coalesce(struct net_device *dev,
/* Only copy relevant parameters, ignore all others. */
priv->tx_coal_frames = ec->tx_max_coalesced_frames;
priv->tx_coal_timer = ec->tx_coalesce_usecs;
+ priv->rx_coal_frames = ec->rx_max_coalesced_frames;
priv->rx_riwt = rx_riwt;
stmmac_rx_watchdog(priv, priv->ioaddr, priv->rx_riwt, rx_cnt);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3425d4dda03d..c8fe85ef9a7e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2268,20 +2268,21 @@ static void stmmac_tx_timer(struct timer_list *t)
}
/**
- * stmmac_init_tx_coalesce - init tx mitigation options.
+ * stmmac_init_coalesce - init mitigation options.
* @priv: driver private structure
* Description:
- * This inits the transmit coalesce parameters: i.e. timer rate,
+ * This inits the coalesce parameters: i.e. timer rate,
* timer handler and default threshold used for enabling the
* interrupt on completion bit.
*/
-static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
+static void stmmac_init_coalesce(struct stmmac_priv *priv)
{
u32 tx_channel_count = priv->plat->tx_queues_to_use;
u32 chan;
priv->tx_coal_frames = STMMAC_TX_FRAMES;
priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
+ priv->rx_coal_frames = STMMAC_RX_FRAMES;
for (chan = 0; chan < tx_channel_count; chan++) {
struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan];
@@ -2651,7 +2652,7 @@ static int stmmac_open(struct net_device *dev)
goto init_error;
}
- stmmac_init_tx_coalesce(priv);
+ stmmac_init_coalesce(priv);
phylink_start(priv->phylink);
@@ -3298,6 +3299,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
while (dirty-- > 0) {
struct dma_desc *p;
+ bool use_rx_wd;
if (priv->extend_desc)
p = (struct dma_desc *)(rx_q->dma_erx + entry);
@@ -3340,7 +3342,11 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
}
dma_wmb();
- stmmac_set_rx_owner(priv, p, priv->use_riwt);
+ rx_q->rx_count_frames++;
+ rx_q->rx_count_frames %= priv->rx_coal_frames;
+ use_rx_wd = priv->use_riwt && rx_q->rx_count_frames;
+
+ stmmac_set_rx_owner(priv, p, use_rx_wd);
dma_wmb();
@@ -4623,7 +4629,7 @@ int stmmac_resume(struct device *dev)
stmmac_clear_descriptors(priv);
stmmac_hw_setup(ndev, false);
- stmmac_init_tx_coalesce(priv);
+ stmmac_init_coalesce(priv);
stmmac_set_rx_mode(ndev);
stmmac_enable_all_queues(priv);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v3 2/3] net: stmmac: Fix descriptors address being in > 32 bits address space
From: Jose Abreu @ 2019-07-05 7:22 UTC (permalink / raw)
To: linux-kernel, netdev, linux-stm32, linux-arm-kernel
Cc: Jose Abreu, Joao Pinto, David S . Miller, Giuseppe Cavallaro,
Alexandre Torgue, Maxime Coquelin, Maxime Ripard, Chen-Yu Tsai
In-Reply-To: <cover.1562311299.git.joabreu@synopsys.com>
Commit a993db88d17d ("net: stmmac: Enable support for > 32 Bits
addressing in XGMAC"), introduced support for > 32 bits addressing in
XGMAC but the conversion of descriptors to dma_addr_t was left out.
As some devices assing coherent memory in regions > 32 bits we need to
set lower and upper value of descriptors address when initializing DMA
channels.
Luckly, this was working for me because I was assigning CMA to < 4GB
address space for performance reasons.
Fixes: a993db88d17d ("net: stmmac: Enable support for > 32 Bits addressing in XGMAC")
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Maxime Ripard <maxime.ripard@bootlin.com>
Cc: Chen-Yu Tsai <wens@csie.org>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 8 ++++----
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 8 ++++----
drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 8 ++++----
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 8 ++++----
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 2 ++
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 10 ++++++----
drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 ++--
7 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 6d5cba4075eb..2856f3fe5266 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -289,18 +289,18 @@ static void sun8i_dwmac_dma_init(void __iomem *ioaddr,
static void sun8i_dwmac_dma_init_rx(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_rx_phy, u32 chan)
+ dma_addr_t dma_rx_phy, u32 chan)
{
/* Write RX descriptors address */
- writel(dma_rx_phy, ioaddr + EMAC_RX_DESC_LIST);
+ writel(lower_32_bits(dma_rx_phy), ioaddr + EMAC_RX_DESC_LIST);
}
static void sun8i_dwmac_dma_init_tx(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_tx_phy, u32 chan)
+ dma_addr_t dma_tx_phy, u32 chan)
{
/* Write TX descriptors address */
- writel(dma_tx_phy, ioaddr + EMAC_TX_DESC_LIST);
+ writel(lower_32_bits(dma_tx_phy), ioaddr + EMAC_TX_DESC_LIST);
}
/* sun8i_dwmac_dump_regs() - Dump EMAC address space
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 1fdedf77678f..2bac49b49f73 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -112,18 +112,18 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
static void dwmac1000_dma_init_rx(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_rx_phy, u32 chan)
+ dma_addr_t dma_rx_phy, u32 chan)
{
/* RX descriptor base address list must be written into DMA CSR3 */
- writel(dma_rx_phy, ioaddr + DMA_RCV_BASE_ADDR);
+ writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
}
static void dwmac1000_dma_init_tx(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_tx_phy, u32 chan)
+ dma_addr_t dma_tx_phy, u32 chan)
{
/* TX descriptor base address list must be written into DMA CSR4 */
- writel(dma_tx_phy, ioaddr + DMA_TX_BASE_ADDR);
+ writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
}
static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index c980cc7360a4..8f0d9bc7cab5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
@@ -31,18 +31,18 @@ static void dwmac100_dma_init(void __iomem *ioaddr,
static void dwmac100_dma_init_rx(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_rx_phy, u32 chan)
+ dma_addr_t dma_rx_phy, u32 chan)
{
/* RX descriptor base addr lists must be written into DMA CSR3 */
- writel(dma_rx_phy, ioaddr + DMA_RCV_BASE_ADDR);
+ writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
}
static void dwmac100_dma_init_tx(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_tx_phy, u32 chan)
+ dma_addr_t dma_tx_phy, u32 chan)
{
/* TX descriptor base addr lists must be written into DMA CSR4 */
- writel(dma_tx_phy, ioaddr + DMA_TX_BASE_ADDR);
+ writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
}
/* Store and Forward capability is not used at all.
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 0f208e13da9f..6cbcdaea55f6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -70,7 +70,7 @@ static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
static void dwmac4_dma_init_rx_chan(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_rx_phy, u32 chan)
+ dma_addr_t dma_rx_phy, u32 chan)
{
u32 value;
u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
@@ -79,12 +79,12 @@ static void dwmac4_dma_init_rx_chan(void __iomem *ioaddr,
value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
- writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(chan));
+ writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RX_BASE_ADDR(chan));
}
static void dwmac4_dma_init_tx_chan(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_tx_phy, u32 chan)
+ dma_addr_t dma_tx_phy, u32 chan)
{
u32 value;
u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
@@ -97,7 +97,7 @@ static void dwmac4_dma_init_tx_chan(void __iomem *ioaddr,
writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
- writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
+ writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
}
static void dwmac4_dma_init_channel(void __iomem *ioaddr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index 9a9792527530..7f86dffb264d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -199,7 +199,9 @@
#define XGMAC_RxPBL GENMASK(21, 16)
#define XGMAC_RxPBL_SHIFT 16
#define XGMAC_RXST BIT(0)
+#define XGMAC_DMA_CH_TxDESC_HADDR(x) (0x00003110 + (0x80 * (x)))
#define XGMAC_DMA_CH_TxDESC_LADDR(x) (0x00003114 + (0x80 * (x)))
+#define XGMAC_DMA_CH_RxDESC_HADDR(x) (0x00003118 + (0x80 * (x)))
#define XGMAC_DMA_CH_RxDESC_LADDR(x) (0x0000311c + (0x80 * (x)))
#define XGMAC_DMA_CH_TxDESC_TAIL_LPTR(x) (0x00003124 + (0x80 * (x)))
#define XGMAC_DMA_CH_RxDESC_TAIL_LPTR(x) (0x0000312c + (0x80 * (x)))
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index 229c58758cbd..a4f236e3593e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -44,7 +44,7 @@ static void dwxgmac2_dma_init_chan(void __iomem *ioaddr,
static void dwxgmac2_dma_init_rx_chan(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_rx_phy, u32 chan)
+ dma_addr_t phy, u32 chan)
{
u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
u32 value;
@@ -54,12 +54,13 @@ static void dwxgmac2_dma_init_rx_chan(void __iomem *ioaddr,
value |= (rxpbl << XGMAC_RxPBL_SHIFT) & XGMAC_RxPBL;
writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
- writel(dma_rx_phy, ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan));
+ writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan));
+ writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan));
}
static void dwxgmac2_dma_init_tx_chan(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_tx_phy, u32 chan)
+ dma_addr_t phy, u32 chan)
{
u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
u32 value;
@@ -70,7 +71,8 @@ static void dwxgmac2_dma_init_tx_chan(void __iomem *ioaddr,
value |= XGMAC_OSP;
writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
- writel(dma_tx_phy, ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan));
+ writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan));
+ writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan));
}
static void dwxgmac2_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 2acfbc70e3c8..278c0dbec9d9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -150,10 +150,10 @@ struct stmmac_dma_ops {
struct stmmac_dma_cfg *dma_cfg, u32 chan);
void (*init_rx_chan)(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_rx_phy, u32 chan);
+ dma_addr_t phy, u32 chan);
void (*init_tx_chan)(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
- u32 dma_tx_phy, u32 chan);
+ dma_addr_t phy, u32 chan);
/* Configure the AXI Bus Mode Register */
void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi);
/* Dump DMA registers */
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v3 0/3] net: stmmac: Some improvements and a fix
From: Jose Abreu @ 2019-07-05 7:22 UTC (permalink / raw)
To: linux-kernel, netdev, linux-stm32, linux-arm-kernel
Cc: Jose Abreu, Joao Pinto, David S . Miller, Giuseppe Cavallaro,
Alexandre Torgue
Some performace improvements (01/03 and 03/03) and a fix (02/03), all for -next.
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Jose Abreu (3):
net: stmmac: Implement RX Coalesce Frames setting
net: stmmac: Fix descriptors address being in > 32 bits address space
net: stmmac: Introducing support for Page Pool
drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
drivers/net/ethernet/stmicro/stmmac/common.h | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 8 +-
.../net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 8 +-
drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 8 +-
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 8 +-
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 2 +
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 10 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 +-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 12 +-
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 7 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 217 +++++++--------------
12 files changed, 114 insertions(+), 172 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH net-next v3 3/3] net: stmmac: Introducing support for Page Pool
From: Jose Abreu @ 2019-07-05 7:23 UTC (permalink / raw)
To: linux-kernel, netdev, linux-stm32, linux-arm-kernel
Cc: Jose Abreu, Joao Pinto, David S . Miller, Giuseppe Cavallaro,
Alexandre Torgue, Ilias Apalodimas, Jesper Dangaard Brouer,
Arnd Bergmann
In-Reply-To: <cover.1562311299.git.joabreu@synopsys.com>
Mapping and unmapping DMA region is an high bottleneck in stmmac driver,
specially in the RX path.
This commit introduces support for Page Pool API and uses it in all RX
queues. With this change, we get more stable troughput and some increase
of banwidth with iperf:
- MAC1000 - 950 Mbps
- XGMAC: 9.22 Gbps
Changes from v2:
- Uncoditionally call page_pool_free() (Jesper)
Changes from v1:
- Use page_pool_get_dma_addr() (Jesper)
- Add a comment (Jesper)
- Add page_pool_free() call (Jesper)
- Reintroduce sync_single_for_device (Arnd / Ilias)
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jesper Dangaard Brouer <brouer@redhat.com>
Cc: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 10 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 203 +++++++---------------
3 files changed, 70 insertions(+), 144 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 943189dcccb1..2325b40dff6e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -3,6 +3,7 @@ config STMMAC_ETH
tristate "STMicroelectronics Multi-Gigabit Ethernet driver"
depends on HAS_IOMEM && HAS_DMA
select MII
+ select PAGE_POOL
select PHYLINK
select CRC32
imply PTP_1588_CLOCK
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 513f4e2df5f6..5cd966c154f3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -20,6 +20,7 @@
#include <linux/ptp_clock_kernel.h>
#include <linux/net_tstamp.h>
#include <linux/reset.h>
+#include <net/page_pool.h>
struct stmmac_resources {
void __iomem *addr;
@@ -54,14 +55,19 @@ struct stmmac_tx_queue {
u32 mss;
};
+struct stmmac_rx_buffer {
+ struct page *page;
+ dma_addr_t addr;
+};
+
struct stmmac_rx_queue {
u32 rx_count_frames;
u32 queue_index;
+ struct page_pool *page_pool;
+ struct stmmac_rx_buffer *buf_pool;
struct stmmac_priv *priv_data;
struct dma_extended_desc *dma_erx;
struct dma_desc *dma_rx ____cacheline_aligned_in_smp;
- struct sk_buff **rx_skbuff;
- dma_addr_t *rx_skbuff_dma;
unsigned int cur_rx;
unsigned int dirty_rx;
u32 rx_zeroc_thresh;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c8fe85ef9a7e..6566772e8ed5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1197,26 +1197,14 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
int i, gfp_t flags, u32 queue)
{
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
- struct sk_buff *skb;
+ struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
- skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
- if (!skb) {
- netdev_err(priv->dev,
- "%s: Rx init fails; skb is NULL\n", __func__);
+ buf->page = page_pool_dev_alloc_pages(rx_q->page_pool);
+ if (!buf->page)
return -ENOMEM;
- }
- rx_q->rx_skbuff[i] = skb;
- rx_q->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
- priv->dma_buf_sz,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(priv->device, rx_q->rx_skbuff_dma[i])) {
- netdev_err(priv->dev, "%s: DMA mapping error\n", __func__);
- dev_kfree_skb_any(skb);
- return -EINVAL;
- }
-
- stmmac_set_desc_addr(priv, p, rx_q->rx_skbuff_dma[i]);
+ buf->addr = page_pool_get_dma_addr(buf->page);
+ stmmac_set_desc_addr(priv, p, buf->addr);
if (priv->dma_buf_sz == BUF_SIZE_16KiB)
stmmac_init_desc3(priv, p);
@@ -1232,13 +1220,11 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i)
{
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
- if (rx_q->rx_skbuff[i]) {
- dma_unmap_single(priv->device, rx_q->rx_skbuff_dma[i],
- priv->dma_buf_sz, DMA_FROM_DEVICE);
- dev_kfree_skb_any(rx_q->rx_skbuff[i]);
- }
- rx_q->rx_skbuff[i] = NULL;
+ if (buf->page)
+ page_pool_put_page(rx_q->page_pool, buf->page, false);
+ buf->page = NULL;
}
/**
@@ -1321,10 +1307,6 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
queue);
if (ret)
goto err_init_rx_buffers;
-
- netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n",
- rx_q->rx_skbuff[i], rx_q->rx_skbuff[i]->data,
- (unsigned int)rx_q->rx_skbuff_dma[i]);
}
rx_q->cur_rx = 0;
@@ -1498,8 +1480,11 @@ static void free_dma_rx_desc_resources(struct stmmac_priv *priv)
sizeof(struct dma_extended_desc),
rx_q->dma_erx, rx_q->dma_rx_phy);
- kfree(rx_q->rx_skbuff_dma);
- kfree(rx_q->rx_skbuff);
+ kfree(rx_q->buf_pool);
+ if (rx_q->page_pool) {
+ page_pool_request_shutdown(rx_q->page_pool);
+ page_pool_free(rx_q->page_pool);
+ }
}
}
@@ -1551,20 +1536,29 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
/* RX queues buffers and DMA */
for (queue = 0; queue < rx_count; queue++) {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ struct page_pool_params pp_params = { 0 };
rx_q->queue_index = queue;
rx_q->priv_data = priv;
- rx_q->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE,
- sizeof(dma_addr_t),
- GFP_KERNEL);
- if (!rx_q->rx_skbuff_dma)
+ pp_params.flags = PP_FLAG_DMA_MAP;
+ pp_params.pool_size = DMA_RX_SIZE;
+ pp_params.order = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE);
+ pp_params.nid = dev_to_node(priv->device);
+ pp_params.dev = priv->device;
+ pp_params.dma_dir = DMA_FROM_DEVICE;
+
+ rx_q->page_pool = page_pool_create(&pp_params);
+ if (IS_ERR(rx_q->page_pool)) {
+ ret = PTR_ERR(rx_q->page_pool);
+ rx_q->page_pool = NULL;
goto err_dma;
+ }
- rx_q->rx_skbuff = kmalloc_array(DMA_RX_SIZE,
- sizeof(struct sk_buff *),
- GFP_KERNEL);
- if (!rx_q->rx_skbuff)
+ rx_q->buf_pool = kmalloc_array(DMA_RX_SIZE,
+ sizeof(*rx_q->buf_pool),
+ GFP_KERNEL);
+ if (!rx_q->buf_pool)
goto err_dma;
if (priv->extend_desc) {
@@ -3295,9 +3289,8 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
int dirty = stmmac_rx_dirty(priv, queue);
unsigned int entry = rx_q->dirty_rx;
- int bfsize = priv->dma_buf_sz;
-
while (dirty-- > 0) {
+ struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry];
struct dma_desc *p;
bool use_rx_wd;
@@ -3306,49 +3299,22 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
else
p = rx_q->dma_rx + entry;
- if (likely(!rx_q->rx_skbuff[entry])) {
- struct sk_buff *skb;
-
- skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
- if (unlikely(!skb)) {
- /* so for a while no zero-copy! */
- rx_q->rx_zeroc_thresh = STMMAC_RX_THRESH;
- if (unlikely(net_ratelimit()))
- dev_err(priv->device,
- "fail to alloc skb entry %d\n",
- entry);
- break;
- }
-
- rx_q->rx_skbuff[entry] = skb;
- rx_q->rx_skbuff_dma[entry] =
- dma_map_single(priv->device, skb->data, bfsize,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(priv->device,
- rx_q->rx_skbuff_dma[entry])) {
- netdev_err(priv->dev, "Rx DMA map failed\n");
- dev_kfree_skb(skb);
+ if (!buf->page) {
+ buf->page = page_pool_dev_alloc_pages(rx_q->page_pool);
+ if (!buf->page)
break;
- }
-
- stmmac_set_desc_addr(priv, p, rx_q->rx_skbuff_dma[entry]);
- stmmac_refill_desc3(priv, rx_q, p);
-
- if (rx_q->rx_zeroc_thresh > 0)
- rx_q->rx_zeroc_thresh--;
-
- netif_dbg(priv, rx_status, priv->dev,
- "refill entry #%d\n", entry);
}
- dma_wmb();
+
+ buf->addr = page_pool_get_dma_addr(buf->page);
+ stmmac_set_desc_addr(priv, p, buf->addr);
+ stmmac_refill_desc3(priv, rx_q, p);
rx_q->rx_count_frames++;
rx_q->rx_count_frames %= priv->rx_coal_frames;
use_rx_wd = priv->use_riwt && rx_q->rx_count_frames;
- stmmac_set_rx_owner(priv, p, use_rx_wd);
-
dma_wmb();
+ stmmac_set_rx_owner(priv, p, use_rx_wd);
entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE);
}
@@ -3373,9 +3339,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
unsigned int next_entry = rx_q->cur_rx;
int coe = priv->hw->rx_csum;
unsigned int count = 0;
- bool xmac;
-
- xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;
if (netif_msg_rx_status(priv)) {
void *rx_head;
@@ -3389,11 +3352,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
stmmac_display_ring(priv, rx_head, DMA_RX_SIZE, true);
}
while (count < limit) {
+ struct stmmac_rx_buffer *buf;
+ struct dma_desc *np, *p;
int entry, status;
- struct dma_desc *p;
- struct dma_desc *np;
entry = next_entry;
+ buf = &rx_q->buf_pool[entry];
if (priv->extend_desc)
p = (struct dma_desc *)(rx_q->dma_erx + entry);
@@ -3423,20 +3387,9 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
stmmac_rx_extended_status(priv, &priv->dev->stats,
&priv->xstats, rx_q->dma_erx + entry);
if (unlikely(status == discard_frame)) {
+ page_pool_recycle_direct(rx_q->page_pool, buf->page);
priv->dev->stats.rx_errors++;
- if (priv->hwts_rx_en && !priv->extend_desc) {
- /* DESC2 & DESC3 will be overwritten by device
- * with timestamp value, hence reinitialize
- * them in stmmac_rx_refill() function so that
- * device can reuse it.
- */
- dev_kfree_skb_any(rx_q->rx_skbuff[entry]);
- rx_q->rx_skbuff[entry] = NULL;
- dma_unmap_single(priv->device,
- rx_q->rx_skbuff_dma[entry],
- priv->dma_buf_sz,
- DMA_FROM_DEVICE);
- }
+ buf->page = NULL;
} else {
struct sk_buff *skb;
int frame_len;
@@ -3476,58 +3429,20 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
frame_len, status);
}
- /* The zero-copy is always used for all the sizes
- * in case of GMAC4 because it needs
- * to refill the used descriptors, always.
- */
- if (unlikely(!xmac &&
- ((frame_len < priv->rx_copybreak) ||
- stmmac_rx_threshold_count(rx_q)))) {
- skb = netdev_alloc_skb_ip_align(priv->dev,
- frame_len);
- if (unlikely(!skb)) {
- if (net_ratelimit())
- dev_warn(priv->device,
- "packet dropped\n");
- priv->dev->stats.rx_dropped++;
- continue;
- }
-
- dma_sync_single_for_cpu(priv->device,
- rx_q->rx_skbuff_dma
- [entry], frame_len,
- DMA_FROM_DEVICE);
- skb_copy_to_linear_data(skb,
- rx_q->
- rx_skbuff[entry]->data,
- frame_len);
-
- skb_put(skb, frame_len);
- dma_sync_single_for_device(priv->device,
- rx_q->rx_skbuff_dma
- [entry], frame_len,
- DMA_FROM_DEVICE);
- } else {
- skb = rx_q->rx_skbuff[entry];
- if (unlikely(!skb)) {
- if (net_ratelimit())
- netdev_err(priv->dev,
- "%s: Inconsistent Rx chain\n",
- priv->dev->name);
- priv->dev->stats.rx_dropped++;
- continue;
- }
- prefetch(skb->data - NET_IP_ALIGN);
- rx_q->rx_skbuff[entry] = NULL;
- rx_q->rx_zeroc_thresh++;
-
- skb_put(skb, frame_len);
- dma_unmap_single(priv->device,
- rx_q->rx_skbuff_dma[entry],
- priv->dma_buf_sz,
- DMA_FROM_DEVICE);
+ skb = netdev_alloc_skb_ip_align(priv->dev, frame_len);
+ if (unlikely(!skb)) {
+ priv->dev->stats.rx_dropped++;
+ continue;
}
+ dma_sync_single_for_cpu(priv->device, buf->addr,
+ frame_len, DMA_FROM_DEVICE);
+ skb_copy_to_linear_data(skb, page_address(buf->page),
+ frame_len);
+ skb_put(skb, frame_len);
+ dma_sync_single_for_device(priv->device, buf->addr,
+ frame_len, DMA_FROM_DEVICE);
+
if (netif_msg_pktdata(priv)) {
netdev_dbg(priv->dev, "frame received (%dbytes)",
frame_len);
@@ -3547,6 +3462,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
napi_gro_receive(&ch->rx_napi, skb);
+ /* Data payload copied into SKB, page ready for recycle */
+ page_pool_recycle_direct(rx_q->page_pool, buf->page);
+ buf->page = NULL;
+
priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += frame_len;
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v2 0/3] devlink: Introduce PCI PF, VF ports and attributes
From: Parav Pandit @ 2019-07-05 7:37 UTC (permalink / raw)
To: netdev; +Cc: jiri, saeedm, jakub.kicinski, Parav Pandit
In-Reply-To: <20190701122734.18770-1-parav@mellanox.com>
This patchset carry forwards the work initiated in [1] and discussion
futher concluded at [2].
To improve visibility of representor netdevice, its association with
PF or VF, physical port, two new devlink port flavours are added as
PCI PF and PCI VF ports.
A sample eswitch view can be seen below, which will be futher extended to
mdev subdevices of a PCI function in future.
Patch-1,2 extends devlink port attributes and port flavour.
Patch-3 extends mlx5 driver to register devlink ports for PF, VF and
physical link.
+---+ +---+
vf| | | | pf
+-+-+ +-+-+
physical link <---------+ | |
| | |
| | |
+-+-+ +-+-+ +-+-+
| 1 | | 2 | | 3 |
+--+---+-----+---+------+---+--+
| physical vf pf |
| port port port |
| |
| eswitch |
| |
+------------------------------+
[1] https://www.spinics.net/lists/netdev/msg555797.html
[2] https://marc.info/?l=linux-netdev&m=155354609408485&w=2
---
Changelog:
v1->v2:
- Updated new APIs and mlx5 driver to drop port_number for PF, VF
attributes
- Updated port_number comment for its usage
- Limited putting port_number to physical ports
Parav Pandit (3):
devlink: Introduce PCI PF port flavour and port attribute
devlink: Introduce PCI VF port flavour and port attribute
net/mlx5e: Register devlink ports for physical link, PCI PF, VFs
.../net/ethernet/mellanox/mlx5/core/en_rep.c | 108 ++++++++++++-----
.../net/ethernet/mellanox/mlx5/core/en_rep.h | 1 +
include/net/devlink.h | 25 +++-
include/uapi/linux/devlink.h | 11 ++
net/core/devlink.c | 114 +++++++++++++++---
5 files changed, 212 insertions(+), 47 deletions(-)
--
2.19.2
^ 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