Netdev List
 help / color / mirror / Atom feed
* [RFC bpf-next 1/8] bpf: introducing list based insn patching infra to core layer
From: Jiong Wang @ 2019-07-04 21:26 UTC (permalink / raw)
  To: alexei.starovoitov, daniel
  Cc: ecree, naveen.n.rao, andriin, jakub.kicinski, bpf, netdev,
	oss-drivers, Jiong Wang
In-Reply-To: <1562275611-31790-1-git-send-email-jiong.wang@netronome.com>

This patch introduces list based bpf insn patching infra to bpf core layer
which is lower than verification layer.

This layer has bpf insn sequence as the solo input, therefore the tasks
to be finished during list linerization is:
  - copy insn
  - relocate jumps
  - relocation line info.

Suggested-by: Alexei Starovoitov <ast@kernel.org>
Suggested-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: Jiong Wang <jiong.wang@netronome.com>
---
 include/linux/filter.h |  25 +++++
 kernel/bpf/core.c      | 268 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 293 insertions(+)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index 1fe53e7..1fea68c 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -842,6 +842,31 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
 				       const struct bpf_insn *patch, u32 len);
 int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt);
 
+int bpf_jit_adj_imm_off(struct bpf_insn *insn, int old_idx, int new_idx,
+			int idx_map[]);
+
+#define LIST_INSN_FLAG_PATCHED	0x1
+#define LIST_INSN_FLAG_REMOVED	0x2
+struct bpf_list_insn {
+	struct bpf_insn insn;
+	struct bpf_list_insn *next;
+	s32 orig_idx;
+	u32 flag;
+};
+
+struct bpf_list_insn *bpf_create_list_insn(struct bpf_prog *prog);
+void bpf_destroy_list_insn(struct bpf_list_insn *list);
+/* Replace LIST_INSN with new list insns generated from PATCH. */
+struct bpf_list_insn *bpf_patch_list_insn(struct bpf_list_insn *list_insn,
+					  const struct bpf_insn *patch,
+					  u32 len);
+/* Pre-patch list_insn with insns inside PATCH, meaning LIST_INSN is not
+ * touched. New list insns are inserted before it.
+ */
+struct bpf_list_insn *bpf_prepatch_list_insn(struct bpf_list_insn *list_insn,
+					     const struct bpf_insn *patch,
+					     u32 len);
+
 void bpf_clear_redirect_map(struct bpf_map *map);
 
 static inline bool xdp_return_frame_no_direct(void)
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index e2c1b43..e60703e 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -502,6 +502,274 @@ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
 	return WARN_ON_ONCE(bpf_adj_branches(prog, off, off + cnt, off, false));
 }
 
+int bpf_jit_adj_imm_off(struct bpf_insn *insn, int old_idx, int new_idx,
+			s32 idx_map[])
+{
+	u8 code = insn->code;
+	s64 imm;
+	s32 off;
+
+	if (BPF_CLASS(code) != BPF_JMP && BPF_CLASS(code) != BPF_JMP32)
+		return 0;
+
+	if (BPF_CLASS(code) == BPF_JMP &&
+	    (BPF_OP(code) == BPF_EXIT ||
+	     (BPF_OP(code) == BPF_CALL && insn->src_reg != BPF_PSEUDO_CALL)))
+		return 0;
+
+	/* BPF to BPF call. */
+	if (BPF_OP(code) == BPF_CALL) {
+		imm = idx_map[old_idx + insn->imm + 1] - new_idx - 1;
+		if (imm < S32_MIN || imm > S32_MAX)
+			return -ERANGE;
+		insn->imm = imm;
+		return 1;
+	}
+
+	/* Jump. */
+	off = idx_map[old_idx + insn->off + 1] - new_idx - 1;
+	if (off < S16_MIN || off > S16_MAX)
+		return -ERANGE;
+	insn->off = off;
+	return 0;
+}
+
+void bpf_destroy_list_insn(struct bpf_list_insn *list)
+{
+	struct bpf_list_insn *elem, *next;
+
+	for (elem = list; elem; elem = next) {
+		next = elem->next;
+		kvfree(elem);
+	}
+}
+
+struct bpf_list_insn *bpf_create_list_insn(struct bpf_prog *prog)
+{
+	unsigned int idx, len = prog->len;
+	struct bpf_list_insn *hdr, *prev;
+	struct bpf_insn *insns;
+
+	hdr = kvzalloc(sizeof(*hdr), GFP_KERNEL);
+	if (!hdr)
+		return ERR_PTR(-ENOMEM);
+
+	insns = prog->insnsi;
+	hdr->insn = insns[0];
+	hdr->orig_idx = 1;
+	prev = hdr;
+
+	for (idx = 1; idx < len; idx++) {
+		struct bpf_list_insn *node = kvzalloc(sizeof(*node),
+						      GFP_KERNEL);
+
+		if (!node) {
+			/* Destroy what has been allocated. */
+			bpf_destroy_list_insn(hdr);
+			return ERR_PTR(-ENOMEM);
+		}
+		node->insn = insns[idx];
+		node->orig_idx = idx + 1;
+		prev->next = node;
+		prev = node;
+	}
+
+	return hdr;
+}
+
+/* Linearize bpf list insn to array. */
+static struct bpf_prog *bpf_linearize_list_insn(struct bpf_prog *prog,
+						struct bpf_list_insn *list)
+{
+	u32 *idx_map, idx, prev_idx, fini_cnt = 0, orig_cnt = prog->len;
+	struct bpf_insn *insns, *insn;
+	struct bpf_list_insn *elem;
+
+	/* Calculate final size. */
+	for (elem = list; elem; elem = elem->next)
+		if (!(elem->flag & LIST_INSN_FLAG_REMOVED))
+			fini_cnt++;
+
+	insns = prog->insnsi;
+	/* If prog length remains same, nothing else to do. */
+	if (fini_cnt == orig_cnt) {
+		for (insn = insns, elem = list; elem; elem = elem->next, insn++)
+			*insn = elem->insn;
+		return prog;
+	}
+	/* Realloc insn buffer when necessary. */
+	if (fini_cnt > orig_cnt)
+		prog = bpf_prog_realloc(prog, bpf_prog_size(fini_cnt),
+					GFP_USER);
+	if (!prog)
+		return ERR_PTR(-ENOMEM);
+	insns = prog->insnsi;
+	prog->len = fini_cnt;
+
+	/* idx_map[OLD_IDX] = NEW_IDX */
+	idx_map = kvmalloc(orig_cnt * sizeof(u32), GFP_KERNEL);
+	if (!idx_map)
+		return ERR_PTR(-ENOMEM);
+	memset(idx_map, 0xff, orig_cnt * sizeof(u32));
+
+	/* Copy over insn + calculate idx_map. */
+	for (idx = 0, elem = list; elem; elem = elem->next) {
+		int orig_idx = elem->orig_idx - 1;
+
+		if (orig_idx >= 0) {
+			idx_map[orig_idx] = idx;
+
+			if (elem->flag & LIST_INSN_FLAG_REMOVED)
+				continue;
+		}
+		insns[idx++] = elem->insn;
+	}
+
+	/* Relocate jumps using idx_map.
+	 *   old_dst = jmp_insn.old_target + old_pc + 1;
+	 *   new_dst = idx_map[old_dst] = jmp_insn.new_target + new_pc + 1;
+	 *   jmp_insn.new_target = new_dst - new_pc - 1;
+	 */
+	for (idx = 0, prev_idx = 0, elem = list; elem; elem = elem->next) {
+		int ret, orig_idx;
+
+		/* A removed insn doesn't increase new_pc */
+		if (elem->flag & LIST_INSN_FLAG_REMOVED)
+			continue;
+
+		orig_idx = elem->orig_idx - 1;
+		ret = bpf_jit_adj_imm_off(&insns[idx],
+					  orig_idx >= 0 ? orig_idx : prev_idx,
+					  idx, idx_map);
+		idx++;
+		if (ret < 0) {
+			kvfree(idx_map);
+			return ERR_PTR(ret);
+		}
+		if (orig_idx >= 0)
+			/* Record prev_idx. it is used for relocating jump insn
+			 * inside patch buffer. For example, when doing jit
+			 * blinding, a jump could be moved to some other
+			 * positions inside the patch buffer, and its old_dst
+			 * could be calculated using prev_idx.
+			 */
+			prev_idx = orig_idx;
+	}
+
+	/* Adjust linfo.
+	 *
+	 * NOTE: the prog reached core layer has been adjusted to contain insns
+	 *       for single function, however linfo contains information for
+	 *       whole program, so we need to make sure linfo beyond current
+	 *       function is handled properly.
+	 */
+	if (prog->aux->nr_linfo) {
+		u32 linfo_idx, insn_start, insn_end, nr_linfo, idx, delta;
+		struct bpf_line_info *linfo;
+
+		linfo_idx = prog->aux->linfo_idx;
+		linfo = &prog->aux->linfo[linfo_idx];
+		insn_start = linfo[0].insn_off;
+		insn_end = insn_start + orig_cnt;
+		nr_linfo = prog->aux->nr_linfo - linfo_idx;
+		delta = fini_cnt - orig_cnt;
+		for (idx = 0; idx < nr_linfo; idx++) {
+			int adj_off;
+
+			if (linfo[idx].insn_off >= insn_end) {
+				linfo[idx].insn_off += delta;
+				continue;
+			}
+
+			adj_off = linfo[idx].insn_off - insn_start;
+			linfo[idx].insn_off = idx_map[adj_off] + insn_start;
+		}
+	}
+	kvfree(idx_map);
+
+	return prog;
+}
+
+struct bpf_list_insn *bpf_patch_list_insn(struct bpf_list_insn *list_insn,
+					  const struct bpf_insn *patch,
+					  u32 len)
+{
+	struct bpf_list_insn *prev, *next;
+	u32 insn_delta = len - 1;
+	u32 idx;
+
+	list_insn->insn = *patch;
+	list_insn->flag |= LIST_INSN_FLAG_PATCHED;
+
+	/* Since our patchlet doesn't expand the image, we're done. */
+	if (insn_delta == 0)
+		return list_insn;
+
+	len--;
+	patch++;
+
+	prev = list_insn;
+	next = list_insn->next;
+	for (idx = 0; idx < len; idx++) {
+		struct bpf_list_insn *node = kvzalloc(sizeof(*node),
+						      GFP_KERNEL);
+
+		if (!node) {
+			/* Link what's allocated, so list destroyer could
+			 * free them.
+			 */
+			prev->next = next;
+			return ERR_PTR(-ENOMEM);
+		}
+
+		node->insn = patch[idx];
+		prev->next = node;
+		prev = node;
+	}
+
+	prev->next = next;
+	return prev;
+}
+
+struct bpf_list_insn *bpf_prepatch_list_insn(struct bpf_list_insn *list_insn,
+					     const struct bpf_insn *patch,
+					     u32 len)
+{
+	struct bpf_list_insn *prev, *node, *begin_node;
+	u32 idx;
+
+	if (!len)
+		return list_insn;
+
+	node = kvzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
+		return ERR_PTR(-ENOMEM);
+	node->insn = patch[0];
+	begin_node = node;
+	prev = node;
+
+	for (idx = 1; idx < len; idx++) {
+		node = kvzalloc(sizeof(*node), GFP_KERNEL);
+		if (!node) {
+			node = begin_node;
+			/* Release what's has been allocated. */
+			while (node) {
+				struct bpf_list_insn *next = node->next;
+
+				kvfree(node);
+				node = next;
+			}
+			return ERR_PTR(-ENOMEM);
+		}
+		node->insn = patch[idx];
+		prev->next = node;
+		prev = node;
+	}
+
+	prev->next = list_insn;
+	return begin_node;
+}
+
 void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
 {
 	int i;
-- 
2.7.4


^ permalink raw reply related

* [RFC bpf-next 0/8] bpf: accelerate insn patching speed
From: Jiong Wang @ 2019-07-04 21:26 UTC (permalink / raw)
  To: alexei.starovoitov, daniel
  Cc: ecree, naveen.n.rao, andriin, jakub.kicinski, bpf, netdev,
	oss-drivers, Jiong Wang

This is an RFC based on latest bpf-next about acclerating insn patching
speed, it is now near the shape of final PATCH set, and we could see the
changes migrating to list patching would brings, so send out for
comments. Most of the info are in cover letter. I splitted the code in a
way to show API migration more easily.

Test Results
===
  - Full pass on test_verifier/test_prog/test_prog_32 under all three
    modes (interpreter, JIT, JIT with blinding).

  - Benchmarking shows 10 ~ 15x faster on medium sized prog, and reduce
    patching time from 5100s (nearly one and a half hour) to less than
    0.5s for 1M insn patching.

Known Issues
===
  - The following warning is triggered when running scale test which
    contains 1M insns and patching:
      warning of mm/page_alloc.c:4639 __alloc_pages_nodemask+0x29e/0x330

    This is caused by existing code, it can be reproduced on bpf-next
    master with jit blinding enabled, then run scale unit test, it will
    shown up after half an hour. After this set, patching is very fast, so
    it shows up quickly.

  - No line info adjustment support when doing insn delete, subprog adj
    is with bug when doing insn delete as well. Generally, removal of insns
    could possibly cause remove of entire line or subprog, therefore
    entries of prog->aux->linfo or env->subprog needs to be deleted. I
    don't have good idea and clean code for integrating this into the
    linearization code at the moment, will do more experimenting,
    appreciate ideas and suggestions on this.
     
    Insn delete doesn't happen on normal programs, for example Cilium
    benchmarks, and happens rarely on test_progs, so the test coverage is
    not good. That's also why this RFC have a full pass on selftest with
    this known issue.

  - Could further use mem pool to accelerate the speed, changes are trivial
    on top of this RFC, and could be 2x extra faster. Not included in this
    RFC as reducing the algo complexity from quadratic to linear of insn
    number is the first step.

Background
===
This RFC aims to accelerate BPF insn patching speed, patching means expand
one bpf insn at any offset inside bpf prog into a set of new insns, or
remove insns.

At the moment, insn patching is quadratic of insn number, this is due to
branch targets of jump insns needs to be adjusted, and the algo used is:

  for insn inside prog
    patch insn + regeneate bpf prog
    for insn inside new prog
      adjust jump target

This is causing significant time spending when a bpf prog requires large
amount of patching on different insns. Benchmarking shows it could take
more than half minutes to finish patching when patching number is more
than 50K, and the time spent could be more than one hour when patching
number is around 1M.

  15000   :    3s
  45000   :   29s
  95000   :  125s
  195000  :  712s
  1000000 : 5100s

This RFC introduces new patching infrastructure. Before doing insn
patching, insns in bpf prog are turned into a singly linked list, insert
new insns just insert new list node, delete insns just set delete flag.
And finally, the list is linearized back into array, and branch target
adjustment is done for all jump insns during linearization. This algo
brings the time complexity from quadratic to linear of insn number.

Benchmarking shows the new patching infrastructure could be 10 ~ 15x faster
on medium sized prog, and for a 1M patching it reduce the time from 5100s
to less than 0.5s.

Patching API
===
Insn patching could happen on two layers inside BPF. One is "core layer"
where only BPF insns are patched. The other is "verification layer" where
insns have corresponding aux info as well high level subprog info, so
insn patching means aux info needs to be patched as well, and subprog info
needs to be adjusted. BPF prog also has debug info associated, so line info
should always be updated after insn patching.

So, list creation, destroy, insert, delete is the same for both layer,
but lineration is different. "verification layer" patching require extra
work. Therefore the patch APIs are:

   list creation:                bpf_create_list_insn
   list patch:                   bpf_patch_list_insn
   list pre-patch:               bpf_prepatch_list_insn
   list lineration (core layer): prog = bpf_linearize_list_insn(prog, list)
   list lineration (veri layer): env = verifier_linearize_list_insn(env, list)
   list destroy:                 bpf_destroy_list_insn

list patch could change the insn at patch point, it will invalid the aux
info at patching point. list pre-patch insert new insns before patch point
where the insn and associated aux info are not touched, it is used for
example in convert_ctx_access when generating prologue. 

Typical API sequence for one patching pass:

   struct bpf_list_insn list = bpf_create_list_insn(struct bpf_prog);
   for (elem = list; elem; elem = elem->next)
      patch_buf = gen_patch_buf_logic;
      elem = bpf_patch_list_insn(elem, patch_buf, cnt);
   bpf_prog = bpf_linearize_list_insn(list)
   bpf_destroy_list_insn(list)
  
Several patching passes could also share the same list:

   struct bpf_list_insn list = bpf_create_list_insn(struct bpf_prog);
   for (elem = list; elem; elem = elem->next)
      patch_buf = gen_patch_buf_logic1;
      elem = bpf_patch_list_insn(elem, patch_buf, cnt);
   for (elem = list; elem; elem = elem->next)
      patch_buf = gen_patch_buf_logic2;
      elem = bpf_patch_list_insn(elem, patch_buf, cnt);
   bpf_prog = bpf_linearize_list_insn(list)
   bpf_destroy_list_insn(list)

but note new inserted insns int early passes won't have aux info except
zext info. So, if one patch pass requires all aux info updated and
recalculated for all insns including those pathced, it should first
linearize the old list, then re-create the list. The RFC always create and
linearize the list for each migrated patching pass separately.

Compared with old patching code, this new infrastructure has much less core
code, even though the final code has a couple of extra lines but that is
mostly due to for list based infrastructure, we need to do more error
checks, so the list and associated aux data structure could be freed when
errors happens.

Patching Restrictions
===
  - For core layer, the linearization assume no new jumps inside patch buf.
    Currently, the only user of this layer is jit blinding.
  - For verifier layer, there could be new jumps inside patch buf, but
    they should have branch target resolved themselves, meaning new jumps
    doesn't jump to insns out of the patch buf. This is the case for all
    existing verifier layer users.
  - bpf_insn_aux_data for all patched insns including the one at patch
    point are invalidated, only 32-bit zext info will be recalcuated.
    If the aux data of insn at patch point needs to be retained, it is
    purely insn insertion, so need to use the pre-patch API.

I plan to send out a PATCH set once I finished insn deletion line info adj
support, please have a looks at this RFC, and appreciate feedbacks.

Jiong Wang (8):
  bpf: introducing list based insn patching infra to core layer
  bpf: extend list based insn patching infra to verification layer
  bpf: migrate jit blinding to list patching infra
  bpf: migrate convert_ctx_accesses to list patching infra
  bpf: migrate fixup_bpf_calls to list patching infra
  bpf: migrate zero extension opt to list patching infra
  bpf: migrate insn remove to list patching infra
  bpf: delete all those code around old insn patching infrastructure

 include/linux/bpf_verifier.h |   1 -
 include/linux/filter.h       |  27 +-
 kernel/bpf/core.c            | 431 +++++++++++++++++-----------
 kernel/bpf/verifier.c        | 649 +++++++++++++++++++------------------------
 4 files changed, 580 insertions(+), 528 deletions(-)

-- 
2.7.4


^ permalink raw reply

* Re: [PATCH net-next 0/2] Mellanox, mlx5 devlink versions query
From: Saeed Mahameed @ 2019-07-04 20:54 UTC (permalink / raw)
  To: David Miller; +Cc: Saeed Mahameed, Linux Netdev List
In-Reply-To: <20190704.135005.2091981554195496315.davem@davemloft.net>

On Thu, Jul 4, 2019 at 4:50 PM David Miller <davem@davemloft.net> wrote:
>
> From: Saeed Mahameed <saeedm@dev.mellanox.co.il>
> Date: Wed, 3 Jul 2019 16:07:11 -0700
>
> > Or just  wait for my next pull request.
>
> Please resubmit this series once I pull your pull request in.
>

Done just submitted:
"[pull request][net-next V2 0/2] Mellanox, mlx5 updates 2019-07-04"
it includes both of the dependencies and the 2 mlx5 devlink fw version patches.

> Thanks.

^ permalink raw reply

* [net-next V2 2/2] net/mlx5: Added devlink info callback
From: Saeed Mahameed @ 2019-07-04 20:51 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev@vger.kernel.org, Tariq Toukan, Shay Agroskin,
	Jakub Kicinski, Saeed Mahameed
In-Reply-To: <20190704205050.3354-1-saeedm@mellanox.com>

From: Shay Agroskin <shayag@mellanox.com>

The callback is invoked using 'devlink dev info <pci>' command and returns
the running and pending firmware version of the HCA and the name of the
kernel driver.

If there is a pending firmware version (a new version is burned but the
HCA still runs with the previous) it is returned as the stored
firmware version. Otherwise, the running version is returned for this
field.

Output example:
$ devlink dev info pci/0000:00:06.0
pci/0000:00:06.0:
  driver mlx5_core
  versions:
      fixed:
        fw.psid MT_0000000009
      running:
        fw.version 16.26.0100
      stored:
        fw.version 16.26.0100

Signed-off-by: Shay Agroskin <shayag@mellanox.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 .../device_drivers/mellanox/mlx5.rst          | 19 ++++++
 .../net/ethernet/mellanox/mlx5/core/devlink.c | 60 +++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/Documentation/networking/device_drivers/mellanox/mlx5.rst b/Documentation/networking/device_drivers/mellanox/mlx5.rst
index 4eeef2df912f..214325897732 100644
--- a/Documentation/networking/device_drivers/mellanox/mlx5.rst
+++ b/Documentation/networking/device_drivers/mellanox/mlx5.rst
@@ -10,6 +10,7 @@ Contents
 ========
 
 - `Enabling the driver and kconfig options`_
+- `Devlink info`_
 - `Devlink health reporters`_
 
 Enabling the driver and kconfig options
@@ -101,6 +102,24 @@ Enabling the driver and kconfig options
 - CONFIG_VXLAN: When chosen, mlx5 vxaln support will be enabled.
 - CONFIG_MLXFW: When chosen, mlx5 firmware flashing support will be enabled (via devlink and ethtool).
 
+Devlink info
+============
+
+The devlink info reports the running and stored firmware versions on device.
+It also prints the device PSID which represents the HCA board type ID.
+
+User command example::
+
+   $ devlink dev info pci/0000:00:06.0
+      pci/0000:00:06.0:
+      driver mlx5_core
+      versions:
+         fixed:
+            fw.psid MT_0000000009
+         running:
+            fw.version 16.26.0100
+         stored:
+            fw.version 16.26.0100
 
 Devlink health reporters
 ========================
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
index 1533c657220b..a400f4430c28 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -25,6 +25,65 @@ static int mlx5_devlink_flash_update(struct devlink *devlink,
 	return mlx5_firmware_flash(dev, fw, extack);
 }
 
+static u8 mlx5_fw_ver_major(u32 version)
+{
+	return (version >> 24) & 0xff;
+}
+
+static u8 mlx5_fw_ver_minor(u32 version)
+{
+	return (version >> 16) & 0xff;
+}
+
+static u16 mlx5_fw_ver_subminor(u32 version)
+{
+	return version & 0xffff;
+}
+
+#define DEVLINK_FW_STRING_LEN 32
+
+static int
+mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
+		      struct netlink_ext_ack *extack)
+{
+	struct mlx5_core_dev *dev = devlink_priv(devlink);
+	char version_str[DEVLINK_FW_STRING_LEN];
+	u32 running_fw, stored_fw;
+	int err;
+
+	err = devlink_info_driver_name_put(req, DRIVER_NAME);
+	if (err)
+		return err;
+
+	err = devlink_info_version_fixed_put(req, "fw.psid", dev->board_id);
+	if (err)
+		return err;
+
+	err = mlx5_fw_version_query(dev, &running_fw, &stored_fw);
+	if (err)
+		return err;
+
+	snprintf(version_str, sizeof(version_str), "%d.%d.%04d",
+		 mlx5_fw_ver_major(running_fw), mlx5_fw_ver_minor(running_fw),
+		 mlx5_fw_ver_subminor(running_fw));
+	err = devlink_info_version_running_put(req, "fw.version", version_str);
+	if (err)
+		return err;
+
+	/* no pending version, return running (stored) version */
+	if (stored_fw == 0)
+		stored_fw = running_fw;
+
+	snprintf(version_str, sizeof(version_str), "%d.%d.%04d",
+		 mlx5_fw_ver_major(stored_fw), mlx5_fw_ver_minor(stored_fw),
+		 mlx5_fw_ver_subminor(stored_fw));
+	err = devlink_info_version_stored_put(req, "fw.version", version_str);
+	if (err)
+		return err;
+
+	return 0;
+}
+
 static const struct devlink_ops mlx5_devlink_ops = {
 #ifdef CONFIG_MLX5_ESWITCH
 	.eswitch_mode_set = mlx5_devlink_eswitch_mode_set,
@@ -35,6 +94,7 @@ static const struct devlink_ops mlx5_devlink_ops = {
 	.eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get,
 #endif
 	.flash_update = mlx5_devlink_flash_update,
+	.info_get = mlx5_devlink_info_get,
 };
 
 struct devlink *mlx5_devlink_alloc(void)
-- 
2.21.0


^ permalink raw reply related

* [net-next V2 1/2] net/mlx5: Added fw version query command
From: Saeed Mahameed @ 2019-07-04 20:51 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev@vger.kernel.org, Tariq Toukan, Shay Agroskin,
	Jakub Kicinski, Saeed Mahameed
In-Reply-To: <20190704205050.3354-1-saeedm@mellanox.com>

From: Shay Agroskin <shayag@mellanox.com>

Using the MCQI and MCQS registers, we query the running and pending
fw version of the HCA.
The MCQS is queried with sequentially increasing component index, until
a component of type BOOT_IMG is found. Querying this component's version
using the MCQI register yields the running and pending fw version of the
HCA.

Querying MCQI for the pending fw version should be done only after
validating that such fw version exists. This is done my checking
'component update state' field in MCQS output.

Signed-off-by: Shay Agroskin <shayag@mellanox.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/fw.c  | 219 ++++++++++++++++--
 .../ethernet/mellanox/mlx5/core/mlx5_core.h   |   2 +
 2 files changed, 201 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
index 6452b62eff15..eb9680293b06 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
@@ -37,6 +37,37 @@
 #include "mlx5_core.h"
 #include "../../mlxfw/mlxfw.h"
 
+enum {
+	MCQS_IDENTIFIER_BOOT_IMG	= 0x1,
+	MCQS_IDENTIFIER_OEM_NVCONFIG	= 0x4,
+	MCQS_IDENTIFIER_MLNX_NVCONFIG	= 0x5,
+	MCQS_IDENTIFIER_CS_TOKEN	= 0x6,
+	MCQS_IDENTIFIER_DBG_TOKEN	= 0x7,
+	MCQS_IDENTIFIER_GEARBOX		= 0xA,
+};
+
+enum {
+	MCQS_UPDATE_STATE_IDLE,
+	MCQS_UPDATE_STATE_IN_PROGRESS,
+	MCQS_UPDATE_STATE_APPLIED,
+	MCQS_UPDATE_STATE_ACTIVE,
+	MCQS_UPDATE_STATE_ACTIVE_PENDING_RESET,
+	MCQS_UPDATE_STATE_FAILED,
+	MCQS_UPDATE_STATE_CANCELED,
+	MCQS_UPDATE_STATE_BUSY,
+};
+
+enum {
+	MCQI_INFO_TYPE_CAPABILITIES	  = 0x0,
+	MCQI_INFO_TYPE_VERSION		  = 0x1,
+	MCQI_INFO_TYPE_ACTIVATION_METHOD  = 0x5,
+};
+
+enum {
+	MCQI_FW_RUNNING_VERSION = 0,
+	MCQI_FW_STORED_VERSION  = 1,
+};
+
 static int mlx5_cmd_query_adapter(struct mlx5_core_dev *dev, u32 *out,
 				  int outlen)
 {
@@ -398,33 +429,49 @@ static int mlx5_reg_mcda_set(struct mlx5_core_dev *dev,
 }
 
 static int mlx5_reg_mcqi_query(struct mlx5_core_dev *dev,
-			       u16 component_index,
-			       u32 *max_component_size,
-			       u8 *log_mcda_word_size,
-			       u16 *mcda_max_write_size)
+			       u16 component_index, bool read_pending,
+			       u8 info_type, u16 data_size, void *mcqi_data)
 {
-	u32 out[MLX5_ST_SZ_DW(mcqi_reg) + MLX5_ST_SZ_DW(mcqi_cap)];
-	int offset = MLX5_ST_SZ_DW(mcqi_reg);
-	u32 in[MLX5_ST_SZ_DW(mcqi_reg)];
+	u32 out[MLX5_ST_SZ_DW(mcqi_reg) + MLX5_UN_SZ_DW(mcqi_reg_data)] = {};
+	u32 in[MLX5_ST_SZ_DW(mcqi_reg)] = {};
+	void *data;
 	int err;
 
-	memset(in, 0, sizeof(in));
-	memset(out, 0, sizeof(out));
-
 	MLX5_SET(mcqi_reg, in, component_index, component_index);
-	MLX5_SET(mcqi_reg, in, data_size, MLX5_ST_SZ_BYTES(mcqi_cap));
+	MLX5_SET(mcqi_reg, in, read_pending_component, read_pending);
+	MLX5_SET(mcqi_reg, in, info_type, info_type);
+	MLX5_SET(mcqi_reg, in, data_size, data_size);
 
 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
-				   sizeof(out), MLX5_REG_MCQI, 0, 0);
+				   MLX5_ST_SZ_BYTES(mcqi_reg) + data_size,
+				   MLX5_REG_MCQI, 0, 0);
 	if (err)
-		goto out;
+		return err;
 
-	*max_component_size = MLX5_GET(mcqi_cap, out + offset, max_component_size);
-	*log_mcda_word_size = MLX5_GET(mcqi_cap, out + offset, log_mcda_word_size);
-	*mcda_max_write_size = MLX5_GET(mcqi_cap, out + offset, mcda_max_write_size);
+	data = MLX5_ADDR_OF(mcqi_reg, out, data);
+	memcpy(mcqi_data, data, data_size);
 
-out:
-	return err;
+	return 0;
+}
+
+static int mlx5_reg_mcqi_caps_query(struct mlx5_core_dev *dev, u16 component_index,
+				    u32 *max_component_size, u8 *log_mcda_word_size,
+				    u16 *mcda_max_write_size)
+{
+	u32 mcqi_reg[MLX5_ST_SZ_DW(mcqi_cap)] = {};
+	int err;
+
+	err = mlx5_reg_mcqi_query(dev, component_index, 0,
+				  MCQI_INFO_TYPE_CAPABILITIES,
+				  MLX5_ST_SZ_BYTES(mcqi_cap), mcqi_reg);
+	if (err)
+		return err;
+
+	*max_component_size = MLX5_GET(mcqi_cap, mcqi_reg, max_component_size);
+	*log_mcda_word_size = MLX5_GET(mcqi_cap, mcqi_reg, log_mcda_word_size);
+	*mcda_max_write_size = MLX5_GET(mcqi_cap, mcqi_reg, mcda_max_write_size);
+
+	return 0;
 }
 
 struct mlx5_mlxfw_dev {
@@ -440,8 +487,13 @@ static int mlx5_component_query(struct mlxfw_dev *mlxfw_dev,
 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
 
-	return mlx5_reg_mcqi_query(dev, component_index, p_max_size,
-				   p_align_bits, p_max_write_size);
+	if (!MLX5_CAP_GEN(dev, mcam_reg) || !MLX5_CAP_MCAM_REG(dev, mcqi)) {
+		mlx5_core_warn(dev, "caps query isn't supported by running FW\n");
+		return -EOPNOTSUPP;
+	}
+
+	return mlx5_reg_mcqi_caps_query(dev, component_index, p_max_size,
+					p_align_bits, p_max_write_size);
 }
 
 static int mlx5_fsm_lock(struct mlxfw_dev *mlxfw_dev, u32 *fwhandle)
@@ -581,3 +633,130 @@ int mlx5_firmware_flash(struct mlx5_core_dev *dev,
 	return mlxfw_firmware_flash(&mlx5_mlxfw_dev.mlxfw_dev,
 				    firmware, extack);
 }
+
+static int mlx5_reg_mcqi_version_query(struct mlx5_core_dev *dev,
+				       u16 component_index, bool read_pending,
+				       u32 *mcqi_version_out)
+{
+	return mlx5_reg_mcqi_query(dev, component_index, read_pending,
+				   MCQI_INFO_TYPE_VERSION,
+				   MLX5_ST_SZ_BYTES(mcqi_version),
+				   mcqi_version_out);
+}
+
+static int mlx5_reg_mcqs_query(struct mlx5_core_dev *dev, u32 *out,
+			       u16 component_index)
+{
+	u8 out_sz = MLX5_ST_SZ_BYTES(mcqs_reg);
+	u32 in[MLX5_ST_SZ_DW(mcqs_reg)] = {};
+	int err;
+
+	memset(out, 0, out_sz);
+
+	MLX5_SET(mcqs_reg, in, component_index, component_index);
+
+	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+				   out_sz, MLX5_REG_MCQS, 0, 0);
+	return err;
+}
+
+/* scans component index sequentially, to find the boot img index */
+static int mlx5_get_boot_img_component_index(struct mlx5_core_dev *dev)
+{
+	u32 out[MLX5_ST_SZ_DW(mcqs_reg)] = {};
+	u16 identifier, component_idx = 0;
+	bool quit;
+	int err;
+
+	do {
+		err = mlx5_reg_mcqs_query(dev, out, component_idx);
+		if (err)
+			return err;
+
+		identifier = MLX5_GET(mcqs_reg, out, identifier);
+		quit = !!MLX5_GET(mcqs_reg, out, last_index_flag);
+		quit |= identifier == MCQS_IDENTIFIER_BOOT_IMG;
+	} while (!quit && ++component_idx);
+
+	if (identifier != MCQS_IDENTIFIER_BOOT_IMG) {
+		mlx5_core_warn(dev, "mcqs: can't find boot_img component ix, last scanned idx %d\n",
+			       component_idx);
+		return -EOPNOTSUPP;
+	}
+
+	return component_idx;
+}
+
+static int
+mlx5_fw_image_pending(struct mlx5_core_dev *dev,
+		      int component_index,
+		      bool *pending_version_exists)
+{
+	u32 out[MLX5_ST_SZ_DW(mcqs_reg)];
+	u8 component_update_state;
+	int err;
+
+	err = mlx5_reg_mcqs_query(dev, out, component_index);
+	if (err)
+		return err;
+
+	component_update_state = MLX5_GET(mcqs_reg, out, component_update_state);
+
+	if (component_update_state == MCQS_UPDATE_STATE_IDLE) {
+		*pending_version_exists = false;
+	} else if (component_update_state == MCQS_UPDATE_STATE_ACTIVE_PENDING_RESET) {
+		*pending_version_exists = true;
+	} else {
+		mlx5_core_warn(dev,
+			       "mcqs: can't read pending fw version while fw state is %d\n",
+			       component_update_state);
+		return -ENODATA;
+	}
+	return 0;
+}
+
+int mlx5_fw_version_query(struct mlx5_core_dev *dev,
+			  u32 *running_ver, u32 *pending_ver)
+{
+	u32 reg_mcqi_version[MLX5_ST_SZ_DW(mcqi_version)] = {};
+	bool pending_version_exists;
+	int component_index;
+	int err;
+
+	if (!MLX5_CAP_GEN(dev, mcam_reg) || !MLX5_CAP_MCAM_REG(dev, mcqi) ||
+	    !MLX5_CAP_MCAM_REG(dev, mcqs)) {
+		mlx5_core_warn(dev, "fw query isn't supported by the FW\n");
+		return -EOPNOTSUPP;
+	}
+
+	component_index = mlx5_get_boot_img_component_index(dev);
+	if (component_index < 0)
+		return component_index;
+
+	err = mlx5_reg_mcqi_version_query(dev, component_index,
+					  MCQI_FW_RUNNING_VERSION,
+					  reg_mcqi_version);
+	if (err)
+		return err;
+
+	*running_ver = MLX5_GET(mcqi_version, reg_mcqi_version, version);
+
+	err = mlx5_fw_image_pending(dev, component_index, &pending_version_exists);
+	if (err)
+		return err;
+
+	if (!pending_version_exists) {
+		*pending_ver = 0;
+		return 0;
+	}
+
+	err = mlx5_reg_mcqi_version_query(dev, component_index,
+					  MCQI_FW_STORED_VERSION,
+					  reg_mcqi_version);
+	if (err)
+		return err;
+
+	*pending_ver = MLX5_GET(mcqi_version, reg_mcqi_version, version);
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 958769702823..471bbc48bc1f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -205,6 +205,8 @@ int mlx5_set_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 arm, u8 mode);
 
 int mlx5_firmware_flash(struct mlx5_core_dev *dev, const struct firmware *fw,
 			struct netlink_ext_ack *extack);
+int mlx5_fw_version_query(struct mlx5_core_dev *dev,
+			  u32 *running_ver, u32 *stored_ver);
 
 void mlx5e_init(void);
 void mlx5e_cleanup(void);
-- 
2.21.0


^ permalink raw reply related

* [pull request][net-next V2 0/2] Mellanox, mlx5 updates 2019-07-04
From: Saeed Mahameed @ 2019-07-04 20:51 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev@vger.kernel.org, Tariq Toukan, Saeed Mahameed

Hi Dave,

This series adds the support for devlink fw query in mlx5

Please pull and let me know if there is any problem.

Please note that the series starts with a merge of mlx5-next branch,
to resolve and avoid dependency with rdma tree.
This what was actually missing from my previous submission of the 2
devlink patches.

v1->v2:
  - Removed the TLS patches from the pull request and will post them as a
    standalone series for Jakub to review.

Thanks,
Saeed.

---
The following changes since commit e08a976a16cafc20931db1d17aed9183202bfa8d:

  Merge branch 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux (2019-07-04 16:42:59 -0400)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux.git tags/mlx5-updates-2019-07-04-v2

for you to fetch changes up to 8338d93788950e63d12bd1d5eb09e239550e80e9:

  net/mlx5: Added devlink info callback (2019-07-04 16:43:16 -0400)

----------------------------------------------------------------
mlx5-update-2019-07-04

This series adds mlx5 support for devlink fw versions query.

1) Implement the required low level firmware commands
2) Implement the devlink knobs and callbacks for fw versions query.

----------------------------------------------------------------
Shay Agroskin (2):
      net/mlx5: Added fw version query command
      net/mlx5: Added devlink info callback

 .../networking/device_drivers/mellanox/mlx5.rst    |  19 ++
 drivers/net/ethernet/mellanox/mlx5/core/devlink.c  |  60 ++++++
 drivers/net/ethernet/mellanox/mlx5/core/fw.c       | 219 +++++++++++++++++++--
 .../net/ethernet/mellanox/mlx5/core/mlx5_core.h    |   2 +
 4 files changed, 280 insertions(+), 20 deletions(-)

^ permalink raw reply

* Re: [net-next 05/14] net/mlx5: Add crypto library to support create/destroy encryption key
From: Jakub Kicinski @ 2019-07-04 20:50 UTC (permalink / raw)
  To: Saeed Mahameed
  Cc: David S. Miller, netdev@vger.kernel.org, Tariq Toukan,
	Eran Ben Elisha
In-Reply-To: <20190704181235.8966-6-saeedm@mellanox.com>

On Thu, 4 Jul 2019 18:15:55 +0000, Saeed Mahameed wrote:
> +	/* avoid leaking key on the stack */
> +	memset(in, 0, sizeof(in));

memzero_explicit() ?

^ permalink raw reply

* Re: [PATCH net-next 0/2] Mellanox, mlx5 devlink versions query
From: David Miller @ 2019-07-04 20:50 UTC (permalink / raw)
  To: saeedm; +Cc: saeedm, netdev
In-Reply-To: <CALzJLG97wQ8EE+XwuCO-wuS0YcYQmSfzu12TFJupp3AAg76U=w@mail.gmail.com>

From: Saeed Mahameed <saeedm@dev.mellanox.co.il>
Date: Wed, 3 Jul 2019 16:07:11 -0700

> Or just  wait for my next pull request.

Please resubmit this series once I pull your pull request in.

Thanks.

^ permalink raw reply

* Re: pull-request: bpf-next 2019-07-03
From: David Miller @ 2019-07-04 20:49 UTC (permalink / raw)
  To: daniel; +Cc: ast, saeedm, netdev, bpf
In-Reply-To: <20190703224740.15354-1-daniel@iogearbox.net>

From: Daniel Borkmann <daniel@iogearbox.net>
Date: Thu,  4 Jul 2019 00:47:40 +0200

