Message ID | 5CCBD90FF2823C29+20240804124841.71177-8-mengyuanlou@net-swift.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net-next,v5,01/10] net: libwx: Add malibox api for wangxun pf drivers | expand |
Hi Mengyuan, kernel test robot noticed the following build errors: [auto build test ERROR on net-next/main] url: https://github.com/intel-lab-lkp/linux/commits/Mengyuan-Lou/net-libwx-Add-sriov-api-for-wangxun-nics/20240804-214836 base: net-next/main patch link: https://lore.kernel.org/r/5CCBD90FF2823C29%2B20240804124841.71177-8-mengyuanlou%40net-swift.com patch subject: [PATCH net-next v5 07/10] net: libwx: allocate devlink for devlink port config: loongarch-defconfig (https://download.01.org/0day-ci/archive/20240805/202408051455.A9boD1Oe-lkp@intel.com/config) compiler: loongarch64-linux-gcc (GCC) 14.1.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240805/202408051455.A9boD1Oe-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202408051455.A9boD1Oe-lkp@intel.com/ All errors (new ones prefixed by >>): loongarch64-linux-ld: drivers/net/ethernet/wangxun/libwx/wx_devlink.o: in function `wx_devlink_free': >> wx_devlink.c:(.text+0x58): undefined reference to `devlink_unregister' >> loongarch64-linux-ld: wx_devlink.c:(.text+0x6c): undefined reference to `devlink_free' loongarch64-linux-ld: drivers/net/ethernet/wangxun/libwx/wx_devlink.o: in function `wx_devlink_create_pf_port': >> wx_devlink.c:(.text+0xa0): undefined reference to `priv_to_devlink' >> loongarch64-linux-ld: wx_devlink.c:(.text+0xfc): undefined reference to `devlink_port_attrs_set' >> loongarch64-linux-ld: wx_devlink.c:(.text+0x110): undefined reference to `devlink_port_register_with_ops' loongarch64-linux-ld: drivers/net/ethernet/wangxun/libwx/wx_devlink.o: in function `wx_devlink_destroy_pf_port': >> wx_devlink.c:(.text+0x174): undefined reference to `devl_port_unregister' loongarch64-linux-ld: drivers/net/ethernet/wangxun/libwx/wx_devlink.o: in function `wx_create_devlink': >> wx_devlink.c:(.text+0x2a0): undefined reference to `devlink_alloc_ns' >> loongarch64-linux-ld: wx_devlink.c:(.text+0x2d4): undefined reference to `devlink_unregister' loongarch64-linux-ld: wx_devlink.c:(.text+0x2dc): undefined reference to `devlink_free' >> loongarch64-linux-ld: wx_devlink.c:(.text+0x304): undefined reference to `devlink_register' >> loongarch64-linux-ld: wx_devlink.c:(.text+0x31c): undefined reference to `devlink_priv' loongarch64-linux-ld: drivers/net/ethernet/wangxun/libwx/wx_devlink.o: in function `wx_devlink_create_vf_port': wx_devlink.c:(.text+0x354): undefined reference to `priv_to_devlink' loongarch64-linux-ld: wx_devlink.c:(.text+0x3d0): undefined reference to `devlink_port_attrs_set' >> loongarch64-linux-ld: wx_devlink.c:(.text+0x3e8): undefined reference to `devl_port_register_with_ops' loongarch64-linux-ld: drivers/net/ethernet/wangxun/libwx/wx_devlink.o: in function `wx_devlink_destroy_vf_port': wx_devlink.c:(.text+0x47c): undefined reference to `devl_port_unregister'
On Sun, Aug 04, 2024 at 08:48:38PM +0800, Mengyuan Lou wrote: > Make devlink allocation function generic to use it for PF and for VF. > > Add function for PF/VF devlink port creation. It will be used in > wangxun NICs. > > Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com> ... > diff --git a/drivers/net/ethernet/wangxun/libwx/wx_devlink.c b/drivers/net/ethernet/wangxun/libwx/wx_devlink.c > new file mode 100644 > index 000000000000..b39da37c0842 > --- /dev/null > +++ b/drivers/net/ethernet/wangxun/libwx/wx_devlink.c > @@ -0,0 +1,208 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ > + > +#include <linux/vmalloc.h> > +#include <linux/pci.h> > + > +#include "wx_type.h" > +#include "wx_sriov.h" > +#include "wx_devlink.h" > + > +static const struct devlink_ops wx_pf_devlink_ops = { > +}; > + > +static void wx_devlink_free(void *devlink_ptr) > +{ > + devlink_unregister((struct devlink *)devlink_ptr); > + devlink_free((struct devlink *)devlink_ptr); > +} > + > +struct wx_dl_priv *wx_create_devlink(struct device *dev) > +{ > + struct devlink *devlink; > + > + devlink = devlink_alloc(&wx_pf_devlink_ops, sizeof(devlink), dev); Perhaps this should be sizeof(wx_dl_priv *) ? Flagged by Coccinelle. > + if (!devlink) > + return NULL; > + > + /* Add an action to teardown the devlink when unwinding the driver */ > + if (devm_add_action_or_reset(dev, wx_devlink_free, devlink)) > + return NULL; > + > + devlink_register(devlink); > + > + return devlink_priv(devlink); > +} > +EXPORT_SYMBOL(wx_create_devlink); ...
Sun, Aug 04, 2024 at 02:48:38PM CEST, mengyuanlou@net-swift.com wrote: >Make devlink allocation function generic to use it for PF and for VF. > >Add function for PF/VF devlink port creation. It will be used in >wangxun NICs. > >Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com> Interesting how you decide to split the patches. Seems a bit odd to me to have all you have here in one patch and for example eswitch mode set in a separate patch. Anyway... >--- > drivers/net/ethernet/wangxun/libwx/Makefile | 2 +- > .../net/ethernet/wangxun/libwx/wx_devlink.c | 208 ++++++++++++++++++ > .../net/ethernet/wangxun/libwx/wx_devlink.h | 13 ++ > drivers/net/ethernet/wangxun/libwx/wx_sriov.c | 13 +- > drivers/net/ethernet/wangxun/libwx/wx_sriov.h | 1 + > drivers/net/ethernet/wangxun/libwx/wx_type.h | 14 ++ > 6 files changed, 249 insertions(+), 2 deletions(-) > create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_devlink.c > create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_devlink.h > >diff --git a/drivers/net/ethernet/wangxun/libwx/Makefile b/drivers/net/ethernet/wangxun/libwx/Makefile >index 5b996d973d29..643a5e947ba9 100644 >--- a/drivers/net/ethernet/wangxun/libwx/Makefile >+++ b/drivers/net/ethernet/wangxun/libwx/Makefile >@@ -4,4 +4,4 @@ > > obj-$(CONFIG_LIBWX) += libwx.o > >-libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_mbx.o wx_sriov.o >+libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_mbx.o wx_sriov.o wx_devlink.o >diff --git a/drivers/net/ethernet/wangxun/libwx/wx_devlink.c b/drivers/net/ethernet/wangxun/libwx/wx_devlink.c >new file mode 100644 >index 000000000000..b39da37c0842 >--- /dev/null >+++ b/drivers/net/ethernet/wangxun/libwx/wx_devlink.c >@@ -0,0 +1,208 @@ >+// SPDX-License-Identifier: GPL-2.0 >+/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ >+ >+#include <linux/vmalloc.h> >+#include <linux/pci.h> >+ >+#include "wx_type.h" >+#include "wx_sriov.h" >+#include "wx_devlink.h" >+ >+static const struct devlink_ops wx_pf_devlink_ops = { >+}; >+ >+static void wx_devlink_free(void *devlink_ptr) "void *data" perhaps to follow the naming this usually has? struct devlink *devlink = data; devlink_unregister(devlink_ptr); devlink_free(devlink); ? Certainly, you don't need to cast from (void*). >+{ >+ devlink_unregister((struct devlink *)devlink_ptr); >+ devlink_free((struct devlink *)devlink_ptr); >+} >+ >+struct wx_dl_priv *wx_create_devlink(struct device *dev) >+{ >+ struct devlink *devlink; >+ >+ devlink = devlink_alloc(&wx_pf_devlink_ops, sizeof(devlink), dev); sizeof(struct wx) perhaps? Sizeof(devlink) is certainly wrong. >+ if (!devlink) >+ return NULL; >+ >+ /* Add an action to teardown the devlink when unwinding the driver */ >+ if (devm_add_action_or_reset(dev, wx_devlink_free, devlink)) >+ return NULL; >+ >+ devlink_register(devlink); >+ >+ return devlink_priv(devlink); >+} >+EXPORT_SYMBOL(wx_create_devlink); >+ >+/** >+ * wx_devlink_set_switch_id - Set unique switch id based on pci dsn >+ * @wx: the PF to create a devlink port for >+ * @ppid: struct with switch id information >+ */ >+static void wx_devlink_set_switch_id(struct wx *wx, >+ struct netdev_phys_item_id *ppid) >+{ >+ struct pci_dev *pdev = wx->pdev; >+ u64 id; >+ >+ id = pci_get_dsn(pdev); >+ >+ ppid->id_len = sizeof(id); >+ put_unaligned_be64(id, &ppid->id); >+} >+ >+/** >+ * wx_devlink_create_pf_port - Create a devlink port for this PF >+ * @wx: the PF to create a devlink port for >+ * >+ * Create and register a devlink_port for this PF. >+ * This function has to be called under devl_lock. >+ * >+ * Return: zero on success or an error code on failure. >+ */ >+int wx_devlink_create_pf_port(struct wx *wx) >+{ >+ struct devlink *devlink = priv_to_devlink(wx->dl_priv); >+ struct devlink_port_attrs attrs = {}; >+ int err; >+ >+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; >+ attrs.phys.port_number = wx->bus.func; Interesting. bus.func is 0, 1? You have a port label "0" on you nic. Quite odd. Also, if you pass this through to VM, func can be anything, can't it? You have to get port_number some place else. Perhaps your FW can tell you? >+ wx_devlink_set_switch_id(wx, &attrs.switch_id); >+ devlink_port_attrs_set(&wx->devlink_port, &attrs); >+ err = devlink_port_register(devlink, &wx->devlink_port, 0); >+ if (err) { >+ wx_err(wx, "Failed to create devlink port for PF%d, error %d\n", >+ wx->bus.func, err); >+ return err; >+ } >+ >+ return 0; >+} >+EXPORT_SYMBOL(wx_devlink_create_pf_port); >+ >+/** >+ * wx_devlink_destroy_pf_port - Destroy the devlink_port for this PF >+ * @wx: the PF to cleanup >+ * >+ * Unregisters the devlink_port structure associated with this PF. >+ * This function has to be called under devl_lock. >+ */ >+void wx_devlink_destroy_pf_port(struct wx *wx) >+{ >+ devl_port_unregister(&wx->devlink_port); >+} >+EXPORT_SYMBOL(wx_devlink_destroy_pf_port); >+ >+/** >+ * wx_devlink_port_get_vf_fn_mac - .port_fn_hw_addr_get devlink handler >+ * @port: devlink port structure >+ * @hw_addr: MAC address of the port >+ * @hw_addr_len: length of MAC address >+ * @extack: extended netdev ack structure >+ * >+ * Callback for the devlink .port_fn_hw_addr_get operation >+ * Return: zero on success or an error code on failure. >+ */ >+static int wx_devlink_port_get_vf_fn_mac(struct devlink_port *port, >+ u8 *hw_addr, int *hw_addr_len, >+ struct netlink_ext_ack *extack) >+{ >+ struct vf_data_storage *vfinfo = container_of(port, >+ struct vf_data_storage, >+ devlink_port); >+ struct devlink_port_attrs *attrs = &port->attrs; >+ struct devlink_port_pci_vf_attrs *pci_vf; >+ struct wx *wx = vfinfo->vf_priv_wx; >+ u16 vf_id; >+ >+ pci_vf = &attrs->pci_vf; >+ vf_id = pci_vf->vf; >+ >+ ether_addr_copy(hw_addr, wx->vfinfo[vf_id].vf_mac_addr); >+ *hw_addr_len = ETH_ALEN; >+ >+ return 0; >+} >+ >+/** >+ * wx_devlink_port_set_vf_fn_mac - .port_fn_hw_addr_set devlink handler >+ * @port: devlink port structure >+ * @hw_addr: MAC address of the port >+ * @hw_addr_len: length of MAC address >+ * @extack: extended netdev ack structure >+ * >+ * Callback for the devlink .port_fn_hw_addr_set operation >+ * Return: zero on success or an error code on failure. >+ */ >+static int wx_devlink_port_set_vf_fn_mac(struct devlink_port *port, >+ const u8 *hw_addr, >+ int hw_addr_len, >+ struct netlink_ext_ack *extack) >+ >+{ >+ struct vf_data_storage *vfinfo = container_of(port, You name the structure vf_data_storage yet you name the variable with "info". Why not to somehow keep this consistent? >+ struct vf_data_storage, >+ devlink_port); >+ struct devlink_port_attrs *attrs = &port->attrs; >+ struct devlink_port_pci_vf_attrs *pci_vf; >+ struct wx *wx = vfinfo->vf_priv_wx; >+ int ret = 0; Pointless init. >+ u16 vf_id; >+ >+ pci_vf = &attrs->pci_vf; >+ vf_id = pci_vf->vf; >+ >+ if (!is_valid_ether_addr(hw_addr) || vf_id >= wx->num_vfs) Fillup extack message with appropriate error. How exacly (vf_id >= wx->num_vfs) could ever evaluate to "true"? >+ return -EINVAL; >+ >+ ret = wx_set_vf_mac(wx, vf_id, hw_addr); >+ if (ret >= 0) { >+ wx->vfinfo[vf_id].pf_set_mac = true; >+ if (!netif_running(wx->netdev)) >+ wx_err(wx, "Bring the PF device up before use vfs\n"); >+ } else { >+ wx_err(wx, "The VF MAC address was NOT set due to invalid\n"); Invalid what? Finish the sentence. Instead of this, use extack message. >+ } >+ >+ return 0; return ret; >+} >+ >+static const struct devlink_port_ops wx_devlink_vf_port_ops = { >+ .port_fn_hw_addr_get = wx_devlink_port_get_vf_fn_mac, >+ .port_fn_hw_addr_set = wx_devlink_port_set_vf_fn_mac, >+}; >+ >+int wx_devlink_create_vf_port(struct wx *wx, int vf_id) >+{ >+ struct devlink *devlink = priv_to_devlink(wx->dl_priv); >+ struct devlink_port_attrs attrs = {}; >+ struct devlink_port *devlink_port; >+ int err; >+ >+ devlink_port = &wx->vfinfo[vf_id].devlink_port; >+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; >+ attrs.pci_vf.pf = wx->bus.func; Again, this looks wrong. You have to get the pf index (0, 1, ...) from some place else. >+ attrs.pci_vf.vf = vf_id; >+ >+ wx_devlink_set_switch_id(wx, &attrs.switch_id); >+ devlink_port_attrs_set(devlink_port, &attrs); >+ err = devl_port_register_with_ops(devlink, devlink_port, vf_id + 1, This +1 may be a bit confusing for user to see VF0 with index 1. Perhaps start at some base offset instead? >+ &wx_devlink_vf_port_ops); >+ if (err) { >+ wx_err(wx, "Failed to create devlink port for VF %d, error %d\n", >+ vf_id, err); >+ return err; >+ } >+ >+ return 0; >+} >+ >+void wx_devlink_destroy_vf_port(struct wx *wx) >+{ >+ int i; >+ >+ for (i = 0; i < wx->num_vfs; i++) >+ devl_port_unregister(&wx->vfinfo[i].devlink_port); >+} >diff --git a/drivers/net/ethernet/wangxun/libwx/wx_devlink.h b/drivers/net/ethernet/wangxun/libwx/wx_devlink.h >new file mode 100644 >index 000000000000..0754579ed304 >--- /dev/null >+++ b/drivers/net/ethernet/wangxun/libwx/wx_devlink.h >@@ -0,0 +1,13 @@ >+/* SPDX-License-Identifier: GPL-2.0 */ >+/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ >+ >+#ifndef _WX_DEVLINK_H_ >+#define _WX_DEVLINK_H_ >+ >+struct wx_dl_priv *wx_create_devlink(struct device *dev); >+int wx_devlink_create_pf_port(struct wx *wx); >+void wx_devlink_destroy_pf_port(struct wx *wx); >+int wx_devlink_create_vf_port(struct wx *wx, int vf_id); >+void wx_devlink_destroy_vf_port(struct wx *wx); >+ >+#endif /* _WX_DEVLINK_H_ */ >diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c >index 08738738d02e..88ef82f1a1a3 100644 >--- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c >+++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c >@@ -7,6 +7,7 @@ > #include "wx_type.h" > #include "wx_hw.h" > #include "wx_mbx.h" >+#include "wx_devlink.h" > #include "wx_sriov.h" > > static void wx_vf_configuration(struct pci_dev *pdev, int event_mask) >@@ -92,6 +93,7 @@ static int __wx_enable_sriov(struct wx *wx, u8 num_vfs) > wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_SW_EN, WX_PSR_CTL_SW_EN); > > for (i = 0; i < num_vfs; i++) { >+ wx->vfinfo[i].vf_priv_wx = wx; > /* enable spoof checking for all VFs */ > wx->vfinfo[i].spoofchk_enabled = true; > wx->vfinfo[i].link_enable = true; >@@ -130,6 +132,7 @@ void wx_disable_sriov(struct wx *wx) > else > wx_err(wx, "Unloading driver while VFs are assigned.\n"); > >+ wx_devlink_destroy_vf_port(wx); > /* clear flags and free allloced data */ > wx_sriov_clear_data(wx); > } >@@ -158,7 +161,15 @@ static int wx_pci_sriov_enable(struct pci_dev *dev, > goto err_out; > } > >+ for (i = 0; i < wx->num_vfs; i++) { >+ err = wx_devlink_create_vf_port(wx, i); >+ if (err) >+ goto err_dis_sriov; >+ } >+ > return num_vfs; >+err_dis_sriov: >+ pci_disable_sriov(dev); > err_out: > wx_sriov_clear_data(wx); > return err; >@@ -210,7 +221,7 @@ int wx_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) > } > EXPORT_SYMBOL(wx_pci_sriov_configure); > >-static int wx_set_vf_mac(struct wx *wx, u16 vf, const u8 *mac_addr) >+int wx_set_vf_mac(struct wx *wx, u16 vf, const u8 *mac_addr) > { > u8 hw_addr[ETH_ALEN]; > int ret = 0; >diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.h b/drivers/net/ethernet/wangxun/libwx/wx_sriov.h >index 2aa68947c0d3..e876cb03c2c9 100644 >--- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.h >+++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.h >@@ -6,6 +6,7 @@ > > void wx_disable_sriov(struct wx *wx); > int wx_pci_sriov_configure(struct pci_dev *pdev, int num_vfs); >+int wx_set_vf_mac(struct wx *wx, u16 vf, const u8 *mac_addr); > void wx_msg_task(struct wx *wx); > void wx_disable_vf_rx_tx(struct wx *wx); > void wx_ping_all_vfs_with_link_status(struct wx *wx, bool link_up); >diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h >index e50a75e7c58b..a8722f69cebb 100644 >--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h >+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h >@@ -8,6 +8,7 @@ > #include <linux/netdevice.h> > #include <linux/if_vlan.h> > #include <linux/phylink.h> >+#include <net/devlink.h> > #include <net/ip.h> > > #define WX_NCSI_SUP 0x8000 >@@ -1084,6 +1085,10 @@ enum wx_state { > > struct vf_data_storage { > struct pci_dev *vfdev; >+ struct wx *vf_priv_wx; >+ /* vf devlink port data */ >+ struct devlink_port devlink_port; >+ > unsigned char vf_mac_addr[ETH_ALEN]; > bool spoofchk_enabled; > bool link_enable; >@@ -1119,6 +1124,10 @@ enum wx_pf_flags { > WX_PF_FLAGS_NBITS /* must be last */ > }; > >+struct wx_dl_priv { >+ struct wx *priv_wx; >+}; This is nonsence structure. Just let devlink_alloc() to allocate struct wx or you. > struct wx { > unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; > DECLARE_BITMAP(state, WX_STATE_NBITS); >@@ -1128,6 +1137,11 @@ struct wx { > u8 __iomem *hw_addr; > struct pci_dev *pdev; > struct net_device *netdev; >+ >+ /* devlink port data */ >+ struct devlink_port devlink_port; >+ struct wx_dl_priv *dl_priv; >+ > struct wx_bus_info bus; > struct wx_mbx_info mbx; > struct wx_mac_info mac; >-- >2.45.2 > >
diff --git a/drivers/net/ethernet/wangxun/libwx/Makefile b/drivers/net/ethernet/wangxun/libwx/Makefile index 5b996d973d29..643a5e947ba9 100644 --- a/drivers/net/ethernet/wangxun/libwx/Makefile +++ b/drivers/net/ethernet/wangxun/libwx/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_LIBWX) += libwx.o -libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_mbx.o wx_sriov.o +libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_mbx.o wx_sriov.o wx_devlink.o diff --git a/drivers/net/ethernet/wangxun/libwx/wx_devlink.c b/drivers/net/ethernet/wangxun/libwx/wx_devlink.c new file mode 100644 index 000000000000..b39da37c0842 --- /dev/null +++ b/drivers/net/ethernet/wangxun/libwx/wx_devlink.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ + +#include <linux/vmalloc.h> +#include <linux/pci.h> + +#include "wx_type.h" +#include "wx_sriov.h" +#include "wx_devlink.h" + +static const struct devlink_ops wx_pf_devlink_ops = { +}; + +static void wx_devlink_free(void *devlink_ptr) +{ + devlink_unregister((struct devlink *)devlink_ptr); + devlink_free((struct devlink *)devlink_ptr); +} + +struct wx_dl_priv *wx_create_devlink(struct device *dev) +{ + struct devlink *devlink; + + devlink = devlink_alloc(&wx_pf_devlink_ops, sizeof(devlink), dev); + if (!devlink) + return NULL; + + /* Add an action to teardown the devlink when unwinding the driver */ + if (devm_add_action_or_reset(dev, wx_devlink_free, devlink)) + return NULL; + + devlink_register(devlink); + + return devlink_priv(devlink); +} +EXPORT_SYMBOL(wx_create_devlink); + +/** + * wx_devlink_set_switch_id - Set unique switch id based on pci dsn + * @wx: the PF to create a devlink port for + * @ppid: struct with switch id information + */ +static void wx_devlink_set_switch_id(struct wx *wx, + struct netdev_phys_item_id *ppid) +{ + struct pci_dev *pdev = wx->pdev; + u64 id; + + id = pci_get_dsn(pdev); + + ppid->id_len = sizeof(id); + put_unaligned_be64(id, &ppid->id); +} + +/** + * wx_devlink_create_pf_port - Create a devlink port for this PF + * @wx: the PF to create a devlink port for + * + * Create and register a devlink_port for this PF. + * This function has to be called under devl_lock. + * + * Return: zero on success or an error code on failure. + */ +int wx_devlink_create_pf_port(struct wx *wx) +{ + struct devlink *devlink = priv_to_devlink(wx->dl_priv); + struct devlink_port_attrs attrs = {}; + int err; + + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; + attrs.phys.port_number = wx->bus.func; + wx_devlink_set_switch_id(wx, &attrs.switch_id); + devlink_port_attrs_set(&wx->devlink_port, &attrs); + err = devlink_port_register(devlink, &wx->devlink_port, 0); + if (err) { + wx_err(wx, "Failed to create devlink port for PF%d, error %d\n", + wx->bus.func, err); + return err; + } + + return 0; +} +EXPORT_SYMBOL(wx_devlink_create_pf_port); + +/** + * wx_devlink_destroy_pf_port - Destroy the devlink_port for this PF + * @wx: the PF to cleanup + * + * Unregisters the devlink_port structure associated with this PF. + * This function has to be called under devl_lock. + */ +void wx_devlink_destroy_pf_port(struct wx *wx) +{ + devl_port_unregister(&wx->devlink_port); +} +EXPORT_SYMBOL(wx_devlink_destroy_pf_port); + +/** + * wx_devlink_port_get_vf_fn_mac - .port_fn_hw_addr_get devlink handler + * @port: devlink port structure + * @hw_addr: MAC address of the port + * @hw_addr_len: length of MAC address + * @extack: extended netdev ack structure + * + * Callback for the devlink .port_fn_hw_addr_get operation + * Return: zero on success or an error code on failure. + */ +static int wx_devlink_port_get_vf_fn_mac(struct devlink_port *port, + u8 *hw_addr, int *hw_addr_len, + struct netlink_ext_ack *extack) +{ + struct vf_data_storage *vfinfo = container_of(port, + struct vf_data_storage, + devlink_port); + struct devlink_port_attrs *attrs = &port->attrs; + struct devlink_port_pci_vf_attrs *pci_vf; + struct wx *wx = vfinfo->vf_priv_wx; + u16 vf_id; + + pci_vf = &attrs->pci_vf; + vf_id = pci_vf->vf; + + ether_addr_copy(hw_addr, wx->vfinfo[vf_id].vf_mac_addr); + *hw_addr_len = ETH_ALEN; + + return 0; +} + +/** + * wx_devlink_port_set_vf_fn_mac - .port_fn_hw_addr_set devlink handler + * @port: devlink port structure + * @hw_addr: MAC address of the port + * @hw_addr_len: length of MAC address + * @extack: extended netdev ack structure + * + * Callback for the devlink .port_fn_hw_addr_set operation + * Return: zero on success or an error code on failure. + */ +static int wx_devlink_port_set_vf_fn_mac(struct devlink_port *port, + const u8 *hw_addr, + int hw_addr_len, + struct netlink_ext_ack *extack) + +{ + struct vf_data_storage *vfinfo = container_of(port, + struct vf_data_storage, + devlink_port); + struct devlink_port_attrs *attrs = &port->attrs; + struct devlink_port_pci_vf_attrs *pci_vf; + struct wx *wx = vfinfo->vf_priv_wx; + int ret = 0; + u16 vf_id; + + pci_vf = &attrs->pci_vf; + vf_id = pci_vf->vf; + + if (!is_valid_ether_addr(hw_addr) || vf_id >= wx->num_vfs) + return -EINVAL; + + ret = wx_set_vf_mac(wx, vf_id, hw_addr); + if (ret >= 0) { + wx->vfinfo[vf_id].pf_set_mac = true; + if (!netif_running(wx->netdev)) + wx_err(wx, "Bring the PF device up before use vfs\n"); + } else { + wx_err(wx, "The VF MAC address was NOT set due to invalid\n"); + } + + return 0; +} + +static const struct devlink_port_ops wx_devlink_vf_port_ops = { + .port_fn_hw_addr_get = wx_devlink_port_get_vf_fn_mac, + .port_fn_hw_addr_set = wx_devlink_port_set_vf_fn_mac, +}; + +int wx_devlink_create_vf_port(struct wx *wx, int vf_id) +{ + struct devlink *devlink = priv_to_devlink(wx->dl_priv); + struct devlink_port_attrs attrs = {}; + struct devlink_port *devlink_port; + int err; + + devlink_port = &wx->vfinfo[vf_id].devlink_port; + attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; + attrs.pci_vf.pf = wx->bus.func; + attrs.pci_vf.vf = vf_id; + + wx_devlink_set_switch_id(wx, &attrs.switch_id); + devlink_port_attrs_set(devlink_port, &attrs); + err = devl_port_register_with_ops(devlink, devlink_port, vf_id + 1, + &wx_devlink_vf_port_ops); + if (err) { + wx_err(wx, "Failed to create devlink port for VF %d, error %d\n", + vf_id, err); + return err; + } + + return 0; +} + +void wx_devlink_destroy_vf_port(struct wx *wx) +{ + int i; + + for (i = 0; i < wx->num_vfs; i++) + devl_port_unregister(&wx->vfinfo[i].devlink_port); +} diff --git a/drivers/net/ethernet/wangxun/libwx/wx_devlink.h b/drivers/net/ethernet/wangxun/libwx/wx_devlink.h new file mode 100644 index 000000000000..0754579ed304 --- /dev/null +++ b/drivers/net/ethernet/wangxun/libwx/wx_devlink.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ + +#ifndef _WX_DEVLINK_H_ +#define _WX_DEVLINK_H_ + +struct wx_dl_priv *wx_create_devlink(struct device *dev); +int wx_devlink_create_pf_port(struct wx *wx); +void wx_devlink_destroy_pf_port(struct wx *wx); +int wx_devlink_create_vf_port(struct wx *wx, int vf_id); +void wx_devlink_destroy_vf_port(struct wx *wx); + +#endif /* _WX_DEVLINK_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c index 08738738d02e..88ef82f1a1a3 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c @@ -7,6 +7,7 @@ #include "wx_type.h" #include "wx_hw.h" #include "wx_mbx.h" +#include "wx_devlink.h" #include "wx_sriov.h" static void wx_vf_configuration(struct pci_dev *pdev, int event_mask) @@ -92,6 +93,7 @@ static int __wx_enable_sriov(struct wx *wx, u8 num_vfs) wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_SW_EN, WX_PSR_CTL_SW_EN); for (i = 0; i < num_vfs; i++) { + wx->vfinfo[i].vf_priv_wx = wx; /* enable spoof checking for all VFs */ wx->vfinfo[i].spoofchk_enabled = true; wx->vfinfo[i].link_enable = true; @@ -130,6 +132,7 @@ void wx_disable_sriov(struct wx *wx) else wx_err(wx, "Unloading driver while VFs are assigned.\n"); + wx_devlink_destroy_vf_port(wx); /* clear flags and free allloced data */ wx_sriov_clear_data(wx); } @@ -158,7 +161,15 @@ static int wx_pci_sriov_enable(struct pci_dev *dev, goto err_out; } + for (i = 0; i < wx->num_vfs; i++) { + err = wx_devlink_create_vf_port(wx, i); + if (err) + goto err_dis_sriov; + } + return num_vfs; +err_dis_sriov: + pci_disable_sriov(dev); err_out: wx_sriov_clear_data(wx); return err; @@ -210,7 +221,7 @@ int wx_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) } EXPORT_SYMBOL(wx_pci_sriov_configure); -static int wx_set_vf_mac(struct wx *wx, u16 vf, const u8 *mac_addr) +int wx_set_vf_mac(struct wx *wx, u16 vf, const u8 *mac_addr) { u8 hw_addr[ETH_ALEN]; int ret = 0; diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.h b/drivers/net/ethernet/wangxun/libwx/wx_sriov.h index 2aa68947c0d3..e876cb03c2c9 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.h @@ -6,6 +6,7 @@ void wx_disable_sriov(struct wx *wx); int wx_pci_sriov_configure(struct pci_dev *pdev, int num_vfs); +int wx_set_vf_mac(struct wx *wx, u16 vf, const u8 *mac_addr); void wx_msg_task(struct wx *wx); void wx_disable_vf_rx_tx(struct wx *wx); void wx_ping_all_vfs_with_link_status(struct wx *wx, bool link_up); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index e50a75e7c58b..a8722f69cebb 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -8,6 +8,7 @@ #include <linux/netdevice.h> #include <linux/if_vlan.h> #include <linux/phylink.h> +#include <net/devlink.h> #include <net/ip.h> #define WX_NCSI_SUP 0x8000 @@ -1084,6 +1085,10 @@ enum wx_state { struct vf_data_storage { struct pci_dev *vfdev; + struct wx *vf_priv_wx; + /* vf devlink port data */ + struct devlink_port devlink_port; + unsigned char vf_mac_addr[ETH_ALEN]; bool spoofchk_enabled; bool link_enable; @@ -1119,6 +1124,10 @@ enum wx_pf_flags { WX_PF_FLAGS_NBITS /* must be last */ }; +struct wx_dl_priv { + struct wx *priv_wx; +}; + struct wx { unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; DECLARE_BITMAP(state, WX_STATE_NBITS); @@ -1128,6 +1137,11 @@ struct wx { u8 __iomem *hw_addr; struct pci_dev *pdev; struct net_device *netdev; + + /* devlink port data */ + struct devlink_port devlink_port; + struct wx_dl_priv *dl_priv; + struct wx_bus_info bus; struct wx_mbx_info mbx; struct wx_mac_info mac;
Make devlink allocation function generic to use it for PF and for VF. Add function for PF/VF devlink port creation. It will be used in wangxun NICs. Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com> --- drivers/net/ethernet/wangxun/libwx/Makefile | 2 +- .../net/ethernet/wangxun/libwx/wx_devlink.c | 208 ++++++++++++++++++ .../net/ethernet/wangxun/libwx/wx_devlink.h | 13 ++ drivers/net/ethernet/wangxun/libwx/wx_sriov.c | 13 +- drivers/net/ethernet/wangxun/libwx/wx_sriov.h | 1 + drivers/net/ethernet/wangxun/libwx/wx_type.h | 14 ++ 6 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_devlink.c create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_devlink.h