Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sfc: set the MAC address using MC_CMD_VADAPTOR_SET_MAC

Add a set_mac_address() NIC-type function for EF10 only, and
use this to set the MAC address on the vadaptor. For Siena and
earlier, the MAC address continues to be set by MC_CMD_SET_MAC;
this is still called on EF10, and including a MAC address in
this command has no effect.

The sriov_mac_address_changed() NIC-type function is no longer
needed on EF10, but it is needed for Siena where it is used to
update the peer address of the PF for VFDI. Change this to use
the new set_mac_address function pointer.

efx_ef10_sriov_mac_address_changed() is no longer called, as VFs
will try to change the MAC address on their vadaptor rather than
trying to change to the context of the PF to alter the vport.

When a VF is running in direct passthrough mode with MAC spoofing
enabled, it will be able to change the MAC address on its vadaptor.
In this case, there is a link to the PF, so find the correct VF in
its ef10_vf array and update the MAC address.

ndo_set_mac_address() can be called during driver unload while
bonding, and in this case the device has already been stopped, so
don't call efx_net_open() to restart it after reconfiguration.

efx->port_enabled is set to false in efx_stop_port(), so it is
indicator of whether the device needs to be restarted.

Signed-off-by: Shradha Shah <sshah@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Shradha Shah and committed by
David S. Miller
910c8789 860d2ffa