> The following pull-request contains BPF updates for your *net-next* tree.
> 
> There is a minor merge conflict in mlx5 due to 8960b38932be ("linux/dim:
> Rename externally used net_dim members") which has been pulled into your
> tree in the meantime, but resolution seems not that bad ... getting current
> bpf-next out now before there's coming more on mlx5. ;) I'm Cc'ing Saeed
> just so he's aware of the resolution below:
 ...

Thanks for the detailed merge resolution guidance, it helps a lot.

> Let me know if you run into any issues. Anyway, the main changes are:
 ...
> Please consider pulling these changes from:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git

Pulled.

^ permalink raw reply

* Re: [net-next 14/14] net/mlx5e: Add kTLS TX HW offload support
From: Jakub Kicinski @ 2019-07-04 20:45 UTC (permalink / raw)
  To: Saeed Mahameed
  Cc: Saeed Mahameed, David S. Miller, netdev@vger.kernel.org,
	Tariq Toukan, Eran Ben Elisha, Boris Pismenny
In-Reply-To: <CALzJLG_qF=Yv58_EpV0bRm8_=Kn2AtsOywDDMjhwxSUOW44EAQ@mail.gmail.com>

On Thu, 4 Jul 2019 16:30:21 -0400, Saeed Mahameed wrote:
> > > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_drop_no_sync_data) },
> > > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_drop_bypass_req) },
> > > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_dump_bytes) },
> > > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_dump_packets) },
> > > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_enc_packets) },
> > > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_enc_bytes) },
> > > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ctx) },
> > >  #endif
> > >
> > >       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_lro_packets) },  
> >
> > Dave, please don't apply this, I will review in depth once I get
> > through the earlier 200 emails ;)  
> 
> Jakub can you please expedite ?

Sure thing!  Looking now..

> Dave if it is ok with you i will re-spin and push a  new pull request
> with  mlx5-next dependencies + 2 Devlink fw version patches,
> and independently, i will post the TLS series for Jakub to review ?

^ permalink raw reply

* Re: [PATCH 6/7] nfp: Use spinlock_t instead of struct spinlock
From: Jakub Kicinski @ 2019-07-04 20:42 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: LKML, tglx, Peter Zijlstra, David S. Miller, OSS Drivers,
	Linux Netdev List
In-Reply-To: <20190704153803.12739-7-bigeasy@linutronix.de>

On Thu,  4 Jul 2019 17:38:02 +0200, Sebastian Andrzej Siewior wrote:
> For spinlocks the type spinlock_t should be used instead of "struct
> spinlock".
>
> Use spinlock_t for spinlock's definition.
>
> Cc: Jakub Kicinski <jakub.kicinski@netronome.com>

Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>


> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: oss-drivers@netronome.com
> Cc: netdev@vger.kernel.org
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  drivers/net/ethernet/netronome/nfp/nfp_net.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
> index df9aff2684ed0..4690363fc5421 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
> +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
> @@ -392,7 +392,7 @@ struct nfp_net_r_vector {
>               struct {
>                       struct tasklet_struct tasklet;
>                       struct sk_buff_head queue;
> -                     struct spinlock lock;
> +                     spinlock_t lock;
>               };
>       };
>

^ permalink raw reply

* Re: [PATCH] tools bpftool: Fix json dump crash on powerpc
From: Jakub Kicinski @ 2019-07-04 20:42 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Michael Petlan, netdev, bpf,
	Martin KaFai Lau
In-Reply-To: <20190704085856.17502-1-jolsa@kernel.org>

On Thu,  4 Jul 2019 10:58:56 +0200, Jiri Olsa wrote:
> Michael reported crash with by bpf program in json mode on powerpc:
> 
>   # bpftool prog -p dump jited id 14
>   [{
>         "name": "0xd00000000a9aa760",
>         "insns": [{
>                 "pc": "0x0",
>                 "operation": "nop",
>                 "operands": [null
>                 ]
>             },{
>                 "pc": "0x4",
>                 "operation": "nop",
>                 "operands": [null
>                 ]
>             },{
>                 "pc": "0x8",
>                 "operation": "mflr",
>   Segmentation fault (core dumped)
> 
> The code is assuming char pointers in format, which is not always
> true at least for powerpc. Fixing this by dumping the whole string
> into buffer based on its format.
> 
> Please note that libopcodes code does not check return values from
> fprintf callback, so there's no point to return error in case of
> allocation failure.

Well, it doesn't check it today, it may perhaps do it in the future?
Let's flip the question - since it doesn't check it today, why not
propagate the error? :)  We should stay close to how fprintf would
behave, IMHO.

Fixes: 107f041212c1 ("tools: bpftool: add JSON output for `bpftool prog dump jited *` command")

> Reported-by: Michael Petlan <mpetlan@redhat.com>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>

^ permalink raw reply

* Re: [net-next 14/14] net/mlx5e: Add kTLS TX HW offload support
From: Saeed Mahameed @ 2019-07-04 20:30 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Saeed Mahameed, David S. Miller, netdev@vger.kernel.org,
	Tariq Toukan, Eran Ben Elisha, Boris Pismenny
In-Reply-To: <20190704131237.239bfa56@cakuba.netronome.com>

On Thu, Jul 4, 2019 at 4:12 PM Jakub Kicinski
<jakub.kicinski@netronome.com> wrote:
>
> On Thu, 4 Jul 2019 18:16:15 +0000, Saeed Mahameed wrote:
> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> > index 483d321d2151..6854f132d505 100644
> > --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> > @@ -50,6 +50,15 @@ static const struct counter_desc sw_stats_desc[] = {
> >  #ifdef CONFIG_MLX5_EN_TLS
> >       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ooo) },
> >       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_resync_bytes) },
> > +
> > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo) },
>
> Why do you call this stat tx_ktls_ooo, and not tx_tls_ooo (extra 'k')?
>
> For nfp I used the stats' names from mlx5 FPGA to make sure we are all
> consistent.  I've added them to the tls-offload.rst doc and Boris has
> reviewed it.
>
>  * ``rx_tls_decrypted`` - number of successfully decrypted TLS segments
>  * ``tx_tls_encrypted`` - number of in-order TLS segments passed to device
>    for encryption
>  * ``tx_tls_ooo`` - number of TX packets which were part of a TLS stream
>    but did not arrive in the expected order
>  * ``tx_tls_drop_no_sync_data`` - number of TX packets dropped because
>    they arrived out of order and associated record could not be found
>
> Why can't you use the same names for the stats as you used for your mlx5
> FPGA?
>

Actually i agree here, I asked tariq to have FPGA TLS and new mlx5
embedded TLS  mutually exclusive.
so there shouldn't be any reason to have new counter names for non FPGA tls.

> > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_drop_no_sync_data) },
> > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_drop_bypass_req) },
> > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_dump_bytes) },
> > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_dump_packets) },
> > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_enc_packets) },
> > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_enc_bytes) },
> > +     { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ctx) },
> >  #endif
> >
> >       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_lro_packets) },
>
> Dave, please don't apply this, I will review in depth once I get
> through the earlier 200 emails ;)

Jakub can you please expedite ?
Dave if it is ok with you i will re-spin and push a  new pull request
with  mlx5-next dependencies + 2 Devlink fw version patches,
and independently, i will post the TLS series for Jakub to review ?

^ permalink raw reply

* Re: [PATCH v2 net-next 3/3] tc-testing: introduce scapyPlugin for basic traffic
From: Alexander Aring @ 2019-07-04 20:29 UTC (permalink / raw)
  To: Lucas Bates
  Cc: davem, netdev, jhs, xiyou.wangcong, jiri, mleitner, vladbu,
	dcaratti, kernel
In-Reply-To: <1562201102-4332-4-git-send-email-lucasb@mojatatu.com>

Hi,

On Wed, Jul 03, 2019 at 08:45:02PM -0400, Lucas Bates wrote:
> The scapyPlugin allows for simple traffic generation in tdc to
> test various tc features. It was tested with scapy v2.4.2, but
> should work with any successive version.
> 
> In order to use the plugin's functionality, scapy must be
> installed. This can be done with:
>    pip3 install scapy
> 
> or to install 2.4.2:
>    pip3 install scapy==2.4.2
> 
> If the plugin is unable to import the scapy module, it will
> terminate the tdc run.
> 
> The plugin makes use of a new key in the test case data, 'scapy'.
> This block contains three other elements: 'iface', 'count', and
> 'packet':
> 
>         "scapy": {
>             "iface": "$DEV0",
>             "count": 1,
>             "packet": "Ether(type=0x800)/IP(src='16.61.16.61')/ICMP()"
>         },
> 
> * iface is the name of the device on the host machine from which
>   the packet(s) will be sent. Values contained within tdc_config.py's
>   NAMES dict can be used here - this is useful if paired with
>   nsPlugin
> * count is the number of copies of this packet to be sent
> * packet is a string detailing the different layers of the packet
>   to be sent. If a property isn't explicitly set, scapy will set
>   default values for you.
> 
> Layers in the packet info are separated by slashes. For info about
> common TCP and IP properties, see:
> https://blogs.sans.org/pen-testing/files/2016/04/ScapyCheatSheet_v0.2.pdf
> 
> Caution is advised when running tests using the scapy functionality,
> since the plugin blindly sends the packet as defined in the test case
> data.
> 
> See creating-testcases/scapy-example.json for sample test cases;
> the first test is intended to pass while the second is intended to
> fail. Consider using the matchJSON functionality for verification
> when using scapy.
> 

Is there a way to introduce thrid party scapy level descriptions which
are not upstream yet?

- Alex

^ permalink raw reply

* Re: [PATCH v2 4/4] net: dsa: vsc73xx: Assert reset if iCPU is enabled
From: Florian Fainelli @ 2019-07-04 20:27 UTC (permalink / raw)
  To: Pawel Dembicki
  Cc: linus.walleij, Andrew Lunn, Vivien Didelot, David S. Miller,
	Rob Herring, Mark Rutland, netdev, devicetree, linux-kernel
In-Reply-To: <20190703171924.31801-5-paweldembicki@gmail.com>



On 7/3/2019 10:19 AM, Pawel Dembicki wrote:
> Driver allow to use devices with disabled iCPU only.
> 
> Some devices have pre-initialised iCPU by bootloader.
> That state make switch unmanaged. This patch force reset
> if device is in unmanaged state. In the result chip lost
> internal firmware from RAM and it can be managed.
> 
> Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
> ---

[snip]

> @@ -1158,6 +1143,19 @@ int vsc73xx_probe(struct vsc73xx *vsc)
>  		msleep(20);
>  
>  	ret = vsc73xx_detect(vsc);
> +	if (ret == -EAGAIN) {
> +		dev_err(vsc->dev,
> +			"Chip seams to be out of control. Assert reset and try again.\n");
> +		gpiod_set_value_cansleep(vsc->reset, 1);

s/seams/seems/

With that fixed:

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply

* Re: [PATCH v2 2/4] net: dsa: vsc73xx: Split vsc73xx driver
From: Florian Fainelli @ 2019-07-04 20:24 UTC (permalink / raw)
  To: Pawel Dembicki
  Cc: linus.walleij, Andrew Lunn, Vivien Didelot, David S. Miller,
	Rob Herring, Mark Rutland, netdev, devicetree, linux-kernel
In-Reply-To: <20190703171924.31801-3-paweldembicki@gmail.com>



On 7/3/2019 10:19 AM, Pawel Dembicki wrote:
> This driver (currently) only takes control of the switch chip over
> SPI and configures it to route packages around when connected to a
> CPU port. But Vitesse chip support also parallel interface.
> 
> This patch split driver into two parts: core and spi. It is required
> for add support to another managing interface.
> 
> Tested-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply

* Re: [PATCH v2 1/4] net: dsa: Change DT bindings for Vitesse VSC73xx switches
From: Florian Fainelli @ 2019-07-04 20:22 UTC (permalink / raw)
  To: Linus Walleij, Pawel Dembicki
  Cc: Andrew Lunn, Vivien Didelot, David S. Miller, Rob Herring,
	Mark Rutland, netdev,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-kernel@vger.kernel.org
In-Reply-To: <CACRpkdb5LonYLpbOHj=Oo8Z7XjVUWoO0CuhOokxfSoY_fRinPw@mail.gmail.com>



On 7/4/2019 12:05 AM, Linus Walleij wrote:
> On Wed, Jul 3, 2019 at 7:21 PM Pawel Dembicki <paweldembicki@gmail.com> wrote:
> 
>> This commit introduce how to use vsc73xx platform driver.
>>
>> Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
> 
> Nice!
> 
>> +If Platform driver is used, the device tree node is an platform device so it
>> +must reside inside a platform bus device tree node.
> 
> I would write something like "when connected to a memory bus, and
> used in memory-mapped I/O mode, a platform device is used to represent
> the vsc73xx" so it is clear what is going on.

Agreed, with that fixed:

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply

* Re: [PATCH v2 net-next 1/3] tc-testing: Add JSON verification to tdc
From: Alexander Aring @ 2019-07-04 20:21 UTC (permalink / raw)
  To: Lucas Bates
  Cc: davem, netdev, jhs, xiyou.wangcong, jiri, mleitner, vladbu,
	dcaratti, kernel
In-Reply-To: <1562201102-4332-2-git-send-email-lucasb@mojatatu.com>

Hi,

On Wed, Jul 03, 2019 at 08:45:00PM -0400, Lucas Bates wrote:
> This patch allows tdc to process JSON output to perform secondary
> verification of the command under test. If the verifyCmd generates
> JSON, one can provide the 'matchJSON' key to process it
> instead of a regex.
> 
> matchJSON has two elements: 'path' and 'value'. The 'path' key is a
> list of integers and strings that provide the key values for tdc to
> navigate the JSON information. The value is an integer or string
> that tdc will compare against what it finds in the provided path.
> 
> If the numerical position of an element can vary, it's possible to
> substitute an asterisk as a wildcard. tdc will search all possible
> entries in the array.
> 
> Multiple matches are possible, but everything specified must
> match for the test to pass.
> 
> If both matchPattern and matchJSON are present, tdc will only
> operate on matchPattern. If neither are present, verification
> is skipped.
> 
> Example:
> 
>   "cmdUnderTest": "$TC actions add action pass index 8",
>   "verifyCmd": "$TC actions list action gact",
>   "matchJSON": [
>       {
>           "path": [
>               0,
>               "actions",
>               0,
>               "control action",
>               "type"
>           ],
>           "value": "gact"
>       },
>       {
>           "path": [
>               0,
>               "actions",
>               0,
>               "index"
>           ],
>           "value": 8
>       }
>   ]

why you just use eval() as pattern matching operation and let the user
define how to declare a matching mechanism instead you introduce another
static matching scheme based on a json description?

Whereas in eval() you could directly use the python bool expression
parser to make whatever you want.

I don't know, I see at some points you will hit limitations what you can
express with this matchFOO and we need to introduce another matchBAR,
whereas in providing the code it should be no problem expression
anything. If you want smaller shortcuts writing matching patterns you
can implement them and using in your eval() operation.

- Alex

^ permalink raw reply

* Re: [net-next 14/14] net/mlx5e: Add kTLS TX HW offload support
From: Jakub Kicinski @ 2019-07-04 20:12 UTC (permalink / raw)
  To: Saeed Mahameed
  Cc: David S. Miller, netdev@vger.kernel.org, Tariq Toukan,
	Eran Ben Elisha, Boris Pismenny
In-Reply-To: <20190704181235.8966-15-saeedm@mellanox.com>

On Thu, 4 Jul 2019 18:16:15 +0000, Saeed Mahameed wrote:
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> index 483d321d2151..6854f132d505 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> @@ -50,6 +50,15 @@ static const struct counter_desc sw_stats_desc[] = {
>  #ifdef CONFIG_MLX5_EN_TLS
>  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ooo) },
>  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_resync_bytes) },
> +
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo) },

Why do you call this stat tx_ktls_ooo, and not tx_tls_ooo (extra 'k')?

For nfp I used the stats' names from mlx5 FPGA to make sure we are all
consistent.  I've added them to the tls-offload.rst doc and Boris has
reviewed it.

 * ``rx_tls_decrypted`` - number of successfully decrypted TLS segments
 * ``tx_tls_encrypted`` - number of in-order TLS segments passed to device
   for encryption
 * ``tx_tls_ooo`` - number of TX packets which were part of a TLS stream
   but did not arrive in the expected order
 * ``tx_tls_drop_no_sync_data`` - number of TX packets dropped because
   they arrived out of order and associated record could not be found

Why can't you use the same names for the stats as you used for your mlx5
FPGA?

> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_drop_no_sync_data) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_drop_bypass_req) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_dump_bytes) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo_dump_packets) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_enc_packets) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_enc_bytes) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ctx) },
>  #endif
>  
>  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_lro_packets) },

Dave, please don't apply this, I will review in depth once I get
through the earlier 200 emails ;)

^ permalink raw reply

* Re: [PATCH net] ipv4: Fix NULL pointer dereference in ipv4_neigh_lookup()
From: Ido Schimmel @ 2019-07-04 19:55 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, dsahern, jiri, shalomt, mlxsw, idosch
In-Reply-To: <20190704.122449.742393341056317443.davem@davemloft.net>

On Thu, Jul 04, 2019 at 12:24:49PM -0700, David Miller wrote:
> From: Ido Schimmel <idosch@idosch.org>
> Date: Thu,  4 Jul 2019 19:26:38 +0300
> 
> > Both ip_neigh_gw4() and ip_neigh_gw6() can return either a valid pointer
> > or an error pointer, but the code currently checks that the pointer is
> > not NULL.
>  ...
> > @@ -447,7 +447,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
> >  		n = ip_neigh_gw4(dev, pkey);
> >  	}
> >  
> > -	if (n && !refcount_inc_not_zero(&n->refcnt))
> > +	if (!IS_ERR(n) && !refcount_inc_not_zero(&n->refcnt))
> >  		n = NULL;
> >  
> >  	rcu_read_unlock_bh();
> 
> Don't the callers expect only non-error pointers?

It is actually OK to return an error pointer here. In fact, before the
commit I cited the function returned the return value of neigh_create().

If you think it's clearer, we can do this instead:

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 8ea0735a6754..40697fcd2889 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -447,6 +447,9 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
                n = ip_neigh_gw4(dev, pkey);
        }
 
+       if (IS_ERR(n))
+               n = NULL;
+
        if (n && !refcount_inc_not_zero(&n->refcnt))
                n = NULL;

^ permalink raw reply related

* Re: [PATCH net-next v2] net: ethernet: mediatek: Fix overlapping capability bits.
From: David Miller @ 2019-07-04 19:38 UTC (permalink / raw)
  To: opensource
  Cc: sean.wang, f.fainelli, linux, matthias.bgg, andrew,
	vivien.didelot, frank-w, netdev, linux-mediatek, linux-mips
In-Reply-To: <20190703184203.20137-1-opensource@vdorst.com>

From: René van Dorst <opensource@vdorst.com>
Date: Wed,  3 Jul 2019 20:42:04 +0200

> Both MTK_TRGMII_MT7621_CLK and MTK_PATH_BIT are defined as bit 10.
> 
> This can causes issues on non-MT7621 devices which has the
> MTK_PATH_BIT(MTK_ETH_PATH_GMAC1_RGMII) and MTK_TRGMII capability set.
> The wrong TRGMII setup code can be executed. The current wrongly executed
> code doesn’t do any harm on MT7623 and the TRGMII setup for the MT7623
> SOC side is done in MT7530 driver So it wasn’t noticed in the test.
> 
> Move all capability bits in one enum so that they are all unique and easy
> to expand in the future.
> 
> Because mtk_eth_path enum is merged in to mkt_eth_capabilities, the
> variable path value is no longer between 0 to number of paths,
> mtk_eth_path_name can’t be used anymore in this form. Convert the
> mtk_eth_path_name array to a function to lookup the pathname.
> 
> The old code walked thru the mtk_eth_path enum, which is also merged
> with mkt_eth_capabilities. Expand array mtk_eth_muxc so it can store the
> name and capability bit of the mux. Convert the code so it can walk thru
> the mtk_eth_muxc array.
> 
> Fixes: 8efaa653a8a5 ("net: ethernet: mediatek: Add MT7621 TRGMII mode
> support")

Please in the future do not split Fixes: tags onto mutliple lines, it
must be one contiguous line no matter how long.  I fixed it up this
time.

> Signed-off-by: René van Dorst <opensource@vdorst.com>

Applied, thank you.

^ permalink raw reply

* Re: [PATCH v2 0/4] net: dsa: Add Vitesse VSC73xx parallel mode
From: David Miller @ 2019-07-04 19:34 UTC (permalink / raw)
  To: paweldembicki
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, robh+dt,
	mark.rutland, netdev, devicetree, linux-kernel
In-Reply-To: <20190703171924.31801-1-paweldembicki@gmail.com>

From: Pawel Dembicki <paweldembicki@gmail.com>
Date: Wed,  3 Jul 2019 19:19:20 +0200

> Main goal of this patch series is to add support for parallel bus in
> Vitesse VSC73xx switches. Existing driver supports only SPI mode.
> 
> Second change is needed for devices in unmanaged state.

Please respin with the documentation description changes suggested
in the review for this series.

Thanks.

^ permalink raw reply

* Re: [PATCH v1 net-next] net: stmmac: Enable dwmac4 jumbo frame more than 8KiB
From: David Miller @ 2019-07-04 19:33 UTC (permalink / raw)
  To: weifeng.voon
  Cc: mcoquelin.stm32, netdev, linux-kernel, joabreu, peppe.cavallaro,
	andrew, alexandre.torgue, boon.leong.ong
In-Reply-To: <1562173150-808-1-git-send-email-weifeng.voon@intel.com>

From: Voon Weifeng <weifeng.voon@intel.com>
Date: Thu,  4 Jul 2019 00:59:10 +0800

> From: Weifeng Voon <weifeng.voon@intel.com>
> 
> Enable GMAC v4.xx and beyond to support 16KiB buffer.
> 
> Signed-off-by: Weifeng Voon <weifeng.voon@intel.com>
> Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next v2] bonding: add an option to specify a delay between peer notifications
From: David Miller @ 2019-07-04 19:31 UTC (permalink / raw)
  To: vincent; +Cc: jiri, j.vosburgh, vfalico, andy, netdev
In-Reply-To: <20190702174354.10154-1-vincent@bernat.ch>

From: Vincent Bernat <vincent@bernat.ch>
Date: Tue,  2 Jul 2019 19:43:54 +0200

> Currently, gratuitous ARP/ND packets are sent every `miimon'
> milliseconds. This commit allows a user to specify a custom delay
> through a new option, `peer_notif_delay'.
> 
> Like for `updelay' and `downdelay', this delay should be a multiple of
> `miimon' to avoid managing an additional work queue. The configuration
> logic is copied from `updelay' and `downdelay'. However, the default
> value cannot be set using a module parameter: Netlink or sysfs should
> be used to configure this feature.
> 
> When setting `miimon' to 100 and `peer_notif_delay' to 500, we can
> observe the 500 ms delay is respected:
> 
>     20:30:19.354693 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
>     20:30:19.874892 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
>     20:30:20.394919 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
>     20:30:20.914963 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
> 
> In bond_mii_monitor(), I have tried to keep the lock logic readable.
> The change is due to the fact we cannot rely on a notification to
> lower the value of `bond->send_peer_notif' as `NETDEV_NOTIFY_PEERS' is
> only triggered once every N times, while we need to decrement the
> counter each time.
> 
> iproute2 also needs to be updated to be able to specify this new
> attribute through `ip link'.
> 
> Signed-off-by: Vincent Bernat <vincent@bernat.ch>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH net] ipv4: Fix NULL pointer dereference in ipv4_neigh_lookup()
From: David Miller @ 2019-07-04 19:24 UTC (permalink / raw)
  To: idosch; +Cc: netdev, dsahern, jiri, shalomt, mlxsw, idosch
In-Reply-To: <20190704162638.17913-1-idosch@idosch.org>

From: Ido Schimmel <idosch@idosch.org>
Date: Thu,  4 Jul 2019 19:26:38 +0300

> Both ip_neigh_gw4() and ip_neigh_gw6() can return either a valid pointer
> or an error pointer, but the code currently checks that the pointer is
> not NULL.
 ...
> @@ -447,7 +447,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
>  		n = ip_neigh_gw4(dev, pkey);
>  	}
>  
> -	if (n && !refcount_inc_not_zero(&n->refcnt))
> +	if (!IS_ERR(n) && !refcount_inc_not_zero(&n->refcnt))
>  		n = NULL;
>  
>  	rcu_read_unlock_bh();

Don't the callers expect only non-error pointers?

All of this stuff is so confusing and fragile...

^ permalink raw reply


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