Patch "sfc: Change VF mac via PF as first preference if available." has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    sfc: Change VF mac via PF as first preference if available.

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     sfc-change-vf-mac-via-pf-as-first-preference-if-avai.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit d1e22f09573e7cf235ff780e6f493f031729523a
Author: Jonathan Cooper <jonathan.s.cooper@xxxxxxx>
Date:   Thu Oct 13 10:55:53 2022 +0100

    sfc: Change VF mac via PF as first preference if available.
    
    [ Upstream commit a8aed7b35becfd21f22a77c7014029ea837b018f ]
    
    Changing a VF's mac address through the VF (rather than via the PF)
    fails with EPERM because the latter part of efx_ef10_set_mac_address
    attempts to change the vport mac address list as the VF.
    Even with this fixed it still fails with EBUSY because the vadaptor
    is still assigned on the VF - the vadaptor reassignment must be within
    a section where the VF has torn down its state.
    
    A major reason this has broken is because we have two functions that
    ostensibly do the same thing - have a PF and VF cooperate to change a
    VF mac address. Rather than do this, if we are changing the mac of a VF
    that has a link to the PF in the same VM then simply call
    sriov_set_vf_mac instead, which is a proven working function that does
    that.
    
    If there is no PF available, or that fails non-fatally, then attempt to
    change the VF's mac address as we would a PF, without updating the PF's
    data.
    
    Test case:
    Create a VF:
      echo 1 > /sys/class/net/<if>/device/sriov_numvfs
    Set the mac address of the VF directly:
      ip link set <vf> addr 00:11:22:33:44:55
    Set the MAC address of the VF via the PF:
      ip link set <pf> vf 0 mac 00:11:22:33:44:66
    Without this patch the last command will fail with ENOENT.
    
    Signed-off-by: Jonathan Cooper <jonathan.s.cooper@xxxxxxx>
    Reported-by: Íñigo Huguet <ihuguet@xxxxxxxxxx>
    Fixes: 910c8789a777 ("set the MAC address using MC_CMD_VADAPTOR_SET_MAC")
    Acked-by: Edward Cree <ecree.xilinx@xxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 056c24ec1249..c316a9eb5be3 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -3271,6 +3271,30 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
 	bool was_enabled = efx->port_enabled;
 	int rc;
 
+#ifdef CONFIG_SFC_SRIOV
+	/* If this function is a VF and we have access to the parent PF,
+	 * then use the PF control path to attempt to change the VF MAC address.
+	 */
+	if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) {
+		struct efx_nic *efx_pf = pci_get_drvdata(efx->pci_dev->physfn);
+		struct efx_ef10_nic_data *nic_data = efx->nic_data;
+		u8 mac[ETH_ALEN];
+
+		/* net_dev->dev_addr can be zeroed by efx_net_stop in
+		 * efx_ef10_sriov_set_vf_mac, so pass in a copy.
+		 */
+		ether_addr_copy(mac, efx->net_dev->dev_addr);
+
+		rc = efx_ef10_sriov_set_vf_mac(efx_pf, nic_data->vf_index, mac);
+		if (!rc)
+			return 0;
+
+		netif_dbg(efx, drv, efx->net_dev,
+			  "Updating VF mac via PF failed (%d), setting directly\n",
+			  rc);
+	}
+#endif
+
 	efx_device_detach_sync(efx);
 	efx_net_stop(efx->net_dev);
 
@@ -3293,40 +3317,6 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
 		efx_net_open(efx->net_dev);
 	efx_device_attach_if_not_resetting(efx);
 
-#ifdef CONFIG_SFC_SRIOV
-	if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) {
-		struct efx_ef10_nic_data *nic_data = efx->nic_data;
-		struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
-
-		if (rc == -EPERM) {
-			struct efx_nic *efx_pf;
-
-			/* Switch to PF and change MAC address on vport */
-			efx_pf = pci_get_drvdata(pci_dev_pf);
-
-			rc = efx_ef10_sriov_set_vf_mac(efx_pf,
-						       nic_data->vf_index,
-						       efx->net_dev->dev_addr);
-		} else if (!rc) {
-			struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
-			struct efx_ef10_nic_data *nic_data = efx_pf->nic_data;
-			unsigned int i;
-
-			/* MAC address successfully changed by VF (with MAC
-			 * spoofing) so update the parent PF if possible.
-			 */
-			for (i = 0; i < efx_pf->vf_count; ++i) {
-				struct ef10_vf *vf = nic_data->vf + i;
-
-				if (vf->efx == efx) {
-					ether_addr_copy(vf->mac,
-							efx->net_dev->dev_addr);
-					return 0;
-				}
-			}
-		}
-	} else
-#endif
 	if (rc == -EPERM) {
 		netif_err(efx, drv, efx->net_dev,
 			  "Cannot change MAC address; use sfboot to enable"



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux