2024-04-02 09:23:20

by Karthik Sundaravel

[permalink] [raw]
Subject: [PATCH v7] ice: Add get/set hw address for VFs using devlink commands

Dear Maintainers,
Thanks for the review and suggestions for my patch.

v6 -> v7
--------
- Addressed Smatch and checkpatch issues

v5 -> v6
--------
- Changed data type of vf_id to u16
- Used container_of(port, struct ice_vf, devlink_port) to
get the vf instead of ice_get_vf_by_id()/ice_put_vf()

v4 -> v5
--------
- Cloned ice_set_vf_mac() to ice_set_vf_fn_mac() so that the
parameter ice_pf is used instead of net_device of vf
- removed redundant error handling

v3 -> v4
--------
- Released the vf device by calling ice_put_vf()

v2 -> v3
--------
- Fill the extack message instead of dev_err()

v1 -> v2
--------
- called ice_set_vf_mac() directly from the devlink port function
handlers.

RFC -> v1
---------
- Add the function handlers to set and get the HW address for the
VF representor ports.



2024-04-02 09:27:34

by Karthik Sundaravel

[permalink] [raw]
Subject: [PATCH v7] ice: Add get/set hw address for VFs using devlink commands

Changing the MAC address of the VFs is currently unsupported via devlink.
Add the function handlers to set and get the HW address for the VFs.

Signed-off-by: Karthik Sundaravel <[email protected]>
---
drivers/net/ethernet/intel/ice/ice_devlink.c | 63 +++++++++++++++++++-
drivers/net/ethernet/intel/ice/ice_sriov.c | 62 +++++++++++++++++++
drivers/net/ethernet/intel/ice/ice_sriov.h | 8 +++
3 files changed, 132 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..10735715403a 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -1576,6 +1576,66 @@ void ice_devlink_destroy_pf_port(struct ice_pf *pf)
devlink_port_unregister(&pf->devlink_port);
}

