Commit 910c8789 authored by Shradha Shah's avatar Shradha Shah Committed by David S. Miller

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: default avatarShradha Shah <sshah@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 860d2ffa
...@@ -3596,6 +3596,78 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) ...@@ -3596,6 +3596,78 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx)
WARN_ON(remove_failed); WARN_ON(remove_failed);
} }
static int efx_ef10_set_mac_address(struct efx_nic *efx)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
struct efx_ef10_nic_data *nic_data = efx->nic_data;
bool was_enabled = efx->port_enabled;
int rc;
efx_device_detach_sync(efx);
efx_net_stop(efx->net_dev);
down_write(&efx->filter_sem);
efx_ef10_filter_table_remove(efx);
ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR),
efx->net_dev->dev_addr);
MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
nic_data->vport_id);
rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
sizeof(inbuf), NULL, 0, NULL);
efx_ef10_filter_table_probe(efx);
up_write(&efx->filter_sem);
if (was_enabled)
efx_net_open(efx->net_dev);
netif_device_attach(efx->net_dev);
#if !defined(CONFIG_SFC_SRIOV)
if (rc == -EPERM)
netif_err(efx, drv, efx->net_dev,
"Cannot change MAC address; use sfboot to enable mac-spoofing"
" on this interface\n");
#else
if (rc == -EPERM) {
struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
/* Switch to PF and change MAC address on vport */
if (efx->pci_dev->is_virtfn && pci_dev_pf) {
struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
if (!efx_ef10_sriov_set_vf_mac(efx_pf,
nic_data->vf_index,
efx->net_dev->dev_addr))
return 0;
}
netif_err(efx, drv, efx->net_dev,
"Cannot change MAC address; use sfboot to enable mac-spoofing"
" on this interface\n");
} else if (efx->pci_dev->is_virtfn) {
/* Successfully changed by VF (with MAC spoofing), so update the
* parent PF if possible.
*/
struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
if (pci_dev_pf) {
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;
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;
}
}
}
}
#endif
return rc;
}
static int efx_ef10_mac_reconfigure(struct efx_nic *efx) static int efx_ef10_mac_reconfigure(struct efx_nic *efx)
{ {
efx_ef10_filter_sync_rx_mode(efx); efx_ef10_filter_sync_rx_mode(efx);
...@@ -4021,6 +4093,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { ...@@ -4021,6 +4093,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.vswitching_remove = efx_ef10_vswitching_remove_vf, .vswitching_remove = efx_ef10_vswitching_remove_vf,
#endif #endif
.get_mac_address = efx_ef10_get_mac_address_vf, .get_mac_address = efx_ef10_get_mac_address_vf,
.set_mac_address = efx_ef10_set_mac_address,
.revision = EFX_REV_HUNT_A0, .revision = EFX_REV_HUNT_A0,
.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
...@@ -4127,7 +4200,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { ...@@ -4127,7 +4200,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.sriov_configure = efx_ef10_sriov_configure, .sriov_configure = efx_ef10_sriov_configure,
.sriov_init = efx_ef10_sriov_init, .sriov_init = efx_ef10_sriov_init,
.sriov_fini = efx_ef10_sriov_fini, .sriov_fini = efx_ef10_sriov_fini,
.sriov_mac_address_changed = efx_ef10_sriov_mac_address_changed,
.sriov_wanted = efx_ef10_sriov_wanted, .sriov_wanted = efx_ef10_sriov_wanted,
.sriov_reset = efx_ef10_sriov_reset, .sriov_reset = efx_ef10_sriov_reset,
.sriov_flr = efx_ef10_sriov_flr, .sriov_flr = efx_ef10_sriov_flr,
...@@ -4141,6 +4213,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { ...@@ -4141,6 +4213,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.vswitching_remove = efx_ef10_vswitching_remove_pf, .vswitching_remove = efx_ef10_vswitching_remove_pf,
#endif #endif
.get_mac_address = efx_ef10_get_mac_address_pf, .get_mac_address = efx_ef10_get_mac_address_pf,
.set_mac_address = efx_ef10_set_mac_address,
.revision = EFX_REV_HUNT_A0, .revision = EFX_REV_HUNT_A0,
.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
......
...@@ -36,10 +36,6 @@ static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) ...@@ -36,10 +36,6 @@ static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx)
int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs); int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs);
int efx_ef10_sriov_init(struct efx_nic *efx); int efx_ef10_sriov_init(struct efx_nic *efx);
static inline int efx_ef10_sriov_mac_address_changed(struct efx_nic *efx)
{
return -EOPNOTSUPP;
}
static inline void efx_ef10_sriov_reset(struct efx_nic *efx) {} static inline void efx_ef10_sriov_reset(struct efx_nic *efx) {}
void efx_ef10_sriov_fini(struct efx_nic *efx); void efx_ef10_sriov_fini(struct efx_nic *efx);
static inline void efx_ef10_sriov_flr(struct efx_nic *efx, unsigned vf_i) {} static inline void efx_ef10_sriov_flr(struct efx_nic *efx, unsigned vf_i) {}
......
...@@ -2227,8 +2227,8 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) ...@@ -2227,8 +2227,8 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
/* save old address */ /* save old address */
ether_addr_copy(old_addr, net_dev->dev_addr); ether_addr_copy(old_addr, net_dev->dev_addr);
ether_addr_copy(net_dev->dev_addr, new_addr); ether_addr_copy(net_dev->dev_addr, new_addr);
if (efx->type->sriov_mac_address_changed) { if (efx->type->set_mac_address) {
rc = efx->type->sriov_mac_address_changed(efx); rc = efx->type->set_mac_address(efx);
if (rc) { if (rc) {
ether_addr_copy(net_dev->dev_addr, old_addr); ether_addr_copy(net_dev->dev_addr, old_addr);
return rc; return rc;
......
...@@ -5953,6 +5953,46 @@ ...@@ -5953,6 +5953,46 @@
#define MC_CMD_VADAPTOR_FREE_OUT_LEN 0 #define MC_CMD_VADAPTOR_FREE_OUT_LEN 0
/***********************************/
/* MC_CMD_VADAPTOR_SET_MAC
* assign a new MAC address to a v-adaptor.
*/
#define MC_CMD_VADAPTOR_SET_MAC 0x5d
#define MC_CMD_0x5d_PRIVILEGE_CTG SRIOV_CTG_GENERAL
/* MC_CMD_VADAPTOR_SET_MAC_IN msgrequest */
#define MC_CMD_VADAPTOR_SET_MAC_IN_LEN 10
/* The port to which the v-adaptor is connected. */
#define MC_CMD_VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID_OFST 0
/* The new MAC address to assign to this v-adaptor */
#define MC_CMD_VADAPTOR_SET_MAC_IN_MACADDR_OFST 4
#define MC_CMD_VADAPTOR_SET_MAC_IN_MACADDR_LEN 6
/* MC_CMD_VADAPTOR_SET_MAC_OUT msgresponse */
#define MC_CMD_VADAPTOR_SET_MAC_OUT_LEN 0
/***********************************/
/* MC_CMD_VADAPTOR_GET_MAC
* read the MAC address assigned to a v-adaptor.
*/
#define MC_CMD_VADAPTOR_GET_MAC 0x5e
#define MC_CMD_0x5e_PRIVILEGE_CTG SRIOV_CTG_GENERAL
/* MC_CMD_VADAPTOR_GET_MAC_IN msgrequest */
#define MC_CMD_VADAPTOR_GET_MAC_IN_LEN 4
/* The port to which the v-adaptor is connected. */
#define MC_CMD_VADAPTOR_GET_MAC_IN_UPSTREAM_PORT_ID_OFST 0
/* MC_CMD_VADAPTOR_GET_MAC_OUT msgresponse */
#define MC_CMD_VADAPTOR_GET_MAC_OUT_LEN 6
/* The MAC address assigned to this v-adaptor */
#define MC_CMD_VADAPTOR_GET_MAC_OUT_MACADDR_OFST 0
#define MC_CMD_VADAPTOR_GET_MAC_OUT_MACADDR_LEN 6
/***********************************/ /***********************************/
/* MC_CMD_EVB_PORT_ASSIGN /* MC_CMD_EVB_PORT_ASSIGN
* assign a port to a PCI function. * assign a port to a PCI function.
......
...@@ -865,6 +865,7 @@ int efx_mcdi_set_mac(struct efx_nic *efx) ...@@ -865,6 +865,7 @@ int efx_mcdi_set_mac(struct efx_nic *efx)
BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0); BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0);
/* This has no effect on EF10 */
ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR), ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR),
efx->net_dev->dev_addr); efx->net_dev->dev_addr);
......
...@@ -1205,6 +1205,7 @@ struct efx_mtd_partition { ...@@ -1205,6 +1205,7 @@ struct efx_mtd_partition {
* @ptp_set_ts_config: Set hardware timestamp configuration. The flags * @ptp_set_ts_config: Set hardware timestamp configuration. The flags
* and tx_type will already have been validated but this operation * and tx_type will already have been validated but this operation
* must validate and update rx_filter. * must validate and update rx_filter.
* @set_mac_address: Set the MAC address of the device
* @revision: Hardware architecture revision * @revision: Hardware architecture revision
* @txd_ptr_tbl_base: TX descriptor ring base address * @txd_ptr_tbl_base: TX descriptor ring base address
* @rxd_ptr_tbl_base: RX descriptor ring base address * @rxd_ptr_tbl_base: RX descriptor ring base address
...@@ -1337,7 +1338,6 @@ struct efx_nic_type { ...@@ -1337,7 +1338,6 @@ struct efx_nic_type {
int (*sriov_configure)(struct efx_nic *efx, int num_vfs); int (*sriov_configure)(struct efx_nic *efx, int num_vfs);
int (*sriov_init)(struct efx_nic *efx); int (*sriov_init)(struct efx_nic *efx);
void (*sriov_fini)(struct efx_nic *efx); void (*sriov_fini)(struct efx_nic *efx);
int (*sriov_mac_address_changed)(struct efx_nic *efx);
bool (*sriov_wanted)(struct efx_nic *efx); bool (*sriov_wanted)(struct efx_nic *efx);
void (*sriov_reset)(struct efx_nic *efx); void (*sriov_reset)(struct efx_nic *efx);
void (*sriov_flr)(struct efx_nic *efx, unsigned vf_i); void (*sriov_flr)(struct efx_nic *efx, unsigned vf_i);
...@@ -1354,6 +1354,7 @@ struct efx_nic_type { ...@@ -1354,6 +1354,7 @@ struct efx_nic_type {
int (*vswitching_restore)(struct efx_nic *efx); int (*vswitching_restore)(struct efx_nic *efx);
void (*vswitching_remove)(struct efx_nic *efx); void (*vswitching_remove)(struct efx_nic *efx);
int (*get_mac_address)(struct efx_nic *efx, unsigned char *perm_addr); int (*get_mac_address)(struct efx_nic *efx, unsigned char *perm_addr);
int (*set_mac_address)(struct efx_nic *efx);
int revision; int revision;
unsigned int txd_ptr_tbl_base; unsigned int txd_ptr_tbl_base;
......
...@@ -1010,7 +1010,6 @@ const struct efx_nic_type siena_a0_nic_type = { ...@@ -1010,7 +1010,6 @@ const struct efx_nic_type siena_a0_nic_type = {
.sriov_configure = efx_siena_sriov_configure, .sriov_configure = efx_siena_sriov_configure,
.sriov_init = efx_siena_sriov_init, .sriov_init = efx_siena_sriov_init,
.sriov_fini = efx_siena_sriov_fini, .sriov_fini = efx_siena_sriov_fini,
.sriov_mac_address_changed = efx_siena_sriov_mac_address_changed,
.sriov_wanted = efx_siena_sriov_wanted, .sriov_wanted = efx_siena_sriov_wanted,
.sriov_reset = efx_siena_sriov_reset, .sriov_reset = efx_siena_sriov_reset,
.sriov_flr = efx_siena_sriov_flr, .sriov_flr = efx_siena_sriov_flr,
...@@ -1021,6 +1020,7 @@ const struct efx_nic_type siena_a0_nic_type = { ...@@ -1021,6 +1020,7 @@ const struct efx_nic_type siena_a0_nic_type = {
.vswitching_probe = efx_port_dummy_op_int, .vswitching_probe = efx_port_dummy_op_int,
.vswitching_restore = efx_port_dummy_op_int, .vswitching_restore = efx_port_dummy_op_int,
.vswitching_remove = efx_port_dummy_op_void, .vswitching_remove = efx_port_dummy_op_void,
.set_mac_address = efx_siena_sriov_mac_address_changed,
#endif #endif
.revision = EFX_REV_SIENA_A0, .revision = EFX_REV_SIENA_A0,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment