* [PATCH net v2] ice: Protect vf_state check by cfg_lock in ice_vc_process_vf_msg()
From: Ivan Vecera @ 2022-04-19 14:22 UTC (permalink / raw)
To: netdev
Cc: poros, mschmidt, Fei Liu, Jesse Brandeburg, Tony Nguyen,
David S. Miller, Jakub Kicinski, Paolo Abeni, Brett Creeley,
moderated list:INTEL ETHERNET DRIVERS, open list
Previous patch labelled "ice: Fix incorrect locking in
ice_vc_process_vf_msg()" fixed an issue with ignored messages
sent by VF driver but a small race window still left.
Recently caught trace during 'ip link set ... vf 0 vlan ...' operation:
[ 7332.995625] ice 0000:3b:00.0: Clearing port VLAN on VF 0
[ 7333.001023] iavf 0000:3b:01.0: Reset indication received from the PF
[ 7333.007391] iavf 0000:3b:01.0: Scheduling reset task
[ 7333.059575] iavf 0000:3b:01.0: PF returned error -5 (IAVF_ERR_PARAM) to our request 3
[ 7333.059626] ice 0000:3b:00.0: Invalid message from VF 0, opcode 3, len 4, error -1
Setting of VLAN for VF causes a reset of the affected VF using
ice_reset_vf() function that runs with cfg_lock taken:
1. ice_notify_vf_reset() informs IAVF driver that reset is needed and
IAVF schedules its own reset procedure
2. Bit ICE_VF_STATE_DIS is set in vf->vf_state
3. Misc initialization steps
4. ice_sriov_post_vsi_rebuild() -> ice_vf_set_initialized() and that
clears ICE_VF_STATE_DIS in vf->vf_state
Step 3 is mentioned race window because IAVF reset procedure runs in
parallel and one of its step is sending of VIRTCHNL_OP_GET_VF_RESOURCES
message (opcode==3). This message is handled in ice_vc_process_vf_msg()
and if it is received during the mentioned race window then it's
marked as invalid and error is returned to VF driver.
Protect vf_state check in ice_vc_process_vf_msg() by cfg_lock to avoid
this race condition.
Fixes: e6ba5273d4ed ("ice: Fix race conditions between virtchnl handling and VF ndo ops")
Tested-by: Fei Liu <feliu@redhat.com>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
drivers/net/ethernet/intel/ice/ice_virtchnl.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
index 5612c032f15a..b72606c9e6d0 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
@@ -3625,6 +3625,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
return;
}
+ mutex_lock(&vf->cfg_lock);
+
/* Check if VF is disabled. */
if (test_bit(ICE_VF_STATE_DIS, vf->vf_states)) {
err = -EPERM;
@@ -3648,19 +3650,14 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
NULL, 0);
dev_err(dev, "Invalid message from VF %d, opcode %d, len %d, error %d\n",
vf_id, v_opcode, msglen, err);
- ice_put_vf(vf);
- return;
+ goto finish;
}
- mutex_lock(&vf->cfg_lock);
-
if (!ice_vc_is_opcode_allowed(vf, v_opcode)) {
ice_vc_send_msg_to_vf(vf, v_opcode,
VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, NULL,
0);
- mutex_unlock(&vf->cfg_lock);
- ice_put_vf(vf);
- return;
+ goto finish;
}
switch (v_opcode) {
@@ -3773,6 +3770,7 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
vf_id, v_opcode, err);
}
+finish:
mutex_unlock(&vf->cfg_lock);
ice_put_vf(vf);
}
--
2.35.1
^ permalink raw reply related
* Re: [Intel-wired-lan] [PATCH net] ice: Protect vf_state check by cfg_lock in ice_vc_process_vf_msg()
From: Ivan Vecera @ 2022-04-19 14:23 UTC (permalink / raw)
To: Tony Nguyen
Cc: Maciej Fijalkowski, Fei Liu, netdev, mschmidt, Brett Creeley,
open list, moderated list:INTEL ETHERNET DRIVERS, Jakub Kicinski,
Paolo Abeni, David S. Miller
In-Reply-To: <607248b2-bfb2-08a2-3d17-67c5c28840fc@intel.com>
On Mon, 18 Apr 2022 11:10:30 -0700
Tony Nguyen <anthony.l.nguyen@intel.com> wrote:
> > If you want to leave the code as is and remove this from the patch
> > let me know and I will send v2.
>
> The change itself looks ok to me, but for net patches, we should fix the
> issue without introducing other changes. A v2 without this change would
> be great; feel free to submit this change to -next after I've applied
> the v2 for this patch.
>
> Thanks,
>
> Tony
Agree, sending v2.
Thanks,
Ivan
^ permalink raw reply
* Re: [PATCH net-next] PCI: add Corigine vendor ID into pci_ids.h
From: Bjorn Helgaas @ 2022-04-19 14:23 UTC (permalink / raw)
To: Yinjun Zhang; +Cc: davem, kuba, netdev, Bjorn Helgaas, linux-pci, Simon Horman
In-Reply-To: <1650362568-11119-1-git-send-email-yinjun.zhang@corigine.com>
On Tue, Apr 19, 2022 at 06:02:48PM +0800, Yinjun Zhang wrote:
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: linux-pci@vger.kernel.org
> Signed-off-by: Yinjun Zhang <yinjun.zhang@corigine.com>
> Signed-off-by: Simon Horman <simon.horman@corigine.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
I'd be happy to apply this, but since I'm in the cc: line, I assume it
will be applied with other patches that use this. Let me know if
otherwise.
I see that you also added the ID at
https://pci-ids.ucw.cz/read/PC/1da8; thank you for that!
But it looks like the "name" part isn't quite correct -- at
https://pci-ids.ucw.cz/read/PC?restrict=1, "Corigine" isn't shown, so
I think lspci won't show the right thing yet.
> ---
> include/linux/pci_ids.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 0178823ce8c2..6d12b6d71c61 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -2568,6 +2568,8 @@
>
> #define PCI_VENDOR_ID_HYGON 0x1d94
>
> +#define PCI_VENDOR_ID_CORIGINE 0x1da8
> +
> #define PCI_VENDOR_ID_FUNGIBLE 0x1dad
>
> #define PCI_VENDOR_ID_HXT 0x1dbf
> --
> 1.8.3.1
>
^ permalink raw reply
* [PATCH v2 bpf-next 2/2] libbpf: Support riscv USDT argument parsing logic
From: Pu Lehui @ 2022-04-19 14:52 UTC (permalink / raw)
To: bpf, linux-kernel, netdev, linux-riscv
Cc: andrii, ast, daniel, kafai, songliubraving, yhs, john.fastabend,
kpsingh, paul.walmsley, palmer, aou, pulehui
In-Reply-To: <20220419145238.482134-1-pulehui@huawei.com>
Add riscv-specific USDT argument specification parsing logic.
riscv USDT argument format is shown below:
- Memory dereference case:
"size@off(reg)", e.g. "-8@-88(s0)"
- Constant value case:
"size@val", e.g. "4@5"
- Register read case:
"size@reg", e.g. "-8@a1"
s8 will be marked as poison while it's a reg of riscv, we need
to alias it in advance. Both RV32 and RV64 have been tested.
Signed-off-by: Pu Lehui <pulehui@huawei.com>
---
v1-v2:
- Add brief test results.
- Make reg_map more intuitive.
tools/lib/bpf/usdt.c | 107 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 107 insertions(+)
diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c
index 8e77a7260..f1c9339cf 100644
--- a/tools/lib/bpf/usdt.c
+++ b/tools/lib/bpf/usdt.c
@@ -10,6 +10,11 @@
#include <linux/ptrace.h>
#include <linux/kernel.h>
+/* s8 will be marked as poison while it's a reg of riscv */
+#if defined(__riscv)
+#define rv_s8 s8
+#endif
+
#include "bpf.h"
#include "libbpf.h"
#include "libbpf_common.h"
@@ -1400,6 +1405,108 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
return len;
}
+#elif defined(__riscv)
+
+static int calc_pt_regs_off(const char *reg_name)
+{
+ static struct {
+ const char *name;
+ size_t pt_regs_off;
+ } reg_map[] = {
+ { "ra", offsetof(struct user_regs_struct, ra) },
+ { "sp", offsetof(struct user_regs_struct, sp) },
+ { "gp", offsetof(struct user_regs_struct, gp) },
+ { "tp", offsetof(struct user_regs_struct, tp) },
+ { "a0", offsetof(struct user_regs_struct, a0) },
+ { "a1", offsetof(struct user_regs_struct, a1) },
+ { "a2", offsetof(struct user_regs_struct, a2) },
+ { "a3", offsetof(struct user_regs_struct, a3) },
+ { "a4", offsetof(struct user_regs_struct, a4) },
+ { "a5", offsetof(struct user_regs_struct, a5) },
+ { "a6", offsetof(struct user_regs_struct, a6) },
+ { "a7", offsetof(struct user_regs_struct, a7) },
+ { "s0", offsetof(struct user_regs_struct, s0) },
+ { "s1", offsetof(struct user_regs_struct, s1) },
+ { "s2", offsetof(struct user_regs_struct, s2) },
+ { "s3", offsetof(struct user_regs_struct, s3) },
+ { "s4", offsetof(struct user_regs_struct, s4) },
+ { "s5", offsetof(struct user_regs_struct, s5) },
+ { "s6", offsetof(struct user_regs_struct, s6) },
+ { "s7", offsetof(struct user_regs_struct, s7) },
+ { "s8", offsetof(struct user_regs_struct, rv_s8) },
+ { "s9", offsetof(struct user_regs_struct, s9) },
+ { "s10", offsetof(struct user_regs_struct, s10) },
+ { "s11", offsetof(struct user_regs_struct, s11) },
+ { "t0", offsetof(struct user_regs_struct, t0) },
+ { "t1", offsetof(struct user_regs_struct, t1) },
+ { "t2", offsetof(struct user_regs_struct, t2) },
+ { "t3", offsetof(struct user_regs_struct, t3) },
+ { "t4", offsetof(struct user_regs_struct, t4) },
+ { "t5", offsetof(struct user_regs_struct, t5) },
+ { "t6", offsetof(struct user_regs_struct, t6) },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(reg_map); i++) {
+ if (strcmp(reg_name, reg_map[i].name) == 0)
+ return reg_map[i].pt_regs_off;
+ }
+
+ pr_warn("usdt: unrecognized register '%s'\n", reg_name);
+ return -ENOENT;
+}
+
+static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
+{
+ char *reg_name = NULL;
+ int arg_sz, len, reg_off;
+ long off;
+
+ if (sscanf(arg_str, " %d @ %ld ( %m[a-z0-9] ) %n", &arg_sz, &off, ®_name, &len) == 3) {
+ /* Memory dereference case, e.g., -8@-88(s0) */
+ arg->arg_type = USDT_ARG_REG_DEREF;
+ arg->val_off = off;
+ reg_off = calc_pt_regs_off(reg_name);
+ free(reg_name);
+ if (reg_off < 0)
+ return reg_off;
+ arg->reg_off = reg_off;
+ } else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) {
+ /* Constant value case, e.g., 4@5 */
+ arg->arg_type = USDT_ARG_CONST;
+ arg->val_off = off;
+ arg->reg_off = 0;
+ } else if (sscanf(arg_str, " %d @ %m[a-z0-9] %n", &arg_sz, ®_name, &len) == 2) {
+ /* Register read case, e.g., -8@a1 */
+ arg->arg_type = USDT_ARG_REG;
+ arg->val_off = 0;
+ reg_off = calc_pt_regs_off(reg_name);
+ free(reg_name);
+ if (reg_off < 0)
+ return reg_off;
+ arg->reg_off = reg_off;
+ } else {
+ pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str);
+ return -EINVAL;
+ }
+
+ arg->arg_signed = arg_sz < 0;
+ if (arg_sz < 0)
+ arg_sz = -arg_sz;
+
+ switch (arg_sz) {
+ case 1: case 2: case 4: case 8:
+ arg->arg_bitshift = 64 - arg_sz * 8;
+ break;
+ default:
+ pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
+ arg_num, arg_str, arg_sz);
+ return -EINVAL;
+ }
+
+ return len;
+}
+
#else
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
--
2.25.1
^ permalink raw reply related
* [PATCH v2 bpf-next 0/2] Support riscv libbpf USDT arg parsing logic
From: Pu Lehui @ 2022-04-19 14:52 UTC (permalink / raw)
To: bpf, linux-kernel, netdev, linux-riscv
Cc: andrii, ast, daniel, kafai, songliubraving, yhs, john.fastabend,
kpsingh, paul.walmsley, palmer, aou, pulehui
patch 1 fix a minor issue where usdt_cookie is cast to 32 bits.
patch 2 add support riscv libbpf USDT argument parsing logic,
both RV32 and RV64 tests have been passed as like follow:
# ./test_progs -t usdt
#169 usdt:OK
Summary: 1/4 PASSED, 0 SKIPPED, 0 FAILED
Pu Lehui (2):
libbpf: Fix usdt_cookie being cast to 32 bits
libbpf: Support riscv USDT argument parsing logic
tools/lib/bpf/libbpf.c | 2 +-
tools/lib/bpf/libbpf_internal.h | 2 +-
tools/lib/bpf/usdt.c | 115 ++++++++++++++++++++++++++++++--
3 files changed, 113 insertions(+), 6 deletions(-)
--
2.25.1
^ permalink raw reply
* [PATCH v2 bpf-next 1/2] libbpf: Fix usdt_cookie being cast to 32 bits
From: Pu Lehui @ 2022-04-19 14:52 UTC (permalink / raw)
To: bpf, linux-kernel, netdev, linux-riscv
Cc: andrii, ast, daniel, kafai, songliubraving, yhs, john.fastabend,
kpsingh, paul.walmsley, palmer, aou, pulehui
In-Reply-To: <20220419145238.482134-1-pulehui@huawei.com>
The usdt_cookie is defined as __u64, which should not be
used as a long type because it will be cast to 32 bits
in 32-bit platforms.
Signed-off-by: Pu Lehui <pulehui@huawei.com>
---
tools/lib/bpf/libbpf.c | 2 +-
tools/lib/bpf/libbpf_internal.h | 2 +-
tools/lib/bpf/usdt.c | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index bf4f7ac54..33d21ed7c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -10982,7 +10982,7 @@ struct bpf_link *bpf_program__attach_usdt(const struct bpf_program *prog,
char resolved_path[512];
struct bpf_object *obj = prog->obj;
struct bpf_link *link;
- long usdt_cookie;
+ __u64 usdt_cookie;
int err;
if (!OPTS_VALID(opts, bpf_uprobe_opts))
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index 080272421..054cd8e93 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -571,6 +571,6 @@ struct bpf_link * usdt_manager_attach_usdt(struct usdt_manager *man,
const struct bpf_program *prog,
pid_t pid, const char *path,
const char *usdt_provider, const char *usdt_name,
- long usdt_cookie);
+ __u64 usdt_cookie);
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c
index 934c25301..8e77a7260 100644
--- a/tools/lib/bpf/usdt.c
+++ b/tools/lib/bpf/usdt.c
@@ -557,10 +557,10 @@ static int parse_usdt_note(Elf *elf, const char *path, long base_addr,
GElf_Nhdr *nhdr, const char *data, size_t name_off, size_t desc_off,
struct usdt_note *usdt_note);
-static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, long usdt_cookie);
+static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie);
static int collect_usdt_targets(struct usdt_manager *man, Elf *elf, const char *path, pid_t pid,
- const char *usdt_provider, const char *usdt_name, long usdt_cookie,
+ const char *usdt_provider, const char *usdt_name, __u64 usdt_cookie,
struct usdt_target **out_targets, size_t *out_target_cnt)
{
size_t off, name_off, desc_off, seg_cnt = 0, lib_seg_cnt = 0, target_cnt = 0;
@@ -939,7 +939,7 @@ static int allocate_spec_id(struct usdt_manager *man, struct hashmap *specs_hash
struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct bpf_program *prog,
pid_t pid, const char *path,
const char *usdt_provider, const char *usdt_name,
- long usdt_cookie)
+ __u64 usdt_cookie)
{
int i, fd, err, spec_map_fd, ip_map_fd;
LIBBPF_OPTS(bpf_uprobe_opts, opts);
@@ -1141,7 +1141,7 @@ static int parse_usdt_note(Elf *elf, const char *path, long base_addr,
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg);
-static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, long usdt_cookie)
+static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie)
{
const char *s;
int len;
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v5 net-next 0/4] rtnetlink: improve ALT_IFNAME config and fix dangerous GROUP usage
From: Florent Fourcot @ 2022-04-19 14:25 UTC (permalink / raw)
To: Jason A. Donenfeld; +Cc: netdev, cong.wang, edumazet
In-Reply-To: <Yl6iFqPFrdvD1wam@zx2c4.com>
Hello Jason,
Thanks for the report. Stephen was right, and I introduced a regression
on ip-link.
I submitted a revert patch with more context on what happened. I'm very
sorry for that.
--
Florent Fourcot.
^ permalink raw reply
* Re: [PATCH net 1/2] net/af_packet: adjust network header position for VLAN tagged packets
From: Michael S. Tsirkin @ 2022-04-19 14:26 UTC (permalink / raw)
To: Willem de Bruijn
Cc: Hangbin Liu, Maxim Mikityanskiy, Mike Pattrick, netdev,
Eric Dumazet, virtualization, Balazs Nemeth, Flavio Leitner,
Jakub Kicinski, Paolo Abeni, David S . Miller, Jason Wang
In-Reply-To: <CA+FuTSfBU7ck91ayf_t9=7eRGJZHuWSeXzX2SxFAQMPSitY9SA@mail.gmail.com>
On Tue, Apr 19, 2022 at 09:56:02AM -0400, Willem de Bruijn wrote:
> > >
> > > We should also maintain feature consistency between packet_snd,
> > > tpacket_snd and to the limitations of its feature set to
> > > packet_sendmsg_spkt. The no_fcs is already lacking in tpacket_snd as
> > > far as I can tell. But packet_sendmsg_spkt also sets it and calls
> > > packet_parse_headers.
> >
> > Yes, I think we could fix the tpacket_snd() in another patch.
> >
> > There are also some duplicated codes in these *_snd functions.
> > I think we can move them out to one single function.
>
> Please don't refactor this code. It will complicate future backports
> of stable fixes.
Hmm I don't know offhand which duplication this refers to specifically
so maybe it's not worth addressing specifically but generally not
cleaning up code just because of backports seems wrong ...
> > > Because this patch touches many other packets besides the ones
> > > intended, I am a bit concerned about unintended consequences. Perhaps
> >
> > Yes, makes sense.
> >
> > > stretching the definition of the flags to include VLAN is acceptable
> > > (unlike outright tunnels), but even then I would suggest for net-next.
> >
> > As I asked, I'm not familiar with virtio code. Do you think if I should
> > add a new VIRTIO_NET_HDR_GSO_VLAN flag? It's only a L2 flag without any L3
> > info. If I add something like VIRTIO_NET_HDR_GSO_VLAN_TCPV4/TCPV6/UDP. That
> > would add more combinations. Which doesn't like a good idea.
>
> I would prefer a new flag to denote this type, so that we can be
> strict and only change the datapath for packets that have this flag
> set (and thus express the intent).
>
> But the VIRTIO_NET_HDR types are defined in the virtio spec. The
> maintainers should probably chime in.
Yes, it's a UAPI extension, not to be done lightly. In this case IIUC
gso_type in the header is only u8 - 8 bits and 5 of these are already
used. So I don't think the virtio TC will be all that happy to burn up
a bit unless a clear benefit can be demonstrated.
I agree with the net-next proposal, I think it's more a feature than a
bugfix. In particular I think a Fixes tag can also be dropped in that
IIUC GSO for vlan packets didn't work even before that commit - right?
--
MST
^ permalink raw reply
* [PATCH net-next 0/2] Propagate extack to vxlan_fdb_delet
From: Alaa Mohamed @ 2022-04-19 14:37 UTC (permalink / raw)
To: netdev
Cc: outreachy, roopa, roopa.prabhu, jdenham, sbrivio,
eng.alaamohamedsoliman.am
In order to propagate extack to vxlan_fdb_delet and vxlan_fdb_parse,
add extack to .ndo_fdb_del and edit all fdb del handelers
Alaa Mohamed (2):
rtnetlink: add extack support in fdb del handlers
net: vxlan: vxlan_core.c: Add extack support to vxlan_fdb_delet
drivers/net/ethernet/intel/ice/ice_main.c | 2 +-
drivers/net/ethernet/mscc/ocelot_net.c | 4 ++--
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 +-
drivers/net/macvlan.c | 2 +-
drivers/net/vxlan/vxlan_core.c | 15 +++++++++++----
include/linux/netdevice.h | 2 +-
net/bridge/br_fdb.c | 2 +-
net/bridge/br_private.h | 2 +-
net/core/rtnetlink.c | 4 ++--
9 files changed, 21 insertions(+), 14 deletions(-)
--
2.35.2
^ permalink raw reply
* [PATCH net-next 1/2] rtnetlink: add extack support in fdb del handlers
From: Alaa Mohamed @ 2022-04-19 14:37 UTC (permalink / raw)
To: netdev
Cc: outreachy, roopa, roopa.prabhu, jdenham, sbrivio,
eng.alaamohamedsoliman.am
In-Reply-To: <cover.1650377624.git.eng.alaamohamedsoliman.am@gmail.com>
Add extack support to .ndo_fdb_del in netdevice.h and
all related methods.
Signed-off-by: Alaa Mohamed <eng.alaamohamedsoliman.am@gmail.com>
---
drivers/net/ethernet/intel/ice/ice_main.c | 2 +-
drivers/net/ethernet/mscc/ocelot_net.c | 4 ++--
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 +-
drivers/net/macvlan.c | 2 +-
drivers/net/vxlan/vxlan_core.c | 2 +-
include/linux/netdevice.h | 2 +-
net/bridge/br_fdb.c | 2 +-
net/bridge/br_private.h | 2 +-
net/core/rtnetlink.c | 4 ++--
9 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index d768925785ca..4fd32163729e 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5678,7 +5678,7 @@ ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[],
static int
ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
struct net_device *dev, const unsigned char *addr,
- __always_unused u16 vid)
+ __always_unused u16 vid, struct netlink_ext_ack *extack)
{
int err;
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 247bc105bdd2..e07c64e3159c 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -774,14 +774,14 @@ static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
static int ocelot_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
- const unsigned char *addr, u16 vid)
+ const unsigned char *addr, u16 vid, struct netlink_ext_ack *extack)
{
struct ocelot_port_private *priv = netdev_priv(dev);
struct ocelot_port *ocelot_port = &priv->port;
struct ocelot *ocelot = ocelot_port->ocelot;
int port = priv->chip_port;
- return ocelot_fdb_del(ocelot, port, addr, vid, ocelot_port->bridge);
+ return ocelot_fdb_del(ocelot, port, addr, vid, ocelot_port->bridge, extack);
}
static int ocelot_port_fdb_dump(struct sk_buff *skb,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index d320567b2cca..51fa23418f6a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -368,7 +368,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *netdev,
- const unsigned char *addr, u16 vid)
+ const unsigned char *addr, u16 vid, struct netlink_ext_ack *extack)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int err = -EOPNOTSUPP;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 069e8824c264..ffd34d9f7049 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1017,7 +1017,7 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
- const unsigned char *addr, u16 vid)
+ const unsigned char *addr, u16 vid, struct netlink_ext_ack *extack)
{
struct macvlan_dev *vlan = netdev_priv(dev);
int err = -EINVAL;
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index de97ff98d36e..cf2f60037340 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -1280,7 +1280,7 @@ int __vxlan_fdb_delete(struct vxlan_dev *vxlan,
/* Delete entry (via netlink) */
static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
- const unsigned char *addr, u16 vid)
+ const unsigned char *addr, u16 vid, struct netlink_ext_ack *extack)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
union vxlan_addr ip;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 28ea4f8269d4..d0d2a8f33c73 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1509,7 +1509,7 @@ struct net_device_ops {
struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr,
- u16 vid);
+ u16 vid, struct netlink_ext_ack *extack);
int (*ndo_fdb_dump)(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 6ccda68bd473..5bfce2e9a553 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -1110,7 +1110,7 @@ static int __br_fdb_delete(struct net_bridge *br,
/* Remove neighbor entry with RTM_DELNEIGH */
int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
- const unsigned char *addr, u16 vid)
+ const unsigned char *addr, u16 vid, struct netlink_ext_ack *extack)
{
struct net_bridge_vlan_group *vg;
struct net_bridge_port *p = NULL;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 18ccc3d5d296..95348c1c9ce5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -780,7 +780,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
const unsigned char *addr, u16 vid, unsigned long flags);
int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
- struct net_device *dev, const unsigned char *addr, u16 vid);
+ struct net_device *dev, const unsigned char *addr, u16 vid, struct netlink_ext_ack *extack);
int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev,
const unsigned char *addr, u16 vid, u16 nlh_flags,
struct netlink_ext_ack *extack);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4041b3e2e8ec..99b30ae58a47 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -4223,7 +4223,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
const struct net_device_ops *ops = br_dev->netdev_ops;
if (ops->ndo_fdb_del)
- err = ops->ndo_fdb_del(ndm, tb, dev, addr, vid);
+ err = ops->ndo_fdb_del(ndm, tb, dev, addr, vid, extack);
if (err)
goto out;
@@ -4235,7 +4235,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
if (ndm->ndm_flags & NTF_SELF) {
if (dev->netdev_ops->ndo_fdb_del)
err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr,
- vid);
+ vid, extack);
else
err = ndo_dflt_fdb_del(ndm, tb, dev, addr, vid);
--
2.35.2
^ permalink raw reply related
* [PATCH net-next 2/2] net: vxlan: vxlan_core.c: Add extack support to vxlan_fdb_delet
From: Alaa Mohamed @ 2022-04-19 14:37 UTC (permalink / raw)
To: netdev
Cc: outreachy, roopa, roopa.prabhu, jdenham, sbrivio,
eng.alaamohamedsoliman.am
In-Reply-To: <cover.1650377624.git.eng.alaamohamedsoliman.am@gmail.com>
Add extack to vxlan_fdb_delet and vxlan_fdb_parse
Signed-off-by: Alaa Mohamed <eng.alaamohamedsoliman.am@gmail.com>
---
drivers/net/vxlan/vxlan_core.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index cf2f60037340..4ecbb5878fe2 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -1129,18 +1129,20 @@ static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
union vxlan_addr *ip, __be16 *port, __be32 *src_vni,
- __be32 *vni, u32 *ifindex, u32 *nhid)
+ __be32 *vni, u32 *ifindex, u32 *nhid, struct netlink_ext_ack *extack)
{
struct net *net = dev_net(vxlan->dev);
int err;
if (tb[NDA_NH_ID] && (tb[NDA_DST] || tb[NDA_VNI] || tb[NDA_IFINDEX] ||
tb[NDA_PORT]))
+ NL_SET_ERR_MSG(extack, "Missing required arguments");
return -EINVAL;
if (tb[NDA_DST]) {
err = vxlan_nla_get_addr(ip, tb[NDA_DST]);
if (err)
+ NL_SET_ERR_MSG(extack, "Unsupported address family");
return err;
} else {
union vxlan_addr *remote = &vxlan->default_dst.remote_ip;
@@ -1158,6 +1160,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
if (tb[NDA_PORT]) {
if (nla_len(tb[NDA_PORT]) != sizeof(__be16))
+ NL_SET_ERR_MSG(extack, "Invalid vxlan port");
return -EINVAL;
*port = nla_get_be16(tb[NDA_PORT]);
} else {
@@ -1166,6 +1169,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
if (tb[NDA_VNI]) {
if (nla_len(tb[NDA_VNI]) != sizeof(u32))
+ NL_SET_ERR_MSG(extack, "Invalid vni");
return -EINVAL;
*vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI]));
} else {
@@ -1174,6 +1178,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
if (tb[NDA_SRC_VNI]) {
if (nla_len(tb[NDA_SRC_VNI]) != sizeof(u32))
+ NL_SET_ERR_MSG(extack, "Invalid src vni");
return -EINVAL;
*src_vni = cpu_to_be32(nla_get_u32(tb[NDA_SRC_VNI]));
} else {
@@ -1184,10 +1189,12 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
struct net_device *tdev;
if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
+ NL_SET_ERR_MSG(extack, "Invalid ifindex");
return -EINVAL;
*ifindex = nla_get_u32(tb[NDA_IFINDEX]);
tdev = __dev_get_by_index(net, *ifindex);
if (!tdev)
+ NL_SET_ERR_MSG(extack,"Device not found");
return -EADDRNOTAVAIL;
} else {
*ifindex = 0;
@@ -1226,7 +1233,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
return -EINVAL;
err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &src_vni, &vni, &ifindex,
- &nhid);
+ &nhid, extack);
if (err)
return err;
@@ -1291,7 +1298,7 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
int err;
err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &src_vni, &vni, &ifindex,
- &nhid);
+ &nhid, extack);
if (err)
return err;
--
2.35.2
^ permalink raw reply related
* Re: [RFCv6 PATCH net-next 01/19] net: introduce operation helpers for netdev features
From: Alexander Lobakin @ 2022-04-19 14:40 UTC (permalink / raw)
To: Jian Shen
Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
saeed, leon, netdev, linuxarm, lipeng321
In-Reply-To: <20220419022206.36381-2-shenjian15@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
Date: Tue, 19 Apr 2022 10:21:48 +0800
> Introduce a set of bitmap operation helpers for netdev features,
> then we can use them to replace the logical operation with them.
> As the nic driversare not supposed to modify netdev_features
> directly, it also introduces wrappers helpers to this.
>
> The implementation of these helpers are based on the old prototype
> of netdev_features_t is still u64. I will rewrite them on the last
> patch, when the prototype changes.
>
> To avoid interdependencies between netdev_features_helper.h and
> netdevice.h, put the helpers for testing feature is set in the
> netdevice.h, and move advandced helpers like
> netdev_get_wanted_features() and netdev_intersect_features() to
> netdev_features_helper.h.
>
> Signed-off-by: Jian Shen <shenjian15@huawei.com>
> ---
> .../net/ethernet/netronome/nfp/nfp_net_repr.c | 1 +
> include/linux/netdev_features.h | 12 +
> include/linux/netdev_features_helper.h | 604 ++++++++++++++++++
> include/linux/netdevice.h | 45 +-
> net/8021q/vlan_dev.c | 1 +
> net/core/dev.c | 1 +
> 6 files changed, 646 insertions(+), 18 deletions(-)
> create mode 100644 include/linux/netdev_features_helper.h
>
> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
> index ba3fa7eac98d..08f2c54e0a11 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
> +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
> @@ -4,6 +4,7 @@
> #include <linux/etherdevice.h>
> #include <linux/io-64-nonatomic-hi-lo.h>
> #include <linux/lockdep.h>
> +#include <linux/netdev_features_helper.h>
> #include <net/dst_metadata.h>
>
> #include "nfpcore/nfp_cpp.h"
> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
> index 2c6b9e416225..e2b66fa3d7d6 100644
> --- a/include/linux/netdev_features.h
> +++ b/include/linux/netdev_features.h
> @@ -11,6 +11,18 @@
>
> typedef u64 netdev_features_t;
>
> +struct netdev_feature_set {
> + unsigned int cnt;
> + unsigned short feature_bits[];
> +};
> +
> +#define DECLARE_NETDEV_FEATURE_SET(name, features...) \
> + static unsigned short __##name##_s[] = {features}; \
> + struct netdev_feature_set name = { \
I suggest using `const` here. Those sets are needed only to
initialize bitmaps, that's it. They are not supposed to be
modified. This would be one more hardening here to avoid some weird
usages of sets, and also would place them in .rodata instead of just
.data.
Function old new delta
main 35 33 -2
Total: Before=78, After=76, chg -2.56%
add/remove: 0/2 grow/shrink: 0/0 up/down: 0/-14 (-14)
Data old new delta
arr1 6 - -6
arr2 8 - -8
Total: Before=15, After=1, chg -93.33%
add/remove: 2/0 grow/shrink: 0/0 up/down: 14/0 (14)
RO Data old new delta
arr1 - 8 +8
arr2 - 6 +6
Total: Before=36, After=50, chg +38.89%
As you can see, there's a 2-byte code optimization. And that was
just a simpliest oneliner. The gains will be much bigger from the
real usages.
> + .cnt = ARRAY_SIZE(__##name##_s), \
> + .feature_bits = {features}, \
> + }
The problem with the current macro is that it doesn't allow to
declare feature sets as static. Because the temporary array for
counting the number of bits goes first, and doing
static DECLARE_NETDEV_FEATURE_SET();
wouldn't change anything.
But we want to have most feature sets static as they will be needed
only inside one file. Making every of them global would hurt
optimization.
At the end, I came to
#define DECLARE_NETDEV_FEATURE_SET(name, features...) \
const struct netdev_feature_set name = { \
.feature_bits = { features }, \
.cnt = sizeof((u16 []){ features }) / sizeof(u16), \
}
because ARRAY_SIZE() can be taken only from a variable, not from
a compound literal.
But this one is actually OK. We don't need ARRAY_SIZE() in here
since we define an unnamed array of an explicit type that we know
for sure inline. So there's no chance to do it wrong as long as
the @features argument is correct.
The ability to make it static is important. For example, when I
marked them both static, I got
add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0)
Function old new delta
Total: Before=76, After=76, chg +0.00%
add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0)
Data old new delta
Total: Before=1, After=1, chg +0.00%
add/remove: 0/2 grow/shrink: 0/0 up/down: 0/-14 (-14)
RO Data old new delta
arr1 6 - -6
arr2 8 - -8
Total: Before=50, After=36, chg -28.00%
i.e. both of the sets were removed, because my main() was:
printf("cnt1: %u, cnt2: %u\n", arr1.cnt, arr2.cnt);
The compiler saw that I don't use them, except for printing values
which are actually compile-time constants, and wiped them.
Previously, they were global so it didn't have a clue if they're
used anywhere else.
This was a simple stupid example, but it will bring a lot more value
in real use cases. So please consider my variant :D
> +
> enum {
> NETIF_F_SG_BIT, /* Scatter/gather IO. */
> NETIF_F_IP_CSUM_BIT, /* Can checksum TCP/UDP over IPv4. */
--- 8< ---
> --
> 2.33.0
Thanks,
Al
^ permalink raw reply
* Re: [RFCv6 PATCH net-next 02/19] net: replace general features macroes with global netdev_features variables
From: Alexander Lobakin @ 2022-04-19 14:49 UTC (permalink / raw)
To: Jian Shen
Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
saeed, leon, netdev, linuxarm, lipeng321
In-Reply-To: <20220419022206.36381-3-shenjian15@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
Date: Tue, 19 Apr 2022 10:21:49 +0800
> There are many netdev_features bits group used in kernel. The definition
> will be illegal when using feature bit more than 64. Replace these macroes
> with global netdev_features variables, initialize them when netdev module
> init.
>
> Signed-off-by: Jian Shen <shenjian15@huawei.com>
> ---
> drivers/net/wireguard/device.c | 10 +-
> include/linux/netdev_features.h | 102 +++++++++-----
> net/core/Makefile | 2 +-
> net/core/dev.c | 87 ++++++++++++
> net/core/netdev_features.c | 241 ++++++++++++++++++++++++++++++++
> 5 files changed, 400 insertions(+), 42 deletions(-)
> create mode 100644 net/core/netdev_features.c
>
--- 8< ---
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 4d6b57752eee..85bb418e8ef1 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -146,6 +146,7 @@
> #include <linux/sctp.h>
> #include <net/udp_tunnel.h>
> #include <linux/net_namespace.h>
> +#include <linux/netdev_features_helper.h>
> #include <linux/indirect_call_wrapper.h>
> #include <net/devlink.h>
> #include <linux/pm_runtime.h>
> @@ -11255,6 +11256,90 @@ static struct pernet_operations __net_initdata default_device_ops = {
> .exit_batch = default_device_exit_batch,
> };
>
> +static void netdev_features_init(void)
It is an initialization function, so it must be marked as __init.
> +{
> + netdev_features_t features;
> +
> + netdev_features_set_array(&netif_f_never_change_feature_set,
> + &netdev_never_change_features);
> +
> + netdev_features_set_array(&netif_f_gso_feature_set_mask,
I'm not sure it does make sense to have an empty newline between
each call. I'd leave newlines only between the "regular" blocks
and the "multi-call" blocks, I mean, stuff like VLAN, GSO and
@netdev_ethtool_features.
> + &netdev_gso_features_mask);
> +
> + netdev_features_set_array(&netif_f_ip_csum_feature_set,
> + &netdev_ip_csum_features);
> +
> + netdev_features_set_array(&netif_f_csum_feature_set_mask,
> + &netdev_csum_features_mask);
> +
> + netdev_features_set_array(&netif_f_general_tso_feature_set,
> + &netdev_general_tso_features);
> +
> + netdev_features_set_array(&netif_f_all_tso_feature_set,
> + &netdev_all_tso_features);
> +
> + netdev_features_set_array(&netif_f_tso_ecn_feature_set,
> + &netdev_tso_ecn_features);
> +
> + netdev_features_set_array(&netif_f_all_fcoe_feature_set,
> + &netdev_all_fcoe_features);
> +
> + netdev_features_set_array(&netif_f_gso_soft_feature_set,
> + &netdev_gso_software_features);
> +
> + netdev_features_set_array(&netif_f_one_for_all_feature_set,
> + &netdev_one_for_all_features);
> +
> + netdev_features_set_array(&netif_f_all_for_all_feature_set,
> + &netdev_all_for_all_features);
> +
> + netdev_features_set_array(&netif_f_upper_disables_feature_set,
> + &netdev_upper_disable_features);
> +
> + netdev_features_set_array(&netif_f_soft_feature_set,
> + &netdev_soft_features);
> +
> + netdev_features_set_array(&netif_f_soft_off_feature_set,
> + &netdev_soft_off_features);
> +
> + netdev_features_set_array(&netif_f_rx_vlan_feature_set,
> + &netdev_rx_vlan_features);
> +
> + netdev_features_set_array(&netif_f_tx_vlan_feature_set,
> + &netdev_tx_vlan_features);
> +
> + netdev_features_set_array(&netif_f_vlan_filter_feature_set,
> + &netdev_vlan_filter_features);
> +
> + netdev_all_vlan_features = netdev_rx_vlan_features;
> + netdev_features_set(&netdev_all_vlan_features, netdev_tx_vlan_features);
> + netdev_features_set(&netdev_all_vlan_features,
> + netdev_vlan_filter_features);
> +
> + netdev_features_set_array(&netif_f_ctag_vlan_feature_set,
> + &netdev_ctag_vlan_features);
> +
> + netdev_features_set_array(&netif_f_stag_vlan_feature_set,
> + &netdev_stag_vlan_features);
> +
> + netdev_features_set_array(&netif_f_gso_encap_feature_set,
> + &netdev_gso_encap_all_features);
> +
> + netdev_features_set_array(&netif_f_xfrm_feature_set,
> + &netdev_xfrm_features);
> +
> + netdev_features_set_array(&netif_f_tls_feature_set,
> + &netdev_tls_features);
> +
> + netdev_csum_gso_features_mask =
> + netdev_features_or(netdev_gso_software_features,
> + netdev_csum_features_mask);
> +
> + netdev_features_fill(&features);
> + netdev_ethtool_features =
> + netdev_features_andnot(features, netdev_never_change_features);
> +}
> +
> /*
> * Initialize the DEV module. At boot time this walks the device list and
> * unhooks any devices that fail to initialise (normally hardware not
--- 8< ---
> --
> 2.33.0
Thanks,
Al
^ permalink raw reply
* Re: [PATCH net-next 2/2] net: vxlan: vxlan_core.c: Add extack support to vxlan_fdb_delet
From: Roopa Prabhu @ 2022-04-19 14:54 UTC (permalink / raw)
To: Alaa Mohamed, netdev; +Cc: outreachy, roopa.prabhu, jdenham, sbrivio
In-Reply-To: <c6765ff1f66cf74ba6f25ba9b1c91dfe410abcfd.1650377624.git.eng.alaamohamedsoliman.am@gmail.com>
On 4/19/22 07:37, Alaa Mohamed wrote:
> Add extack to vxlan_fdb_delet and vxlan_fdb_parse
>
> Signed-off-by: Alaa Mohamed <eng.alaamohamedsoliman.am@gmail.com>
> ---
Alaa, minor nit: fix spelling vxlan_fdb_delete
> drivers/net/vxlan/vxlan_core.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
> index cf2f60037340..4ecbb5878fe2 100644
> --- a/drivers/net/vxlan/vxlan_core.c
> +++ b/drivers/net/vxlan/vxlan_core.c
> @@ -1129,18 +1129,20 @@ static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
>
> static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
> union vxlan_addr *ip, __be16 *port, __be32 *src_vni,
> - __be32 *vni, u32 *ifindex, u32 *nhid)
> + __be32 *vni, u32 *ifindex, u32 *nhid, struct netlink_ext_ack *extack)
> {
> struct net *net = dev_net(vxlan->dev);
> int err;
>
> if (tb[NDA_NH_ID] && (tb[NDA_DST] || tb[NDA_VNI] || tb[NDA_IFINDEX] ||
> tb[NDA_PORT]))
> + NL_SET_ERR_MSG(extack, "Missing required arguments");
> return -EINVAL;
>
> if (tb[NDA_DST]) {
> err = vxlan_nla_get_addr(ip, tb[NDA_DST]);
> if (err)
> + NL_SET_ERR_MSG(extack, "Unsupported address family");
> return err;
> } else {
> union vxlan_addr *remote = &vxlan->default_dst.remote_ip;
> @@ -1158,6 +1160,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
>
> if (tb[NDA_PORT]) {
> if (nla_len(tb[NDA_PORT]) != sizeof(__be16))
> + NL_SET_ERR_MSG(extack, "Invalid vxlan port");
> return -EINVAL;
> *port = nla_get_be16(tb[NDA_PORT]);
> } else {
> @@ -1166,6 +1169,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
>
> if (tb[NDA_VNI]) {
> if (nla_len(tb[NDA_VNI]) != sizeof(u32))
> + NL_SET_ERR_MSG(extack, "Invalid vni");
> return -EINVAL;
> *vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI]));
> } else {
> @@ -1174,6 +1178,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
>
> if (tb[NDA_SRC_VNI]) {
> if (nla_len(tb[NDA_SRC_VNI]) != sizeof(u32))
> + NL_SET_ERR_MSG(extack, "Invalid src vni");
> return -EINVAL;
> *src_vni = cpu_to_be32(nla_get_u32(tb[NDA_SRC_VNI]));
> } else {
> @@ -1184,10 +1189,12 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
> struct net_device *tdev;
>
> if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
> + NL_SET_ERR_MSG(extack, "Invalid ifindex");
> return -EINVAL;
Missing braces.
> *ifindex = nla_get_u32(tb[NDA_IFINDEX]);
> tdev = __dev_get_by_index(net, *ifindex);
> if (!tdev)
> + NL_SET_ERR_MSG(extack,"Device not found");
> return -EADDRNOTAVAIL;
same here
> } else {
> *ifindex = 0;
> @@ -1226,7 +1233,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
> return -EINVAL;
>
> err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &src_vni, &vni, &ifindex,
> - &nhid);
> + &nhid, extack);
> if (err)
> return err;
>
> @@ -1291,7 +1298,7 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
> int err;
>
> err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &src_vni, &vni, &ifindex,
> - &nhid);
> + &nhid, extack);
> if (err)
> return err;
>
> --
> 2.35.2
>
^ permalink raw reply
* [PATCH net-next 0/6] mlxsw: Line cards status tracking
From: Ido Schimmel @ 2022-04-19 14:54 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, petrm, jiri, vadimp, mlxsw, Ido Schimmel
When a line card is provisioned, netdevs corresponding to the ports
found on the line card are registered. User space can then perform
various logical configurations (e.g., splitting, setting MTU) on these
netdevs.
However, since the line card is not present / powered on (i.e., it is
not in 'active' state), user space cannot access the various components
found on the line card. For example, user space cannot read the
temperature of gearboxes or transceiver modules found on the line card
via hwmon / thermal. Similarly, it cannot dump the EEPROM contents of
these transceiver modules. The above is only possible when the line card
becomes active.
This patchset solves the problem by tracking the status of each line
card and invoking callbacks from interested parties when a line card
becomes active / inactive.
Patchset overview:
Patch #1 adds the infrastructure in the line cards core that allows
users to registers a set of callbacks that are invoked when a line card
becomes active / inactive. To avoid races, if a line card is already
active during registration, the got_active() callback is invoked.
Patches #2-#3 are preparations.
Patch #4 changes the port module core to register a set of callbacks
with the line cards core. See detailed description with examples in the
commit message.
Patches #5-#6 do the same with regards to thermal / hwmon support, so
that user space will be able to monitor the temperature of various
components on the line card when it becomes active.
Jiri Pirko (1):
mlxsw: core_linecards: Introduce ops for linecards status change
tracking
Vadim Pasternak (5):
mlxsw: core: Add bus argument to environment init API
mlxsw: core_env: Split module power mode setting to a separate
function
mlxsw: core_env: Add interfaces for line card initialization and
de-initialization
mlxsw: core_thermal: Add interfaces for line card initialization and
de-initialization
mlxsw: core_hwmon: Add interfaces for line card initialization and
de-initialization
drivers/net/ethernet/mellanox/mlxsw/core.c | 2 +-
drivers/net/ethernet/mellanox/mlxsw/core.h | 17 ++
.../net/ethernet/mellanox/mlxsw/core_env.c | 213 ++++++++++++++++--
.../net/ethernet/mellanox/mlxsw/core_env.h | 4 +-
.../net/ethernet/mellanox/mlxsw/core_hwmon.c | 84 +++++++
.../ethernet/mellanox/mlxsw/core_linecards.c | 137 +++++++++++
.../ethernet/mellanox/mlxsw/core_thermal.c | 74 ++++++
7 files changed, 513 insertions(+), 18 deletions(-)
--
2.33.1
^ permalink raw reply
* [PATCH net-next 1/6] mlxsw: core_linecards: Introduce ops for linecards status change tracking
From: Ido Schimmel @ 2022-04-19 14:54 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, petrm, jiri, vadimp, mlxsw, Ido Schimmel
In-Reply-To: <20220419145431.2991382-1-idosch@nvidia.com>
From: Jiri Pirko <jiri@nvidia.com>
Introduce an infrastructure allowing users to register a set
of operations which are to be called whenever a line card gets
active/inactive.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
drivers/net/ethernet/mellanox/mlxsw/core.h | 17 +++
.../ethernet/mellanox/mlxsw/core_linecards.c | 137 ++++++++++++++++++
2 files changed, 154 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 850fff51b79f..c2a891287047 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -590,6 +590,8 @@ struct mlxsw_linecards {
const struct mlxsw_bus_info *bus_info;
u8 count;
struct mlxsw_linecard_types_info *types_info;
+ struct list_head event_ops_list;
+ struct mutex event_ops_list_lock; /* Locks accesses to event ops list */
struct mlxsw_linecard linecards[];
};
@@ -603,4 +605,19 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *bus_info);
void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core);
+typedef void mlxsw_linecards_event_op_t(struct mlxsw_core *mlxsw_core,
+ u8 slot_index, void *priv);
+
+struct mlxsw_linecards_event_ops {
+ mlxsw_linecards_event_op_t *got_active;
+ mlxsw_linecards_event_op_t *got_inactive;
+};
+
+int mlxsw_linecards_event_ops_register(struct mlxsw_core *mlxsw_core,
+ struct mlxsw_linecards_event_ops *ops,
+ void *priv);
+void mlxsw_linecards_event_ops_unregister(struct mlxsw_core *mlxsw_core,
+ struct mlxsw_linecards_event_ops *ops,
+ void *priv);
+
#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
index 1d50bfe67156..90e487cc2e2a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
@@ -95,6 +95,137 @@ static void mlxsw_linecard_provision_fail(struct mlxsw_linecard *linecard)
devlink_linecard_provision_fail(linecard->devlink_linecard);
}
+struct mlxsw_linecards_event_ops_item {
+ struct list_head list;
+ const struct mlxsw_linecards_event_ops *event_ops;
+ void *priv;
+};
+
+static void
+mlxsw_linecard_event_op_call(struct mlxsw_linecard *linecard,
+ mlxsw_linecards_event_op_t *op, void *priv)
+{
+ struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core;
+
+ if (!op)
+ return;
+ op(mlxsw_core, linecard->slot_index, priv);
+}
+
+static void
+mlxsw_linecard_active_ops_call(struct mlxsw_linecard *linecard)
+{
+ struct mlxsw_linecards *linecards = linecard->linecards;
+ struct mlxsw_linecards_event_ops_item *item;
+
+ mutex_lock(&linecards->event_ops_list_lock);
+ list_for_each_entry(item, &linecards->event_ops_list, list)
+ mlxsw_linecard_event_op_call(linecard,
+ item->event_ops->got_active,
+ item->priv);
+ mutex_unlock(&linecards->event_ops_list_lock);
+}
+
+static void
+mlxsw_linecard_inactive_ops_call(struct mlxsw_linecard *linecard)
+{
+ struct mlxsw_linecards *linecards = linecard->linecards;
+ struct mlxsw_linecards_event_ops_item *item;
+
+ mutex_lock(&linecards->event_ops_list_lock);
+ list_for_each_entry(item, &linecards->event_ops_list, list)
+ mlxsw_linecard_event_op_call(linecard,
+ item->event_ops->got_inactive,
+ item->priv);
+ mutex_unlock(&linecards->event_ops_list_lock);
+}
+
+static void
+mlxsw_linecards_event_ops_register_call(struct mlxsw_linecards *linecards,
+ const struct mlxsw_linecards_event_ops_item *item)
+{
+ struct mlxsw_linecard *linecard;
+ int i;
+
+ for (i = 0; i < linecards->count; i++) {
+ linecard = mlxsw_linecard_get(linecards, i + 1);
+ mutex_lock(&linecard->lock);
+ if (linecard->active)
+ mlxsw_linecard_event_op_call(linecard,
+ item->event_ops->got_active,
+ item->priv);
+ mutex_unlock(&linecard->lock);
+ }
+}
+
+static void
+mlxsw_linecards_event_ops_unregister_call(struct mlxsw_linecards *linecards,
+ const struct mlxsw_linecards_event_ops_item *item)
+{
+ struct mlxsw_linecard *linecard;
+ int i;
+
+ for (i = 0; i < linecards->count; i++) {
+ linecard = mlxsw_linecard_get(linecards, i + 1);
+ mutex_lock(&linecard->lock);
+ if (linecard->active)
+ mlxsw_linecard_event_op_call(linecard,
+ item->event_ops->got_inactive,
+ item->priv);
+ mutex_unlock(&linecard->lock);
+ }
+}
+
+int mlxsw_linecards_event_ops_register(struct mlxsw_core *mlxsw_core,
+ struct mlxsw_linecards_event_ops *ops,
+ void *priv)
+{
+ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core);
+ struct mlxsw_linecards_event_ops_item *item;
+
+ if (!linecards)
+ return 0;
+ item = kzalloc(sizeof(*item), GFP_KERNEL);
+ if (!item)
+ return -ENOMEM;
+ item->event_ops = ops;
+ item->priv = priv;
+
+ mutex_lock(&linecards->event_ops_list_lock);
+ list_add_tail(&item->list, &linecards->event_ops_list);
+ mutex_unlock(&linecards->event_ops_list_lock);
+ mlxsw_linecards_event_ops_register_call(linecards, item);
+ return 0;
+}
+EXPORT_SYMBOL(mlxsw_linecards_event_ops_register);
+
+void mlxsw_linecards_event_ops_unregister(struct mlxsw_core *mlxsw_core,
+ struct mlxsw_linecards_event_ops *ops,
+ void *priv)
+{
+ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core);
+ struct mlxsw_linecards_event_ops_item *item, *tmp;
+ bool found = false;
+
+ if (!linecards)
+ return;
+ mutex_lock(&linecards->event_ops_list_lock);
+ list_for_each_entry_safe(item, tmp, &linecards->event_ops_list, list) {
+ if (item->event_ops == ops && item->priv == priv) {
+ list_del(&item->list);
+ found = true;
+ break;
+ }
+ }
+ mutex_unlock(&linecards->event_ops_list_lock);
+
+ if (!found)
+ return;
+ mlxsw_linecards_event_ops_unregister_call(linecards, item);
+ kfree(item);
+}
+EXPORT_SYMBOL(mlxsw_linecards_event_ops_unregister);
+
static int
mlxsw_linecard_provision_set(struct mlxsw_linecard *linecard, u8 card_type,
u16 hw_revision, u16 ini_version)
@@ -163,12 +294,14 @@ static int mlxsw_linecard_ready_clear(struct mlxsw_linecard *linecard)
static void mlxsw_linecard_active_set(struct mlxsw_linecard *linecard)
{
+ mlxsw_linecard_active_ops_call(linecard);
linecard->active = true;
devlink_linecard_activate(linecard->devlink_linecard);
}
static void mlxsw_linecard_active_clear(struct mlxsw_linecard *linecard)
{
+ mlxsw_linecard_inactive_ops_call(linecard);
linecard->active = false;
devlink_linecard_deactivate(linecard->devlink_linecard);
}
@@ -954,6 +1087,8 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core,
linecards->count = slot_count;
linecards->mlxsw_core = mlxsw_core;
linecards->bus_info = bus_info;
+ INIT_LIST_HEAD(&linecards->event_ops_list);
+ mutex_init(&linecards->event_ops_list_lock);
err = mlxsw_linecard_types_init(mlxsw_core, linecards);
if (err)
@@ -1001,5 +1136,7 @@ void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core)
ARRAY_SIZE(mlxsw_linecard_listener),
mlxsw_core);
mlxsw_linecard_types_fini(linecards);
+ mutex_destroy(&linecards->event_ops_list_lock);
+ WARN_ON(!list_empty(&linecards->event_ops_list));
vfree(linecards);
}
--
2.33.1
^ permalink raw reply related
* [PATCH net-next 2/6] mlxsw: core: Add bus argument to environment init API
From: Ido Schimmel @ 2022-04-19 14:54 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, petrm, jiri, vadimp, mlxsw, Ido Schimmel
In-Reply-To: <20220419145431.2991382-1-idosch@nvidia.com>
From: Vadim Pasternak <vadimp@nvidia.com>
Pass bus argument to mlxsw_env_init(). The purpose is to get access to
device handle, which is to be provided to error message in case of line
card activation failure.
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
drivers/net/ethernet/mellanox/mlxsw/core.c | 2 +-
drivers/net/ethernet/mellanox/mlxsw/core_env.c | 6 +++++-
drivers/net/ethernet/mellanox/mlxsw/core_env.h | 4 +++-
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 0e92dd91eca4..fc52832241b3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -2175,7 +2175,7 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
if (err)
goto err_thermal_init;
- err = mlxsw_env_init(mlxsw_core, &mlxsw_core->env);
+ err = mlxsw_env_init(mlxsw_core, mlxsw_bus_info, &mlxsw_core->env);
if (err)
goto err_env_init;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
index b3b8a9015cd6..abb54177485c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
@@ -28,6 +28,7 @@ struct mlxsw_env_line_card {
struct mlxsw_env {
struct mlxsw_core *core;
+ const struct mlxsw_bus_info *bus_info;
u8 max_module_count; /* Maximum number of modules per-slot. */
u8 num_of_slots; /* Including the main board. */
struct mutex line_cards_lock; /* Protects line cards. */
@@ -1194,7 +1195,9 @@ mlxsw_env_module_type_set(struct mlxsw_core *mlxsw_core, u8 slot_index)
return 0;
}
-int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
+int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_bus_info *bus_info,
+ struct mlxsw_env **p_env)
{
u8 module_count, num_of_slots, max_module_count;
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
@@ -1221,6 +1224,7 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
return -ENOMEM;
env->core = mlxsw_core;
+ env->bus_info = bus_info;
env->num_of_slots = num_of_slots + 1;
env->max_module_count = max_module_count;
err = mlxsw_env_line_cards_alloc(env);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h
index 6b494c64a4d7..a197e3ae069c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h
@@ -60,7 +60,9 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index,
void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index,
u8 module);
-int mlxsw_env_init(struct mlxsw_core *core, struct mlxsw_env **p_env);
+int mlxsw_env_init(struct mlxsw_core *core,
+ const struct mlxsw_bus_info *bus_info,
+ struct mlxsw_env **p_env);
void mlxsw_env_fini(struct mlxsw_env *env);
#endif
--
2.33.1
^ permalink raw reply related
* [PATCH net-next 4/6] mlxsw: core_env: Add interfaces for line card initialization and de-initialization
From: Ido Schimmel @ 2022-04-19 14:54 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, petrm, jiri, vadimp, mlxsw, Ido Schimmel
In-Reply-To: <20220419145431.2991382-1-idosch@nvidia.com>
From: Vadim Pasternak <vadimp@nvidia.com>
Netdevs for ports found on line cards are registered upon provisioning.
However, user space is not allowed to access the transceiver modules
found on a line card until the line card becomes active.
Therefore, register event operations with the line card core to get
notifications whenever a line card becomes active or inactive.
When user space tries to dump the EEPROM of a transceiver module or reset
it and the corresponding line card is inactive, emit an error
message:
ethtool -m enp1s0nl7p9
netlink error: mlxsw_core: Cannot read EEPROM of module on an inactive line card
netlink error: Input/output error
When user space tries to set the power mode policy of such a transceiver,
cache the configuration and apply it when the line card becomes active. This
is consistent with other port configuration (e.g., MTU setting) that user space
is able to perform while the line card is provisioned, but inactive.
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../net/ethernet/mellanox/mlxsw/core_env.c | 166 +++++++++++++++++-
1 file changed, 165 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
index a9b133d6c2fc..34bec9cd572c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
@@ -23,6 +23,7 @@ struct mlxsw_env_module_info {
struct mlxsw_env_line_card {
u8 module_count;
+ bool active;
struct mlxsw_env_module_info module_info[];
};
@@ -35,6 +36,24 @@ struct mlxsw_env {
struct mlxsw_env_line_card *line_cards[];
};
+static bool __mlxsw_env_linecard_is_active(struct mlxsw_env *mlxsw_env,
+ u8 slot_index)
+{
+ return mlxsw_env->line_cards[slot_index]->active;
+}
+
+static bool mlxsw_env_linecard_is_active(struct mlxsw_env *mlxsw_env,
+ u8 slot_index)
+{
+ bool active;
+
+ mutex_lock(&mlxsw_env->line_cards_lock);
+ active = __mlxsw_env_linecard_is_active(mlxsw_env, slot_index);
+ mutex_unlock(&mlxsw_env->line_cards_lock);
+
+ return active;
+}
+
static struct
mlxsw_env_module_info *mlxsw_env_module_info_get(struct mlxsw_core *mlxsw_core,
u8 slot_index, u8 module)
@@ -47,9 +66,13 @@ mlxsw_env_module_info *mlxsw_env_module_info_get(struct mlxsw_core *mlxsw_core,
static int __mlxsw_env_validate_module_type(struct mlxsw_core *core,
u8 slot_index, u8 module)
{
+ struct mlxsw_env *mlxsw_env = mlxsw_core_env(core);
struct mlxsw_env_module_info *module_info;
int err;
+ if (!__mlxsw_env_linecard_is_active(mlxsw_env, slot_index))
+ return 0;
+
module_info = mlxsw_env_module_info_get(core, slot_index, module);
switch (module_info->type) {
case MLXSW_REG_PMTM_MODULE_TYPE_TWISTED_PAIR:
@@ -269,12 +292,18 @@ int mlxsw_env_get_module_info(struct net_device *netdev,
struct mlxsw_core *mlxsw_core, u8 slot_index,
int module, struct ethtool_modinfo *modinfo)
{
+ struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE];
u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE;
u8 module_rev_id, module_id, diag_mon;
unsigned int read_size;
int err;
+ if (!mlxsw_env_linecard_is_active(mlxsw_env, slot_index)) {
+ netdev_err(netdev, "Cannot read EEPROM of module on an inactive line card\n");
+ return -EIO;
+ }
+
err = mlxsw_env_validate_module_type(mlxsw_core, slot_index, module);
if (err) {
netdev_err(netdev,
@@ -359,6 +388,7 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev,
int module, struct ethtool_eeprom *ee,
u8 *data)
{
+ struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
int offset = ee->offset;
unsigned int read_size;
bool qsfp, cmis;
@@ -368,6 +398,11 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev,
if (!ee->len)
return -EINVAL;
+ if (!mlxsw_env_linecard_is_active(mlxsw_env, slot_index)) {
+ netdev_err(netdev, "Cannot read EEPROM of module on an inactive line card\n");
+ return -EIO;
+ }
+
memset(data, 0, ee->len);
/* Validate module identifier value. */
err = mlxsw_env_validate_cable_ident(mlxsw_core, slot_index, module,
@@ -428,10 +463,17 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core,
const struct ethtool_module_eeprom *page,
struct netlink_ext_ack *extack)
{
+ struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
u32 bytes_read = 0;
u16 device_addr;
int err;
+ if (!mlxsw_env_linecard_is_active(mlxsw_env, slot_index)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot read EEPROM of module on an inactive line card");
+ return -EIO;
+ }
+
err = mlxsw_env_validate_module_type(mlxsw_core, slot_index, module);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "EEPROM is not equipped on port module type");
@@ -497,6 +539,11 @@ int mlxsw_env_reset_module(struct net_device *netdev,
!(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT)))
return 0;
+ if (!mlxsw_env_linecard_is_active(mlxsw_env, slot_index)) {
+ netdev_err(netdev, "Cannot reset module on an inactive line card\n");
+ return -EIO;
+ }
+
mutex_lock(&mlxsw_env->line_cards_lock);
err = __mlxsw_env_validate_module_type(mlxsw_core, slot_index, module);
@@ -543,7 +590,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
struct mlxsw_env_module_info *module_info;
char mcion_pl[MLXSW_REG_MCION_LEN];
u32 status_bits;
- int err;
+ int err = 0;
mutex_lock(&mlxsw_env->line_cards_lock);
@@ -556,6 +603,10 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
params->policy = module_info->power_mode_policy;
+ /* Avoid accessing an inactive line card, as it will result in an error. */
+ if (!__mlxsw_env_linecard_is_active(mlxsw_env, slot_index))
+ goto out;
+
mlxsw_reg_mcion_pack(mcion_pl, slot_index, module);
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl);
if (err) {
@@ -617,8 +668,16 @@ static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core,
bool low_power,
struct netlink_ext_ack *extack)
{
+ struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
int err;
+ /* Avoid accessing an inactive line card, as it will result in an error.
+ * Cached configuration will be applied by mlxsw_env_got_active() when
+ * line card becomes active.
+ */
+ if (!__mlxsw_env_linecard_is_active(mlxsw_env, slot_index))
+ return 0;
+
err = mlxsw_env_module_enable_set(mlxsw_core, slot_index, module, false);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Failed to disable module");
@@ -1208,6 +1267,98 @@ mlxsw_env_module_type_set(struct mlxsw_core *mlxsw_core, u8 slot_index)
return 0;
}
+static void
+mlxsw_env_linecard_modules_power_mode_apply(struct mlxsw_core *mlxsw_core,
+ struct mlxsw_env *env,
+ u8 slot_index)
+{
+ int i;
+
+ for (i = 0; i < env->line_cards[slot_index]->module_count; i++) {
+ enum ethtool_module_power_mode_policy policy;
+ struct mlxsw_env_module_info *module_info;
+ struct netlink_ext_ack extack;
+ int err;
+
+ module_info = &env->line_cards[slot_index]->module_info[i];
+ policy = module_info->power_mode_policy;
+ err = mlxsw_env_set_module_power_mode_apply(mlxsw_core,
+ slot_index, i,
+ policy, &extack);
+ if (err)
+ dev_err(env->bus_info->dev, "%s\n", extack._msg);
+ }
+}
+
+static void
+mlxsw_env_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, void *priv)
+{
+ struct mlxsw_env *mlxsw_env = priv;
+ char mgpir_pl[MLXSW_REG_MGPIR_LEN];
+ int err;
+
+ mutex_lock(&mlxsw_env->line_cards_lock);
+ if (__mlxsw_env_linecard_is_active(mlxsw_env, slot_index))
+ goto out_unlock;
+
+ mlxsw_reg_mgpir_pack(mgpir_pl, slot_index);
+ err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mgpir), mgpir_pl);
+ if (err)
+ goto out_unlock;
+
+ mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
+ &mlxsw_env->line_cards[slot_index]->module_count,
+ NULL);
+
+ err = mlxsw_env_module_event_enable(mlxsw_env, slot_index);
+ if (err) {
+ dev_err(mlxsw_env->bus_info->dev, "Failed to enable port module events for line card in slot %d\n",
+ slot_index);
+ goto err_mlxsw_env_module_event_enable;
+ }
+ err = mlxsw_env_module_type_set(mlxsw_env->core, slot_index);
+ if (err) {
+ dev_err(mlxsw_env->bus_info->dev, "Failed to set modules' type for line card in slot %d\n",
+ slot_index);
+ goto err_type_set;
+ }
+
+ mlxsw_env->line_cards[slot_index]->active = true;
+ /* Apply power mode policy. */
+ mlxsw_env_linecard_modules_power_mode_apply(mlxsw_core, mlxsw_env,
+ slot_index);
+ mutex_unlock(&mlxsw_env->line_cards_lock);
+
+ return;
+
+err_type_set:
+ mlxsw_env_module_event_disable(mlxsw_env, slot_index);
+err_mlxsw_env_module_event_enable:
+out_unlock:
+ mutex_unlock(&mlxsw_env->line_cards_lock);
+}
+
+static void
+mlxsw_env_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
+ void *priv)
+{
+ struct mlxsw_env *mlxsw_env = priv;
+
+ mutex_lock(&mlxsw_env->line_cards_lock);
+ if (!__mlxsw_env_linecard_is_active(mlxsw_env, slot_index))
+ goto out_unlock;
+ mlxsw_env->line_cards[slot_index]->active = false;
+ mlxsw_env_module_event_disable(mlxsw_env, slot_index);
+ mlxsw_env->line_cards[slot_index]->module_count = 0;
+out_unlock:
+ mutex_unlock(&mlxsw_env->line_cards_lock);
+}
+
+static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = {
+ .got_active = mlxsw_env_got_active,
+ .got_inactive = mlxsw_env_got_inactive,
+};
+
int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *bus_info,
struct mlxsw_env **p_env)
@@ -1247,6 +1398,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
mutex_init(&env->line_cards_lock);
*p_env = env;
+ err = mlxsw_linecards_event_ops_register(env->core,
+ &mlxsw_env_event_ops, env);
+ if (err)
+ goto err_linecards_event_ops_register;
+
err = mlxsw_env_temp_warn_event_register(mlxsw_core);
if (err)
goto err_temp_warn_event_register;
@@ -1271,6 +1427,8 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
if (err)
goto err_type_set;
+ env->line_cards[0]->active = true;
+
return 0;
err_type_set:
@@ -1280,6 +1438,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
err_module_plug_event_register:
mlxsw_env_temp_warn_event_unregister(env);
err_temp_warn_event_register:
+ mlxsw_linecards_event_ops_unregister(env->core,
+ &mlxsw_env_event_ops, env);
+err_linecards_event_ops_register:
mutex_destroy(&env->line_cards_lock);
mlxsw_env_line_cards_free(env);
err_mlxsw_env_line_cards_alloc:
@@ -1289,11 +1450,14 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
void mlxsw_env_fini(struct mlxsw_env *env)
{
+ env->line_cards[0]->active = false;
mlxsw_env_module_event_disable(env, 0);
mlxsw_env_module_plug_event_unregister(env);
/* Make sure there is no more event work scheduled. */
mlxsw_core_flush_owq();
mlxsw_env_temp_warn_event_unregister(env);
+ mlxsw_linecards_event_ops_unregister(env->core,
+ &mlxsw_env_event_ops, env);
mutex_destroy(&env->line_cards_lock);
mlxsw_env_line_cards_free(env);
kfree(env);
--
2.33.1
^ permalink raw reply related
* [PATCH net-next 3/6] mlxsw: core_env: Split module power mode setting to a separate function
From: Ido Schimmel @ 2022-04-19 14:54 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, petrm, jiri, vadimp, mlxsw, Ido Schimmel
In-Reply-To: <20220419145431.2991382-1-idosch@nvidia.com>
From: Vadim Pasternak <vadimp@nvidia.com>
Move the code that applies the module power mode to the device to a
separate function. This function will be invoked by the next patch to
set the power mode on transceiver modules found on a line card when the
line card becomes active.
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../net/ethernet/mellanox/mlxsw/core_env.c | 41 ++++++++++++-------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
index abb54177485c..a9b133d6c2fc 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
@@ -648,25 +648,16 @@ static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core,
return err;
}
-int
-mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
- u8 module,
- enum ethtool_module_power_mode_policy policy,
- struct netlink_ext_ack *extack)
+static int
+mlxsw_env_set_module_power_mode_apply(struct mlxsw_core *mlxsw_core,
+ u8 slot_index, u8 module,
+ enum ethtool_module_power_mode_policy policy,
+ struct netlink_ext_ack *extack)
{
- struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
struct mlxsw_env_module_info *module_info;
bool low_power;
int err = 0;
- if (policy != ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH &&
- policy != ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) {
- NL_SET_ERR_MSG_MOD(extack, "Unsupported power mode policy");
- return -EOPNOTSUPP;
- }
-
- mutex_lock(&mlxsw_env->line_cards_lock);
-
err = __mlxsw_env_validate_module_type(mlxsw_core, slot_index, module);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
@@ -691,7 +682,29 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
out_set_policy:
module_info->power_mode_policy = policy;
out:
+ return err;
+}
+
+int
+mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
+ u8 module,
+ enum ethtool_module_power_mode_policy policy,
+ struct netlink_ext_ack *extack)
+{
+ struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
+ int err;
+
+ if (policy != ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH &&
+ policy != ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) {
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported power mode policy");
+ return -EOPNOTSUPP;
+ }
+
+ mutex_lock(&mlxsw_env->line_cards_lock);
+ err = mlxsw_env_set_module_power_mode_apply(mlxsw_core, slot_index,
+ module, policy, extack);
mutex_unlock(&mlxsw_env->line_cards_lock);
+
return err;
}
EXPORT_SYMBOL(mlxsw_env_set_module_power_mode);
--
2.33.1
^ permalink raw reply related
* [PATCH net-next 5/6] mlxsw: core_thermal: Add interfaces for line card initialization and de-initialization
From: Ido Schimmel @ 2022-04-19 14:54 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, petrm, jiri, vadimp, mlxsw, Ido Schimmel
In-Reply-To: <20220419145431.2991382-1-idosch@nvidia.com>
From: Vadim Pasternak <vadimp@nvidia.com>
Add callback functions for line card thermal area initialization and
de-initialization. Each line card is associated with the relevant
thermal area, which may contain thermal zones for cages and gearboxes
found on this line card.
The line card thermal initialization / de-initialization APIs are to be
called when line card is set to active / inactive state by
got_active() / got_inactive() callbacks from line card state machine.
For example thermal zone for module #9 located at line card #7 will
have type:
mlxsw-lc7-module9.
And thermal zone for gearbox #2 located at line card #5 will have type:
mlxsw-lc5-gearbox2.
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../ethernet/mellanox/mlxsw/core_thermal.c | 74 +++++++++++++++++++
1 file changed, 74 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index e8ce26a1d483..3548fe1df7c8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -90,6 +90,7 @@ struct mlxsw_thermal_area {
struct mlxsw_thermal_module *tz_gearbox_arr;
u8 tz_gearbox_num;
u8 slot_index;
+ bool active;
};
struct mlxsw_thermal {
@@ -913,6 +914,64 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal,
kfree(area->tz_gearbox_arr);
}
+static void
+mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
+ void *priv)
+{
+ struct mlxsw_thermal *thermal = priv;
+ struct mlxsw_thermal_area *linecard;
+ int err;
+
+ linecard = &thermal->line_cards[slot_index];
+
+ if (linecard->active)
+ return;
+
+ linecard->slot_index = slot_index;
+ err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core,
+ thermal, linecard);
+ if (err) {
+ dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card modules in slot %d\n",
+ slot_index);
+ return;
+ }
+
+ err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev,
+ thermal->core, thermal, linecard);
+ if (err) {
+ dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card gearboxes in slot %d\n",
+ slot_index);
+ goto err_thermal_linecard_gearboxes_init;
+ }
+
+ linecard->active = true;
+
+ return;
+
+err_thermal_linecard_gearboxes_init:
+ mlxsw_thermal_modules_fini(thermal, linecard);
+}
+
+static void
+mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
+ void *priv)
+{
+ struct mlxsw_thermal *thermal = priv;
+ struct mlxsw_thermal_area *linecard;
+
+ linecard = &thermal->line_cards[slot_index];
+ if (!linecard->active)
+ return;
+ linecard->active = false;
+ mlxsw_thermal_gearboxes_fini(thermal, linecard);
+ mlxsw_thermal_modules_fini(thermal, linecard);
+}
+
+static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = {
+ .got_active = mlxsw_thermal_got_active,
+ .got_inactive = mlxsw_thermal_got_inactive,
+};
+
int mlxsw_thermal_init(struct mlxsw_core *core,
const struct mlxsw_bus_info *bus_info,
struct mlxsw_thermal **p_thermal)
@@ -1018,14 +1077,25 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
if (err)
goto err_thermal_gearboxes_init;
+ err = mlxsw_linecards_event_ops_register(core,
+ &mlxsw_thermal_event_ops,
+ thermal);
+ if (err)
+ goto err_linecards_event_ops_register;
+
err = thermal_zone_device_enable(thermal->tzdev);
if (err)
goto err_thermal_zone_device_enable;
+ thermal->line_cards[0].active = true;
*p_thermal = thermal;
return 0;
err_thermal_zone_device_enable:
+ mlxsw_linecards_event_ops_unregister(thermal->core,
+ &mlxsw_thermal_event_ops,
+ thermal);
+err_linecards_event_ops_register:
mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
err_thermal_gearboxes_init:
mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
@@ -1049,6 +1119,10 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
{
int i;
+ thermal->line_cards[0].active = false;
+ mlxsw_linecards_event_ops_unregister(thermal->core,
+ &mlxsw_thermal_event_ops,
+ thermal);
mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
if (thermal->tzdev) {
--
2.33.1
^ permalink raw reply related
* [PATCH net-next 6/6] mlxsw: core_hwmon: Add interfaces for line card initialization and de-initialization
From: Ido Schimmel @ 2022-04-19 14:54 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, petrm, jiri, vadimp, mlxsw, Ido Schimmel
In-Reply-To: <20220419145431.2991382-1-idosch@nvidia.com>
From: Vadim Pasternak <vadimp@nvidia.com>
Add callback functions for line card 'hwmon' initialization and
de-initialization. Each line card is associated with the relevant
'hwmon' device, which may contain thermal attributes for the cages
and gearboxes found on this line card.
The line card 'hwmon' initialization / de-initialization APIs are to be
called when line card is set to active / inactive state by
got_active() / got_inactive() callbacks from line card state machine.
For example cage temperature for module #9 located at line card #7 will
be exposed by utility 'sensors' like:
linecard#07
front panel 009: +32.0C (crit = +70.0C, emerg = +80.0C)
And temperature for gearbox #3 located at line card #5 will be exposed
like:
linecard#05
gearbox 003: +41.0C (highest = +41.0C)
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../net/ethernet/mellanox/mlxsw/core_hwmon.c | 84 +++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index fff6f248d6f7..70735068cf29 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -19,6 +19,7 @@
#define MLXSW_HWMON_ATTR_PER_SENSOR 3
#define MLXSW_HWMON_ATTR_PER_MODULE 7
#define MLXSW_HWMON_ATTR_PER_GEARBOX 4
+#define MLXSW_HWMON_DEV_NAME_LEN_MAX 16
#define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_SENSORS_MAX_COUNT * MLXSW_HWMON_ATTR_PER_SENSOR + \
MLXSW_HWMON_MODULES_MAX_COUNT * MLXSW_HWMON_ATTR_PER_MODULE + \
@@ -41,6 +42,7 @@ static int mlxsw_hwmon_get_attr_index(int index, int count)
}
struct mlxsw_hwmon_dev {
+ char name[MLXSW_HWMON_DEV_NAME_LEN_MAX];
struct mlxsw_hwmon *hwmon;
struct device *hwmon_dev;
struct attribute_group group;
@@ -51,6 +53,7 @@ struct mlxsw_hwmon_dev {
u8 sensor_count;
u8 module_sensor_max;
u8 slot_index;
+ bool active;
};
struct mlxsw_hwmon {
@@ -780,6 +783,75 @@ static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev)
return 0;
}
+static void
+mlxsw_hwmon_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
+ void *priv)
+{
+ struct mlxsw_hwmon *hwmon = priv;
+ struct mlxsw_hwmon_dev *linecard;
+ struct device *dev;
+ int err;
+
+ dev = hwmon->bus_info->dev;
+ linecard = &hwmon->line_cards[slot_index];
+ if (linecard->active)
+ return;
+ /* For the main board, module sensor indexes start from 1, sensor index
+ * 0 is used for the ASIC. Use the same numbering for line cards.
+ */
+ linecard->sensor_count = 1;
+ linecard->slot_index = slot_index;
+ linecard->hwmon = hwmon;
+ err = mlxsw_hwmon_module_init(linecard);
+ if (err) {
+ dev_err(dev, "Failed to configure hwmon objects for line card modules in slot %d\n",
+ slot_index);
+ return;
+ }
+
+ err = mlxsw_hwmon_gearbox_init(linecard);
+ if (err) {
+ dev_err(dev, "Failed to configure hwmon objects for line card gearboxes in slot %d\n",
+ slot_index);
+ return;
+ }
+
+ linecard->groups[0] = &linecard->group;
+ linecard->group.attrs = linecard->attrs;
+ sprintf(linecard->name, "%s#%02u", "linecard", slot_index);
+ linecard->hwmon_dev =
+ hwmon_device_register_with_groups(dev, linecard->name,
+ linecard, linecard->groups);
+ if (IS_ERR(linecard->hwmon_dev)) {
+ dev_err(dev, "Failed to register hwmon objects for line card in slot %d\n",
+ slot_index);
+ return;
+ }
+
+ linecard->active = true;
+}
+
+static void
+mlxsw_hwmon_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
+ void *priv)
+{
+ struct mlxsw_hwmon *hwmon = priv;
+ struct mlxsw_hwmon_dev *linecard;
+
+ linecard = &hwmon->line_cards[slot_index];
+ if (!linecard->active)
+ return;
+ linecard->active = false;
+ hwmon_device_unregister(linecard->hwmon_dev);
+ /* Reset attributes counter */
+ linecard->attrs_count = 0;
+}
+
+static struct mlxsw_linecards_event_ops mlxsw_hwmon_event_ops = {
+ .got_active = mlxsw_hwmon_got_active,
+ .got_inactive = mlxsw_hwmon_got_inactive,
+};
+
int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *mlxsw_bus_info,
struct mlxsw_hwmon **p_hwmon)
@@ -836,10 +908,19 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
goto err_hwmon_register;
}
+ err = mlxsw_linecards_event_ops_register(mlxsw_hwmon->core,
+ &mlxsw_hwmon_event_ops,
+ mlxsw_hwmon);
+ if (err)
+ goto err_linecards_event_ops_register;
+
mlxsw_hwmon->line_cards[0].hwmon_dev = hwmon_dev;
+ mlxsw_hwmon->line_cards[0].active = true;
*p_hwmon = mlxsw_hwmon;
return 0;
+err_linecards_event_ops_register:
+ hwmon_device_unregister(mlxsw_hwmon->line_cards[0].hwmon_dev);
err_hwmon_register:
err_temp_gearbox_init:
err_temp_module_init:
@@ -851,6 +932,9 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
{
+ mlxsw_hwmon->line_cards[0].active = false;
+ mlxsw_linecards_event_ops_unregister(mlxsw_hwmon->core,
+ &mlxsw_hwmon_event_ops, mlxsw_hwmon);
hwmon_device_unregister(mlxsw_hwmon->line_cards[0].hwmon_dev);
kfree(mlxsw_hwmon);
}
--
2.33.1
^ permalink raw reply related
* Re: [PATCH net-next 03/12] dt-bindings: net: pcs: add bindings for Renesas RZ/N1 MII converter
From: Clément Léger @ 2022-04-19 15:00 UTC (permalink / raw)
To: Rob Herring
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
David S . Miller, Jakub Kicinski, Paolo Abeni,
Krzysztof Kozlowski, Geert Uytterhoeven, Magnus Damm,
Heiner Kallweit, Russell King, Thomas Petazzoni, Herve Codina,
Miquèl Raynal, Milan Stevanovic, Jimmy Lalande, linux-kernel,
devicetree, linux-renesas-soc, netdev
In-Reply-To: <Yl68k22fUw7uBgV9@robh.at.kernel.org>
Le Tue, 19 Apr 2022 08:43:47 -0500,
Rob Herring <robh@kernel.org> a écrit :
> > + clocks:
> > + items:
> > + - description: MII reference clock
> > + - description: RGMII reference clock
> > + - description: RMII reference clock
> > + - description: AHB clock used for the MII converter register interface
> > +
> > + renesas,miic-cfg-mode:
> > + description: MII mux configuration mode. This value should use one of the
> > + value defined in dt-bindings/net/pcs-rzn1-miic.h.
>
> Describe possible values here as constraints. At present, I don't see
> the point of this property if there is only 1 possible value and it is
> required.
The ethernet subsystem contains a number of internal muxes that allows
to configure ethernet routing. This configuration option allows to set
the register that configure these muxes.
After talking with Andrew, I considered moving to something like this:
eth-miic@44030000 {
compatible = "renesas,rzn1-miic";
mii_conv1: mii-conv-1 {
renesas,miic-input = <MIIC_GMAC1_PORT>;
port = <1>;
};
mii_conv2: mii-conv-2 {
renesas,miic-input = <MIIC_SWITCHD_PORT>;
port = <2>;
};
...
};
Which would allow embedding the configuration inside the port
sub-nodes. Moreover, it allows a better validation of the values using
the schema validation directly since only a limited number of values
are allowed for each port.
>
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > +
> > +patternProperties:
> > + "^mii-conv@[0-4]$":
> > + type: object
>
> additionalProperties: false
>
> > + description: MII converter port
> > +
> > + properties:
> > + reg:
> > + maxItems: 1
>
> Why do you need sub-nodes? They don't have any properties. A simple mask
> property could tell you which ports are present/active/enabled if that's
> what you are tracking. Or the SoC specific compatibles you need to add
> can imply the ports if they are SoC specific.
The MACs are using phandles to these sub-nodes to query a specific MII
converter port PCS:
switch@44050000 {
compatible = "renesas,rzn1-a5psw";
ports {
port@0 {
reg = <0>;
label = "lan0";
phy-handle = <&switch0phy3>;
pcs-handle = <&mii_conv4>;
};
};
};
According to Andrew, this is not a good idea to represent the PCS as a
bus since it is indeed not a bus. I could also switch to something like
pcs-handle = <ð_mii 4> but i'm not sure what you'd prefer. We could
also remove this from the device-tree and consider each driver to
request the MII ouput to be configured using something like this for
instance:
miic_request_pcs(pcs_np, miic_port_nr, MIIC_SWITCHD_PORT);
But I'm not really fan of this because it requires the drivers to
assume some specificities of the MII converter (port number are not in
the same order of the switch for instance) and thus I would prefer this
to be in the device-tree.
Let me know if you can think of something that would suit you
better but keep in mind that I need to correctly match a switch/MAC
port with a PCS port and that I also need to configure MII internal
muxes.
For more information, you can look at section 8 of the manual at [1].
Thanks,
[1]
https://www.renesas.com/us/en/document/mah/rzn1d-group-rzn1s-group-rzn1l-group-users-manual-system-introduction-multiplexing-electrical-and
--
Clément Léger,
Embedded Linux and Kernel engineer at Bootlin
https://bootlin.com
^ permalink raw reply
* Re: [PATCH v5 net-next 1/4] rtnetlink: return ENODEV when ifname does not exist and group is given
From: Stephen Hemminger @ 2022-04-19 15:04 UTC (permalink / raw)
To: Florent Fourcot; +Cc: netdev, cong.wang, edumazet, Brian Baboch
In-Reply-To: <d63921e9-2306-a153-48fe-a1f65157aafa@wifirst.fr>
On Tue, 19 Apr 2022 09:29:37 +0200
Florent Fourcot <florent.fourcot@wifirst.fr> wrote:
> Hello,
>
>
> >> + if (link_specified)
> >> + return -ENODEV;
> >
> > Please add extack error message as well?
> > Simple errno's are harder to debug.
>
>
> What kind of message have you in mind for that one? Something like
> "Interface not found" does not have extra information for ENODEV code.
>
> At this place, one gave interface index or interface name, and nothing
> matched.
Not sure how code gets here. Maybe "interface name required"
^ permalink raw reply
* [PATCH net-next 03/17] can: Fix Links to Technologic Systems web resources
From: Marc Kleine-Budde @ 2022-04-19 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel, Kris Bahnsen, Marc Kleine-Budde
In-Reply-To: <20220419152554.2925353-1-mkl@pengutronix.de>
From: Kris Bahnsen <kris@embeddedTS.com>
Technologic Systems has rebranded as embeddedTS with the current
domain eventually going offline. Update web/doc URLs to correct
resource locations.
Link: https://lore.kernel.org/all/20220329201229.16279-1-kris@embeddedTS.com
Signed-off-by: Kris Bahnsen <kris@embeddedTS.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/sja1000/Kconfig | 2 +-
drivers/net/can/sja1000/tscan1.c | 7 +++----
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 110071b26921..4b2f9cb17fc3 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -107,7 +107,7 @@ config CAN_TSCAN1
depends on ISA
help
This driver is for Technologic Systems' TSCAN-1 PC104 boards.
- http://www.embeddedarm.com/products/board-detail.php?product=TS-CAN1
+ https://www.embeddedts.com/products/TS-CAN1
The driver supports multiple boards and automatically configures them:
PLD IO base addresses are read from jumpers JP1 and JP2,
IRQ numbers are read from jumpers JP4 and JP5,
diff --git a/drivers/net/can/sja1000/tscan1.c b/drivers/net/can/sja1000/tscan1.c
index 3dbba8d61afb..f3862bed3d40 100644
--- a/drivers/net/can/sja1000/tscan1.c
+++ b/drivers/net/can/sja1000/tscan1.c
@@ -5,10 +5,9 @@
* Copyright 2010 Andre B. Oliveira
*/
-/*
- * References:
- * - Getting started with TS-CAN1, Technologic Systems, Jun 2009
- * http://www.embeddedarm.com/documentation/ts-can1-manual.pdf
+/* References:
+ * - Getting started with TS-CAN1, Technologic Systems, Feb 2022
+ * https://docs.embeddedts.com/TS-CAN1
*/
#include <linux/init.h>
--
2.35.1
^ permalink raw reply related
* [PATCH net-next 04/17] can: mscan: mpc5xxx_can: Prepare cleanup of powerpc's asm/prom.h
From: Marc Kleine-Budde @ 2022-04-19 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel, Christophe Leroy,
Marc Kleine-Budde
In-Reply-To: <20220419152554.2925353-1-mkl@pengutronix.de>
From: Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc's asm/prom.h brings some headers that it doesn't need itself.
In order to clean it up, first add missing headers in users of
asm/prom.h
Link: https://lore.kernel.org/all/878888f9057ad2f66ca0621a0007472bf57f3e3d.1648833432.git.christophe.leroy@csgroup.eu
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/mscan/mpc5xxx_can.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index de4ddf79ba9b..65ba6697bd7d 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -14,6 +14,8 @@
#include <linux/platform_device.h>
#include <linux/netdevice.h>
#include <linux/can/dev.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
#include <linux/clk.h>
--
2.35.1
^ permalink raw reply related
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