+120 -9
+74 -1
drivers/net/ethernet/sfc/ef10.c
··· 3596 3596 WARN_ON(remove_failed); 3597 3597 } 3598 3598 3599 + static int efx_ef10_set_mac_address(struct efx_nic *efx) 3600 + { 3601 + MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN); 3602 + struct efx_ef10_nic_data *nic_data = efx->nic_data; 3603 + bool was_enabled = efx->port_enabled; 3604 + int rc; 3605 + 3606 + efx_device_detach_sync(efx); 3607 + efx_net_stop(efx->net_dev); 3608 + down_write(&efx->filter_sem); 3609 + efx_ef10_filter_table_remove(efx); 3610 + 3611 + ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR), 3612 + efx->net_dev->dev_addr); 3613 + MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID, 3614 + nic_data->vport_id); 3615 + rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf, 3616 + sizeof(inbuf), NULL, 0, NULL); 3617 + 3618 + efx_ef10_filter_table_probe(efx); 3619 + up_write(&efx->filter_sem); 3620 + if (was_enabled) 3621 + efx_net_open(efx->net_dev); 3622 + netif_device_attach(efx->net_dev); 3623 + 3624 + #if !defined(CONFIG_SFC_SRIOV) 3625 + if (rc == -EPERM) 3626 + netif_err(efx, drv, efx->net_dev, 3627 + "Cannot change MAC address; use sfboot to enable mac-spoofing" 3628 + " on this interface\n"); 3629 + #else 3630 + if (rc == -EPERM) { 3631 + struct pci_dev *pci_dev_pf = efx->pci_dev->physfn; 3632 + 3633 + /* Switch to PF and change MAC address on vport */ 3634 + if (efx->pci_dev->is_virtfn && pci_dev_pf) { 3635 + struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf); 3636 + 3637 + if (!efx_ef10_sriov_set_vf_mac(efx_pf, 3638 + nic_data->vf_index, 3639 + efx->net_dev->dev_addr)) 3640 + return 0; 3641 + } 3642 + netif_err(efx, drv, efx->net_dev, 3643 + "Cannot change MAC address; use sfboot to enable mac-spoofing" 3644 + " on this interface\n"); 3645 + } else if (efx->pci_dev->is_virtfn) { 3646 + /* Successfully changed by VF (with MAC spoofing), so update the 3647 + * parent PF if possible. 3648 + */ 3649 + struct pci_dev *pci_dev_pf = efx->pci_dev->physfn; 3650 + 3651 + if (pci_dev_pf) { 3652 + struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf); 3653 + struct efx_ef10_nic_data *nic_data = efx_pf->nic_data; 3654 + unsigned int i; 3655 + 3656 + for (i = 0; i < efx_pf->vf_count; ++i) { 3657 + struct ef10_vf *vf = nic_data->vf + i; 3658 + 3659 + if (vf->efx == efx) { 3660 + ether_addr_copy(vf->mac, 3661 + efx->net_dev->dev_addr); 3662 + return 0; 3663 + } 3664 + } 3665 + } 3666 + } 3667 + #endif 3668 + return rc; 3669 + } 3670 + 3599 3671 static int efx_ef10_mac_reconfigure(struct efx_nic *efx) 3600 3672 { 3601 3673 efx_ef10_filter_sync_rx_mode(efx); ··· 4093 4021 .vswitching_remove = efx_ef10_vswitching_remove_vf, 4094 4022 #endif 4095 4023 .get_mac_address = efx_ef10_get_mac_address_vf, 4024 + .set_mac_address = efx_ef10_set_mac_address, 4096 4025 4097 4026 .revision = EFX_REV_HUNT_A0, 4098 4027 .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), ··· 4200 4127 .sriov_configure = efx_ef10_sriov_configure, 4201 4128 .sriov_init = efx_ef10_sriov_init, 4202 4129 .sriov_fini = efx_ef10_sriov_fini, 4203 - .sriov_mac_address_changed = efx_ef10_sriov_mac_address_changed, 4204 4130 .sriov_wanted = efx_ef10_sriov_wanted, 4205 4131 .sriov_reset = efx_ef10_sriov_reset, 4206 4132 .sriov_flr = efx_ef10_sriov_flr, ··· 4213 4141 .vswitching_remove = efx_ef10_vswitching_remove_pf, 4214 4142 #endif 4215 4143 .get_mac_address = efx_ef10_get_mac_address_pf, 4144 + .set_mac_address = efx_ef10_set_mac_address, 4216 4145 4217 4146 .revision = EFX_REV_HUNT_A0, 4218 4147 .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
-4
drivers/net/ethernet/sfc/ef10_sriov.h
··· 36 36 37 37 int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs); 38 38 int efx_ef10_sriov_init(struct efx_nic *efx); 39 - static inline int efx_ef10_sriov_mac_address_changed(struct efx_nic *efx) 40 - { 41 - return -EOPNOTSUPP; 42 - } 43 39 static inline void efx_ef10_sriov_reset(struct efx_nic *efx) {} 44 40 void efx_ef10_sriov_fini(struct efx_nic *efx); 45 41 static inline void efx_ef10_sriov_flr(struct efx_nic *efx, unsigned vf_i) {}
+2 -2
drivers/net/ethernet/sfc/efx.c
··· 2227 2227 /* save old address */ 2228 2228 ether_addr_copy(old_addr, net_dev->dev_addr); 2229 2229 ether_addr_copy(net_dev->dev_addr, new_addr); 2230 - if (efx->type->sriov_mac_address_changed) { 2231 - rc = efx->type->sriov_mac_address_changed(efx); 2230 + if (efx->type->set_mac_address) { 2231 + rc = efx->type->set_mac_address(efx); 2232 2232 if (rc) { 2233 2233 ether_addr_copy(net_dev->dev_addr, old_addr); 2234 2234 return rc;
+40
drivers/net/ethernet/sfc/mcdi_pcol.h
··· 5954 5954 5955 5955 5956 5956 /***********************************/ 5957 + /* MC_CMD_VADAPTOR_SET_MAC 5958 + * assign a new MAC address to a v-adaptor. 5959 + */ 5960 + #define MC_CMD_VADAPTOR_SET_MAC 0x5d 5961 + 5962 + #define MC_CMD_0x5d_PRIVILEGE_CTG SRIOV_CTG_GENERAL 5963 + 5964 + /* MC_CMD_VADAPTOR_SET_MAC_IN msgrequest */ 5965 + #define MC_CMD_VADAPTOR_SET_MAC_IN_LEN 10 5966 + /* The port to which the v-adaptor is connected. */ 5967 + #define MC_CMD_VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID_OFST 0 5968 + /* The new MAC address to assign to this v-adaptor */ 5969 + #define MC_CMD_VADAPTOR_SET_MAC_IN_MACADDR_OFST 4 5970 + #define MC_CMD_VADAPTOR_SET_MAC_IN_MACADDR_LEN 6 5971 + 5972 + /* MC_CMD_VADAPTOR_SET_MAC_OUT msgresponse */ 5973 + #define MC_CMD_VADAPTOR_SET_MAC_OUT_LEN 0 5974 + 5975 + 5976 + /***********************************/ 5977 + /* MC_CMD_VADAPTOR_GET_MAC 5978 + * read the MAC address assigned to a v-adaptor. 5979 + */ 5980 + #define MC_CMD_VADAPTOR_GET_MAC 0x5e 5981 + 5982 + #define MC_CMD_0x5e_PRIVILEGE_CTG SRIOV_CTG_GENERAL 5983 + 5984 + /* MC_CMD_VADAPTOR_GET_MAC_IN msgrequest */ 5985 + #define MC_CMD_VADAPTOR_GET_MAC_IN_LEN 4 5986 + /* The port to which the v-adaptor is connected. */ 5987 + #define MC_CMD_VADAPTOR_GET_MAC_IN_UPSTREAM_PORT_ID_OFST 0 5988 + 5989 + /* MC_CMD_VADAPTOR_GET_MAC_OUT msgresponse */ 5990 + #define MC_CMD_VADAPTOR_GET_MAC_OUT_LEN 6 5991 + /* The MAC address assigned to this v-adaptor */ 5992 + #define MC_CMD_VADAPTOR_GET_MAC_OUT_MACADDR_OFST 0 5993 + #define MC_CMD_VADAPTOR_GET_MAC_OUT_MACADDR_LEN 6 5994 + 5995 + 5996 + /***********************************/ 5957 5997 /* MC_CMD_EVB_PORT_ASSIGN 5958 5998 * assign a port to a PCI function. 5959 5999 */
+1
drivers/net/ethernet/sfc/mcdi_port.c
··· 865 865 866 866 BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0); 867 867 868 + /* This has no effect on EF10 */ 868 869 ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR), 869 870 efx->net_dev->dev_addr); 870 871
+2 -1
drivers/net/ethernet/sfc/net_driver.h
··· 1205 1205 * @ptp_set_ts_config: Set hardware timestamp configuration. The flags 1206 1206 * and tx_type will already have been validated but this operation 1207 1207 * must validate and update rx_filter. 1208 + * @set_mac_address: Set the MAC address of the device 1208 1209 * @revision: Hardware architecture revision 1209 1210 * @txd_ptr_tbl_base: TX descriptor ring base address 1210 1211 * @rxd_ptr_tbl_base: RX descriptor ring base address ··· 1338 1337 int (*sriov_configure)(struct efx_nic *efx, int num_vfs); 1339 1338 int (*sriov_init)(struct efx_nic *efx); 1340 1339 void (*sriov_fini)(struct efx_nic *efx); 1341 - int (*sriov_mac_address_changed)(struct efx_nic *efx); 1342 1340 bool (*sriov_wanted)(struct efx_nic *efx); 1343 1341 void (*sriov_reset)(struct efx_nic *efx); 1344 1342 void (*sriov_flr)(struct efx_nic *efx, unsigned vf_i); ··· 1354 1354 int (*vswitching_restore)(struct efx_nic *efx); 1355 1355 void (*vswitching_remove)(struct efx_nic *efx); 1356 1356 int (*get_mac_address)(struct efx_nic *efx, unsigned char *perm_addr); 1357 + int (*set_mac_address)(struct efx_nic *efx); 1357 1358 1358 1359 int revision; 1359 1360 unsigned int txd_ptr_tbl_base;
+1 -1
drivers/net/ethernet/sfc/siena.c
··· 1010 1010 .sriov_configure = efx_siena_sriov_configure, 1011 1011 .sriov_init = efx_siena_sriov_init, 1012 1012 .sriov_fini = efx_siena_sriov_fini, 1013 - .sriov_mac_address_changed = efx_siena_sriov_mac_address_changed, 1014 1013 .sriov_wanted = efx_siena_sriov_wanted, 1015 1014 .sriov_reset = efx_siena_sriov_reset, 1016 1015 .sriov_flr = efx_siena_sriov_flr, ··· 1020 1021 .vswitching_probe = efx_port_dummy_op_int, 1021 1022 .vswitching_restore = efx_port_dummy_op_int, 1022 1023 .vswitching_remove = efx_port_dummy_op_void, 1024 + .set_mac_address = efx_siena_sriov_mac_address_changed, 1023 1025 #endif 1024 1026 1025 1027 .revision = EFX_REV_SIENA_A0,