[v2] ice: Add get/set hw address for VFs using devlink commands
Commit Message
Changing the MAC address of the VF ports are not available
via devlink. Add the function handlers to set and get
the HW address for the VF ports.
Signed-off-by: Karthik Sundaravel <ksundara@redhat.com>
---
drivers/net/ethernet/intel/ice/ice_devlink.c | 89 +++++++++++++++++++-
1 file changed, 88 insertions(+), 1 deletion(-)
Comments
Thu, Feb 08, 2024 at 09:24:55AM CET, ksundara@redhat.com wrote:
>Changing the MAC address of the VF ports are not available
>via devlink. Add the function handlers to set and get
>the HW address for the VF ports.
"VFs". Avoid the word "port" here, as it may falsely indicate you are
talking about the eswitch representor port.
>
>Signed-off-by: Karthik Sundaravel <ksundara@redhat.com>
>---
> drivers/net/ethernet/intel/ice/ice_devlink.c | 89 +++++++++++++++++++-
> 1 file changed, 88 insertions(+), 1 deletion(-)
>
>diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
>index 80dc5445b50d..8455fa94a687 100644
>--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
>+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
>@@ -1576,6 +1576,92 @@ void ice_devlink_destroy_pf_port(struct ice_pf *pf)
> devlink_port_unregister(&pf->devlink_port);
> }
>
>+/**
>+ * ice_devlink_port_get_vf_mac_address - .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 ice_devlink_port_get_vf_mac_address(struct devlink_port *port,
>+ u8 *hw_addr, int *hw_addr_len,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct devlink *devlink = port->devlink;
>+ struct ice_pf *pf = devlink_priv(devlink);
>+ struct device *dev = ice_pf_to_dev(pf);
>+ struct devlink_port_attrs *attrs = &port->attrs;
>+ struct devlink_port_pci_vf_attrs *pci_vf;
>+ int vf_id;
>+ struct ice_vf *vf;
Reverse xmas tree:
https://www.kernel.org/doc/html/v6.7/process/maintainer-netdev.html#tl-dr
>+
>+ if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_VF) {
>+ pci_vf = &attrs->pci_vf;
>+ vf_id = pci_vf->vf;
>+ } else {
>+ dev_err(dev, "Unable to get the vf id for PF %d\n", pf->hw.pf_id);
Fill the extack message instead.
>+ return -EADDRNOTAVAIL;
>+ }
>+ vf = ice_get_vf_by_id(pf, vf_id);
>+ if (!vf) {
>+ dev_err(dev, "Unable to get the vf for PF %d\n", pf->hw.pf_id);
Fill the extack message instead.
>+ return -EINVAL;
>+ }
>+ ether_addr_copy(hw_addr, vf->dev_lan_addr);
>+ *hw_addr_len = ETH_ALEN;
>+ return 0;
>+}
>+
>+/**
>+ * ice_devlink_port_set_vf_mac_address - .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 ice_devlink_port_set_vf_mac_address(struct devlink_port *port,
>+ const u8 *hw_addr,
>+ int hw_addr_len,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct devlink *devlink = port->devlink;
>+ struct ice_pf *pf = devlink_priv(devlink);
>+ struct device *dev = ice_pf_to_dev(pf);
>+ struct net_device *netdev = port->type_eth.netdev;
>+ struct devlink_port_attrs *attrs = &port->attrs;
>+ struct devlink_port_pci_vf_attrs *pci_vf;
>+ int vf_id;
>+ u8 mac[ETH_ALEN];
Reverse xmas tree:
https://www.kernel.org/doc/html/v6.7/process/maintainer-netdev.html#tl-dr
>+
>+ if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_VF) {
>+ pci_vf = &attrs->pci_vf;
>+ vf_id = pci_vf->vf;
>+ } else {
>+ dev_err(dev, "Unable to get the vf id for PF %d\n", pf->hw.pf_id);
Fill the extack message instead.
>+ return -EADDRNOTAVAIL;
>+ }
>+
>+ if (!netdev) {
>+ dev_err(dev, "Unable to get the netdev for PF %d\n", pf->hw.pf_id);
Fill the extack message instead.
>+ return -EADDRNOTAVAIL;
>+ }
>+ ether_addr_copy(mac, hw_addr);
>+
>+ return ice_set_vf_mac(netdev, vf_id, mac);
>+}
>+
>+static const struct devlink_port_ops ice_devlink_vf_port_ops = {
>+ .port_fn_hw_addr_get = ice_devlink_port_get_vf_mac_address,
>+ .port_fn_hw_addr_set = ice_devlink_port_set_vf_mac_address,
>+};
>+
> /**
> * ice_devlink_create_vf_port - Create a devlink port for this VF
> * @vf: the VF to create a port for
>@@ -1611,7 +1697,8 @@ int ice_devlink_create_vf_port(struct ice_vf *vf)
> devlink_port_attrs_set(devlink_port, &attrs);
> devlink = priv_to_devlink(pf);
>
>- err = devlink_port_register(devlink, devlink_port, vsi->idx);
>+ err = devlink_port_register_with_ops(devlink, devlink_port,
>+ vsi->idx, &ice_devlink_vf_port_ops);
> if (err) {
> dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
> vf->vf_id, err);
>--
>2.39.3 (Apple Git-145)
>
@@ -1576,6 +1576,92 @@ void ice_devlink_destroy_pf_port(struct ice_pf *pf)
devlink_port_unregister(&pf->devlink_port);
}
+/**
+ * ice_devlink_port_get_vf_mac_address - .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 ice_devlink_port_get_vf_mac_address(struct devlink_port *port,
+ u8 *hw_addr, int *hw_addr_len,
+ struct netlink_ext_ack *extack)
+{
+ struct devlink *devlink = port->devlink;
+ struct ice_pf *pf = devlink_priv(devlink);
+ struct device *dev = ice_pf_to_dev(pf);
+ struct devlink_port_attrs *attrs = &port->attrs;
+ struct devlink_port_pci_vf_attrs *pci_vf;
+ int vf_id;
+ struct ice_vf *vf;
+
+ if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_VF) {
+ pci_vf = &attrs->pci_vf;
+ vf_id = pci_vf->vf;
+ } else {
+ dev_err(dev, "Unable to get the vf id for PF %d\n", pf->hw.pf_id);
+ return -EADDRNOTAVAIL;
+ }
+ vf = ice_get_vf_by_id(pf, vf_id);
+ if (!vf) {
+ dev_err(dev, "Unable to get the vf for PF %d\n", pf->hw.pf_id);
+ return -EINVAL;
+ }
+ ether_addr_copy(hw_addr, vf->dev_lan_addr);
+ *hw_addr_len = ETH_ALEN;
+ return 0;
+}
+
+/**
+ * ice_devlink_port_set_vf_mac_address - .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 ice_devlink_port_set_vf_mac_address(struct devlink_port *port,
+ const u8 *hw_addr,
+ int hw_addr_len,
+ struct netlink_ext_ack *extack)
+{
+ struct devlink *devlink = port->devlink;
+ struct ice_pf *pf = devlink_priv(devlink);
+ struct device *dev = ice_pf_to_dev(pf);
+ struct net_device *netdev = port->type_eth.netdev;
+ struct devlink_port_attrs *attrs = &port->attrs;
+ struct devlink_port_pci_vf_attrs *pci_vf;
+ int vf_id;
+ u8 mac[ETH_ALEN];
+
+ if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_VF) {
+ pci_vf = &attrs->pci_vf;
+ vf_id = pci_vf->vf;
+ } else {
+ dev_err(dev, "Unable to get the vf id for PF %d\n", pf->hw.pf_id);
+ return -EADDRNOTAVAIL;
+ }
+
+ if (!netdev) {
+ dev_err(dev, "Unable to get the netdev for PF %d\n", pf->hw.pf_id);
+ return -EADDRNOTAVAIL;
+ }
+ ether_addr_copy(mac, hw_addr);
+
+ return ice_set_vf_mac(netdev, vf_id, mac);
+}
+
+static const struct devlink_port_ops ice_devlink_vf_port_ops = {
+ .port_fn_hw_addr_get = ice_devlink_port_get_vf_mac_address,
+ .port_fn_hw_addr_set = ice_devlink_port_set_vf_mac_address,
+};
+
/**
* ice_devlink_create_vf_port - Create a devlink port for this VF
* @vf: the VF to create a port for
@@ -1611,7 +1697,8 @@ int ice_devlink_create_vf_port(struct ice_vf *vf)
devlink_port_attrs_set(devlink_port, &attrs);
devlink = priv_to_devlink(pf);
- err = devlink_port_register(devlink, devlink_port, vsi->idx);
+ err = devlink_port_register_with_ops(devlink, devlink_port,
+ vsi->idx, &ice_devlink_vf_port_ops);
if (err) {
dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
vf->vf_id, err);