+/**
+ * ice_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 ice_devlink_port_get_vf_fn_mac(struct devlink_port *port,
+ u8 *hw_addr, int *hw_addr_len,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_vf *vf = container_of(port, struct ice_vf, devlink_port);
+
+ ether_addr_copy(hw_addr, vf->dev_lan_addr);
+ *hw_addr_len = ETH_ALEN;
+
+ return 0;
+}
+
+/**
+ * ice_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 ice_devlink_port_set_vf_fn_mac(struct devlink_port *port,
+ const u8 *hw_addr,
+ int hw_addr_len,
+ struct netlink_ext_ack *extack)
+
+{
+ struct devlink_port_attrs *attrs = &port->attrs;
+ struct devlink_port_pci_vf_attrs *pci_vf;
+ struct devlink *devlink = port->devlink;
+ struct ice_pf *pf;
+ u8 mac[ETH_ALEN];
+ u16 vf_id;
+
+ pf = devlink_priv(devlink);
+ pci_vf = &attrs->pci_vf;
+ vf_id = pci_vf->vf;
+
+ ether_addr_copy(mac, hw_addr);
+
+ return ice_set_vf_fn_mac(pf, vf_id, mac);
+}
+
+static const struct devlink_port_ops ice_devlink_vf_port_ops = {
+ .port_fn_hw_addr_get = ice_devlink_port_get_vf_fn_mac,
+ .port_fn_hw_addr_set = ice_devlink_port_set_vf_fn_mac,
+};
+
/**
* ice_devlink_create_vf_port - Create a devlink port for this VF
* @vf: the VF to create a port for
@@ -1611,7 +1671,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);
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index 31314e7540f8..b1e5cd188fd7 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -1216,6 +1216,68 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
return ret;
}

+/**
+ * ice_set_vf_fn_mac
+ * @pf: PF to be configure
+ * @vf_id: VF identifier
+ * @mac: MAC address
+ *
+ * program VF MAC address
+ */
+int ice_set_vf_fn_mac(struct ice_pf *pf, u16 vf_id, u8 *mac)
+{
+ struct device *dev;
+ struct ice_vf *vf;
+ int ret;
+
+ dev = ice_pf_to_dev(pf);
+ if (is_multicast_ether_addr(mac)) {
+ dev_err(dev, "%pM not a valid unicast address\n", mac);
+ return -EINVAL;
+ }
+
+ vf = ice_get_vf_by_id(pf, vf_id);
+ if (!vf)
+ return -EINVAL;
+
+ /* nothing left to do, unicast MAC already set */
+ if (ether_addr_equal(vf->dev_lan_addr, mac) &&
+ ether_addr_equal(vf->hw_lan_addr, mac)) {
+ ret = 0;
+ goto out_put_vf;
+ }
+
+ ret = ice_check_vf_ready_for_cfg(vf);
+ if (ret)
+ goto out_put_vf;
+
+ mutex_lock(&vf->cfg_lock);
+
+ /* VF is notified of its new MAC via the PF's response to the
+ * VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset
+ */
+ ether_addr_copy(vf->dev_lan_addr, mac);
+ ether_addr_copy(vf->hw_lan_addr, mac);
+ if (is_zero_ether_addr(mac)) {
+ /* VF will send VIRTCHNL_OP_ADD_ETH_ADDR message with its MAC */
+ vf->pf_set_mac = false;
+ dev_info(dev, "Removing MAC on VF %d. VF driver will be reinitialized\n",
+ vf->vf_id);
+ } else {
+ /* PF will add MAC rule for the VF */
+ vf->pf_set_mac = true;
+ dev_info(dev, "Setting MAC %pM on VF %d. VF driver will be reinitialized\n",
+ mac, vf_id);
+ }
+
+ ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
+ mutex_unlock(&vf->cfg_lock);
+
+out_put_vf:
+ ice_put_vf(vf);
+ return ret;
+}
+
/**
* ice_set_vf_mac
* @netdev: network interface device structure
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.h b/drivers/net/ethernet/intel/ice/ice_sriov.h
index 346cb2666f3a..11cc522b1d9f 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.h
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.h
@@ -28,6 +28,7 @@
#ifdef CONFIG_PCI_IOV
void ice_process_vflr_event(struct ice_pf *pf);
int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
+int ice_set_vf_fn_mac(struct ice_pf *pf, u16 vf_id, u8 *mac);
int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
int
ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi);
@@ -76,6 +77,13 @@ ice_sriov_configure(struct pci_dev __always_unused *pdev,
return -EOPNOTSUPP;
}

+static inline int
+ice_set_vf_fn_mac(struct ice_pf __always_unused *pf,
+ u16 __always_unused vf_id, u8 __always_unused *mac)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int
ice_set_vf_mac(struct net_device __always_unused *netdev,
int __always_unused vf_id, u8 __always_unused *mac)
--
2.39.3 (Apple Git-146)


2024-04-02 11:21:57

by Jiri Pirko

[permalink] [raw]
Subject: Re: [PATCH v7] ice: Add get/set hw address for VFs using devlink commands

Tue, Apr 02, 2024 at 11:22:54AM CEST, [email protected] wrote:
>Changing the MAC address of the VFs is currently unsupported via devlink.
>Add the function handlers to set and get the HW address for the VFs.
>
>Signed-off-by: Karthik Sundaravel <[email protected]>
>---
> drivers/net/ethernet/intel/ice/ice_devlink.c | 63 +++++++++++++++++++-
> drivers/net/ethernet/intel/ice/ice_sriov.c | 62 +++++++++++++++++++
> drivers/net/ethernet/intel/ice/ice_sriov.h | 8 +++
> 3 files changed, 132 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..10735715403a 100644
>--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
>+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
>@@ -1576,6 +1576,66 @@ void ice_devlink_destroy_pf_port(struct ice_pf *pf)
> devlink_port_unregister(&pf->devlink_port);
> }
>
>+/**
>+ * ice_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 ice_devlink_port_get_vf_fn_mac(struct devlink_port *port,
>+ u8 *hw_addr, int *hw_addr_len,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct ice_vf *vf = container_of(port, struct ice_vf, devlink_port);
>+
>+ ether_addr_copy(hw_addr, vf->dev_lan_addr);
>+ *hw_addr_len = ETH_ALEN;
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_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 ice_devlink_port_set_vf_fn_mac(struct devlink_port *port,
>+ const u8 *hw_addr,
>+ int hw_addr_len,
>+ struct netlink_ext_ack *extack)
>+
>+{
>+ struct devlink_port_attrs *attrs = &port->attrs;
>+ struct devlink_port_pci_vf_attrs *pci_vf;
>+ struct devlink *devlink = port->devlink;
>+ struct ice_pf *pf;
>+ u8 mac[ETH_ALEN];

Why you need this extra variable?


>+ u16 vf_id;
>+
>+ pf = devlink_priv(devlink);
>+ pci_vf = &attrs->pci_vf;
>+ vf_id = pci_vf->vf;
>+
>+ ether_addr_copy(mac, hw_addr);
>+
>+ return ice_set_vf_fn_mac(pf, vf_id, mac);
>+}
>+
>+static const struct devlink_port_ops ice_devlink_vf_port_ops = {
>+ .port_fn_hw_addr_get = ice_devlink_port_get_vf_fn_mac,
>+ .port_fn_hw_addr_set = ice_devlink_port_set_vf_fn_mac,
>+};
>+
> /**
> * ice_devlink_create_vf_port - Create a devlink port for this VF
> * @vf: the VF to create a port for
>@@ -1611,7 +1671,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);
>diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
>index 31314e7540f8..b1e5cd188fd7 100644
>--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
>+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
>@@ -1216,6 +1216,68 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
> return ret;
> }
>
>+/**
>+ * ice_set_vf_fn_mac
>+ * @pf: PF to be configure
>+ * @vf_id: VF identifier
>+ * @mac: MAC address
>+ *
>+ * program VF MAC address
>+ */
>+int ice_set_vf_fn_mac(struct ice_pf *pf, u16 vf_id, u8 *mac)
>+{
>+ struct device *dev;
>+ struct ice_vf *vf;
>+ int ret;
>+
>+ dev = ice_pf_to_dev(pf);
>+ if (is_multicast_ether_addr(mac)) {
>+ dev_err(dev, "%pM not a valid unicast address\n", mac);
>+ return -EINVAL;
>+ }
>+
>+ vf = ice_get_vf_by_id(pf, vf_id);
>+ if (!vf)
>+ return -EINVAL;
>+
>+ /* nothing left to do, unicast MAC already set */
>+ if (ether_addr_equal(vf->dev_lan_addr, mac) &&
>+ ether_addr_equal(vf->hw_lan_addr, mac)) {
>+ ret = 0;
>+ goto out_put_vf;
>+ }
>+
>+ ret = ice_check_vf_ready_for_cfg(vf);
>+ if (ret)
>+ goto out_put_vf;
>+
>+ mutex_lock(&vf->cfg_lock);
>+
>+ /* VF is notified of its new MAC via the PF's response to the
>+ * VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset
>+ */
>+ ether_addr_copy(vf->dev_lan_addr, mac);
>+ ether_addr_copy(vf->hw_lan_addr, mac);
>+ if (is_zero_ether_addr(mac)) {
>+ /* VF will send VIRTCHNL_OP_ADD_ETH_ADDR message with its MAC */
>+ vf->pf_set_mac = false;
>+ dev_info(dev, "Removing MAC on VF %d. VF driver will be reinitialized\n",
>+ vf->vf_id);
>+ } else {
>+ /* PF will add MAC rule for the VF */
>+ vf->pf_set_mac = true;
>+ dev_info(dev, "Setting MAC %pM on VF %d. VF driver will be reinitialized\n",
>+ mac, vf_id);
>+ }
>+
>+ ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
>+ mutex_unlock(&vf->cfg_lock);
>+
>+out_put_vf:
>+ ice_put_vf(vf);
>+ return ret;
>+}
>+
> /**
> * ice_set_vf_mac
> * @netdev: network interface device structure
>diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.h b/drivers/net/ethernet/intel/ice/ice_sriov.h
>index 346cb2666f3a..11cc522b1d9f 100644
>--- a/drivers/net/ethernet/intel/ice/ice_sriov.h
>+++ b/drivers/net/ethernet/intel/ice/ice_sriov.h
>@@ -28,6 +28,7 @@
> #ifdef CONFIG_PCI_IOV
> void ice_process_vflr_event(struct ice_pf *pf);
> int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
>+int ice_set_vf_fn_mac(struct ice_pf *pf, u16 vf_id, u8 *mac);
> int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
> int
> ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi);
>@@ -76,6 +77,13 @@ ice_sriov_configure(struct pci_dev __always_unused *pdev,
> return -EOPNOTSUPP;
> }
>
>+static inline int
>+ice_set_vf_fn_mac(struct ice_pf __always_unused *pf,
>+ u16 __always_unused vf_id, u8 __always_unused *mac)
>+{
>+ return -EOPNOTSUPP;
>+}
>+
> static inline int
> ice_set_vf_mac(struct net_device __always_unused *netdev,
> int __always_unused vf_id, u8 __always_unused *mac)
>--
>2.39.3 (Apple Git-146)
>

2024-04-02 14:21:52

by Karthik Sundaravel

[permalink] [raw]
Subject: Re: [PATCH v7] ice: Add get/set hw address for VFs using devlink commands

On Tue, Apr 2, 2024 at 4:51 PM Jiri Pirko <[email protected]> wrote:
>
> Tue, Apr 02, 2024 at 11:22:54AM CEST, [email protected] wrote:
> >Changing the MAC address of the VFs is currently unsupported via devlink.
> >Add the function handlers to set and get the HW address for the VFs.
> >
> >Signed-off-by: Karthik Sundaravel <[email protected]>
> >---
> > drivers/net/ethernet/intel/ice/ice_devlink.c | 63 +++++++++++++++++++-
> > drivers/net/ethernet/intel/ice/ice_sriov.c | 62 +++++++++++++++++++
> > drivers/net/ethernet/intel/ice/ice_sriov.h | 8 +++
> > 3 files changed, 132 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..10735715403a 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
> >+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
> >@@ -1576,6 +1576,66 @@ void ice_devlink_destroy_pf_port(struct ice_pf *pf)
> > devlink_port_unregister(&pf->devlink_port);
> > }
> >
> >+/**
> >+ * ice_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 ice_devlink_port_get_vf_fn_mac(struct devlink_port *port,
> >+ u8 *hw_addr, int *hw_addr_len,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ struct ice_vf *vf = container_of(port, struct ice_vf, devlink_port);
> >+
> >+ ether_addr_copy(hw_addr, vf->dev_lan_addr);
> >+ *hw_addr_len = ETH_ALEN;
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_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 ice_devlink_port_set_vf_fn_mac(struct devlink_port *port,
> >+ const u8 *hw_addr,
> >+ int hw_addr_len,
> >+ struct netlink_ext_ack *extack)
> >+
> >+{
> >+ struct devlink_port_attrs *attrs = &port->attrs;
> >+ struct devlink_port_pci_vf_attrs *pci_vf;
> >+ struct devlink *devlink = port->devlink;
> >+ struct ice_pf *pf;
> >+ u8 mac[ETH_ALEN];
>
> Why you need this extra variable?
The function signature of ice_set_vf_fn_mac() is kept to match
ice_set_vf_mac(), and hence the ``u8 *mac`` is used instead of ``const
u8 *mac``.
A copy of the mac is made to facilitate the same.
Considering the usage of mac in ice_set_vf_fn_mac(), the function
signature could be modified to take a ``const u8 *mac`` as well.
>
>
> >+ u16 vf_id;
> >+
> >+ pf = devlink_priv(devlink);
> >+ pci_vf = &attrs->pci_vf;
> >+ vf_id = pci_vf->vf;
> >+
> >+ ether_addr_copy(mac, hw_addr);
> >+
> >+ return ice_set_vf_fn_mac(pf, vf_id, mac);
> >+}
> >+
> >+static const struct devlink_port_ops ice_devlink_vf_port_ops = {
> >+ .port_fn_hw_addr_get = ice_devlink_port_get_vf_fn_mac,
> >+ .port_fn_hw_addr_set = ice_devlink_port_set_vf_fn_mac,
> >+};
> >+
> > /**
> > * ice_devlink_create_vf_port - Create a devlink port for this VF
> > * @vf: the VF to create a port for
> >@@ -1611,7 +1671,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);
> >diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
> >index 31314e7540f8..b1e5cd188fd7 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
> >+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
> >@@ -1216,6 +1216,68 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
> > return ret;
> > }
> >
> >+/**
> >+ * ice_set_vf_fn_mac
> >+ * @pf: PF to be configure
> >+ * @vf_id: VF identifier
> >+ * @mac: MAC address
> >+ *
> >+ * program VF MAC address
> >+ */
> >+int ice_set_vf_fn_mac(struct ice_pf *pf, u16 vf_id, u8 *mac)
> >+{
> >+ struct device *dev;
> >+ struct ice_vf *vf;
> >+ int ret;
> >+
> >+ dev = ice_pf_to_dev(pf);
> >+ if (is_multicast_ether_addr(mac)) {
> >+ dev_err(dev, "%pM not a valid unicast address\n", mac);
> >+ return -EINVAL;
> >+ }
> >+
> >+ vf = ice_get_vf_by_id(pf, vf_id);
> >+ if (!vf)
> >+ return -EINVAL;
> >+
> >+ /* nothing left to do, unicast MAC already set */
> >+ if (ether_addr_equal(vf->dev_lan_addr, mac) &&
> >+ ether_addr_equal(vf->hw_lan_addr, mac)) {
> >+ ret = 0;
> >+ goto out_put_vf;
> >+ }
> >+
> >+ ret = ice_check_vf_ready_for_cfg(vf);
> >+ if (ret)
> >+ goto out_put_vf;
> >+
> >+ mutex_lock(&vf->cfg_lock);
> >+
> >+ /* VF is notified of its new MAC via the PF's response to the
> >+ * VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset
> >+ */
> >+ ether_addr_copy(vf->dev_lan_addr, mac);
> >+ ether_addr_copy(vf->hw_lan_addr, mac);
> >+ if (is_zero_ether_addr(mac)) {
> >+ /* VF will send VIRTCHNL_OP_ADD_ETH_ADDR message with its MAC */
> >+ vf->pf_set_mac = false;
> >+ dev_info(dev, "Removing MAC on VF %d. VF driver will be reinitialized\n",
> >+ vf->vf_id);
> >+ } else {
> >+ /* PF will add MAC rule for the VF */
> >+ vf->pf_set_mac = true;
> >+ dev_info(dev, "Setting MAC %pM on VF %d. VF driver will be reinitialized\n",
> >+ mac, vf_id);
> >+ }
> >+
> >+ ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
> >+ mutex_unlock(&vf->cfg_lock);
> >+
> >+out_put_vf:
> >+ ice_put_vf(vf);
> >+ return ret;
> >+}
> >+
> > /**
> > * ice_set_vf_mac
> > * @netdev: network interface device structure
> >diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.h b/drivers/net/ethernet/intel/ice/ice_sriov.h
> >index 346cb2666f3a..11cc522b1d9f 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_sriov.h
> >+++ b/drivers/net/ethernet/intel/ice/ice_sriov.h
> >@@ -28,6 +28,7 @@
> > #ifdef CONFIG_PCI_IOV
> > void ice_process_vflr_event(struct ice_pf *pf);
> > int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
> >+int ice_set_vf_fn_mac(struct ice_pf *pf, u16 vf_id, u8 *mac);
> > int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
> > int
> > ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi);
> >@@ -76,6 +77,13 @@ ice_sriov_configure(struct pci_dev __always_unused *pdev,
> > return -EOPNOTSUPP;
> > }
> >
> >+static inline int
> >+ice_set_vf_fn_mac(struct ice_pf __always_unused *pf,
> >+ u16 __always_unused vf_id, u8 __always_unused *mac)
> >+{
> >+ return -EOPNOTSUPP;
> >+}
> >+
> > static inline int
> > ice_set_vf_mac(struct net_device __always_unused *netdev,
> > int __always_unused vf_id, u8 __always_unused *mac)
> >--
> >2.39.3 (Apple Git-146)
> >
>


2024-04-02 16:58:17

by Jiri Pirko

[permalink] [raw]
Subject: Re: [PATCH v7] ice: Add get/set hw address for VFs using devlink commands

Tue, Apr 02, 2024 at 03:57:35PM CEST, [email protected] wrote:
>On Tue, Apr 2, 2024 at 4:51 PM Jiri Pirko <[email protected]> wrote:
>>
>> Tue, Apr 02, 2024 at 11:22:54AM CEST, [email protected] wrote:
>> >Changing the MAC address of the VFs is currently unsupported via devlink.
>> >Add the function handlers to set and get the HW address for the VFs.
>> >
>> >Signed-off-by: Karthik Sundaravel <[email protected]>
>> >---
>> > drivers/net/ethernet/intel/ice/ice_devlink.c | 63 +++++++++++++++++++-
>> > drivers/net/ethernet/intel/ice/ice_sriov.c | 62 +++++++++++++++++++
>> > drivers/net/ethernet/intel/ice/ice_sriov.h | 8 +++
>> > 3 files changed, 132 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..10735715403a 100644
>> >--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
>> >+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
>> >@@ -1576,6 +1576,66 @@ void ice_devlink_destroy_pf_port(struct ice_pf *pf)
>> > devlink_port_unregister(&pf->devlink_port);
>> > }
>> >
>> >+/**
>> >+ * ice_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 ice_devlink_port_get_vf_fn_mac(struct devlink_port *port,
>> >+ u8 *hw_addr, int *hw_addr_len,
>> >+ struct netlink_ext_ack *extack)
>> >+{
>> >+ struct ice_vf *vf = container_of(port, struct ice_vf, devlink_port);
>> >+
>> >+ ether_addr_copy(hw_addr, vf->dev_lan_addr);
>> >+ *hw_addr_len = ETH_ALEN;
>> >+
>> >+ return 0;
>> >+}
>> >+
>> >+/**
>> >+ * ice_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 ice_devlink_port_set_vf_fn_mac(struct devlink_port *port,
>> >+ const u8 *hw_addr,
>> >+ int hw_addr_len,
>> >+ struct netlink_ext_ack *extack)
>> >+
>> >+{
>> >+ struct devlink_port_attrs *attrs = &port->attrs;
>> >+ struct devlink_port_pci_vf_attrs *pci_vf;
>> >+ struct devlink *devlink = port->devlink;
>> >+ struct ice_pf *pf;
>> >+ u8 mac[ETH_ALEN];
>>
>> Why you need this extra variable?
>The function signature of ice_set_vf_fn_mac() is kept to match

Why? Why can't you just make the arg const?


>ice_set_vf_mac(), and hence the ``u8 *mac`` is used instead of ``const
>u8 *mac``.
>A copy of the mac is made to facilitate the same.
>Considering the usage of mac in ice_set_vf_fn_mac(), the function
>signature could be modified to take a ``const u8 *mac`` as well.

Yep.


>>
>>
>> >+ u16 vf_id;
>> >+
>> >+ pf = devlink_priv(devlink);
>> >+ pci_vf = &attrs->pci_vf;
>> >+ vf_id = pci_vf->vf;
>> >+
>> >+ ether_addr_copy(mac, hw_addr);
>> >+
>> >+ return ice_set_vf_fn_mac(pf, vf_id, mac);
>> >+}
>> >+
>> >+static const struct devlink_port_ops ice_devlink_vf_port_ops = {
>> >+ .port_fn_hw_addr_get = ice_devlink_port_get_vf_fn_mac,
>> >+ .port_fn_hw_addr_set = ice_devlink_port_set_vf_fn_mac,
>> >+};
>> >+
>> > /**
>> > * ice_devlink_create_vf_port - Create a devlink port for this VF
>> > * @vf: the VF to create a port for
>> >@@ -1611,7 +1671,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);
>> >diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
>> >index 31314e7540f8..b1e5cd188fd7 100644
>> >--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
>> >+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
>> >@@ -1216,6 +1216,68 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
>> > return ret;
>> > }
>> >
>> >+/**
>> >+ * ice_set_vf_fn_mac
>> >+ * @pf: PF to be configure
>> >+ * @vf_id: VF identifier
>> >+ * @mac: MAC address
>> >+ *
>> >+ * program VF MAC address
>> >+ */
>> >+int ice_set_vf_fn_mac(struct ice_pf *pf, u16 vf_id, u8 *mac)
>> >+{
>> >+ struct device *dev;
>> >+ struct ice_vf *vf;
>> >+ int ret;
>> >+
>> >+ dev = ice_pf_to_dev(pf);
>> >+ if (is_multicast_ether_addr(mac)) {
>> >+ dev_err(dev, "%pM not a valid unicast address\n", mac);
>> >+ return -EINVAL;
>> >+ }
>> >+
>> >+ vf = ice_get_vf_by_id(pf, vf_id);
>> >+ if (!vf)
>> >+ return -EINVAL;
>> >+
>> >+ /* nothing left to do, unicast MAC already set */
>> >+ if (ether_addr_equal(vf->dev_lan_addr, mac) &&
>> >+ ether_addr_equal(vf->hw_lan_addr, mac)) {
>> >+ ret = 0;
>> >+ goto out_put_vf;
>> >+ }
>> >+
>> >+ ret = ice_check_vf_ready_for_cfg(vf);
>> >+ if (ret)
>> >+ goto out_put_vf;
>> >+
>> >+ mutex_lock(&vf->cfg_lock);
>> >+
>> >+ /* VF is notified of its new MAC via the PF's response to the
>> >+ * VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset
>> >+ */
>> >+ ether_addr_copy(vf->dev_lan_addr, mac);
>> >+ ether_addr_copy(vf->hw_lan_addr, mac);
>> >+ if (is_zero_ether_addr(mac)) {
>> >+ /* VF will send VIRTCHNL_OP_ADD_ETH_ADDR message with its MAC */
>> >+ vf->pf_set_mac = false;
>> >+ dev_info(dev, "Removing MAC on VF %d. VF driver will be reinitialized\n",
>> >+ vf->vf_id);
>> >+ } else {
>> >+ /* PF will add MAC rule for the VF */
>> >+ vf->pf_set_mac = true;
>> >+ dev_info(dev, "Setting MAC %pM on VF %d. VF driver will be reinitialized\n",
>> >+ mac, vf_id);
>> >+ }
>> >+
>> >+ ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
>> >+ mutex_unlock(&vf->cfg_lock);
>> >+
>> >+out_put_vf:
>> >+ ice_put_vf(vf);
>> >+ return ret;
>> >+}
>> >+
>> > /**
>> > * ice_set_vf_mac
>> > * @netdev: network interface device structure
>> >diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.h b/drivers/net/ethernet/intel/ice/ice_sriov.h
>> >index 346cb2666f3a..11cc522b1d9f 100644
>> >--- a/drivers/net/ethernet/intel/ice/ice_sriov.h
>> >+++ b/drivers/net/ethernet/intel/ice/ice_sriov.h
>> >@@ -28,6 +28,7 @@
>> > #ifdef CONFIG_PCI_IOV
>> > void ice_process_vflr_event(struct ice_pf *pf);
>> > int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
>> >+int ice_set_vf_fn_mac(struct ice_pf *pf, u16 vf_id, u8 *mac);
>> > int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
>> > int
>> > ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi);
>> >@@ -76,6 +77,13 @@ ice_sriov_configure(struct pci_dev __always_unused *pdev,
>> > return -EOPNOTSUPP;
>> > }
>> >
>> >+static inline int
>> >+ice_set_vf_fn_mac(struct ice_pf __always_unused *pf,
>> >+ u16 __always_unused vf_id, u8 __always_unused *mac)
>> >+{
>> >+ return -EOPNOTSUPP;
>> >+}
>> >+
>> > static inline int
>> > ice_set_vf_mac(struct net_device __always_unused *netdev,
>> > int __always_unused vf_id, u8 __always_unused *mac)
>> >--
>> >2.39.3 (Apple Git-146)
>> >
>>
>