Merge branch 'sfc-set-mac'
Shradha Shah says: ==================== sfc: compat for lack of VADAPTOR_SET_MAC in adaptor_firmware <= 4.1.1.1023 This patch series resolves an incompatibility with legacy firmware due to the lack of MC_CMD_VADAPTOR_SET_MAC in adaptor_firmware <= 4.1.1.1023 Unless this patch series is applied there will be a compatibility issue between the driver and Solarflare adapters running older firmware. Tested with and without CONFIG_SFC_SRIOV ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4df48e8c0e
|
@ -101,6 +101,11 @@ static unsigned int efx_ef10_mem_map_size(struct efx_nic *efx)
|
||||||
return resource_size(&efx->pci_dev->resource[bar]);
|
return resource_size(&efx->pci_dev->resource[bar]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool efx_ef10_is_vf(struct efx_nic *efx)
|
||||||
|
{
|
||||||
|
return efx->type->is_vf;
|
||||||
|
}
|
||||||
|
|
||||||
static int efx_ef10_get_pf_index(struct efx_nic *efx)
|
static int efx_ef10_get_pf_index(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN);
|
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN);
|
||||||
|
@ -677,6 +682,48 @@ static int efx_ef10_probe_pf(struct efx_nic *efx)
|
||||||
return efx_ef10_probe(efx);
|
return efx_ef10_probe(efx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
|
||||||
|
{
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
|
||||||
|
return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
|
||||||
|
NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
|
||||||
|
{
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
|
||||||
|
return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
|
||||||
|
NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int efx_ef10_vport_add_mac(struct efx_nic *efx,
|
||||||
|
unsigned int port_id, u8 *mac)
|
||||||
|
{
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
|
||||||
|
ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
|
||||||
|
|
||||||
|
return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
|
||||||
|
sizeof(inbuf), NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int efx_ef10_vport_del_mac(struct efx_nic *efx,
|
||||||
|
unsigned int port_id, u8 *mac)
|
||||||
|
{
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
|
||||||
|
ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
|
||||||
|
|
||||||
|
return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
|
||||||
|
sizeof(inbuf), NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SFC_SRIOV
|
#ifdef CONFIG_SFC_SRIOV
|
||||||
static int efx_ef10_probe_vf(struct efx_nic *efx)
|
static int efx_ef10_probe_vf(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
|
@ -3804,6 +3851,72 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx)
|
||||||
WARN_ON(remove_failed);
|
WARN_ON(remove_failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
|
||||||
|
{
|
||||||
|
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
||||||
|
u8 mac_old[ETH_ALEN];
|
||||||
|
int rc, rc2;
|
||||||
|
|
||||||
|
/* Only reconfigure a PF-created vport */
|
||||||
|
if (is_zero_ether_addr(nic_data->vport_mac))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
efx_device_detach_sync(efx);
|
||||||
|
efx_net_stop(efx->net_dev);
|
||||||
|
down_write(&efx->filter_sem);
|
||||||
|
efx_ef10_filter_table_remove(efx);
|
||||||
|
up_write(&efx->filter_sem);
|
||||||
|
|
||||||
|
rc = efx_ef10_vadaptor_free(efx, nic_data->vport_id);
|
||||||
|
if (rc)
|
||||||
|
goto restore_filters;
|
||||||
|
|
||||||
|
ether_addr_copy(mac_old, nic_data->vport_mac);
|
||||||
|
rc = efx_ef10_vport_del_mac(efx, nic_data->vport_id,
|
||||||
|
nic_data->vport_mac);
|
||||||
|
if (rc)
|
||||||
|
goto restore_vadaptor;
|
||||||
|
|
||||||
|
rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id,
|
||||||
|
efx->net_dev->dev_addr);
|
||||||
|
if (!rc) {
|
||||||
|
ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr);
|
||||||
|
} else {
|
||||||
|
rc2 = efx_ef10_vport_add_mac(efx, nic_data->vport_id, mac_old);
|
||||||
|
if (rc2) {
|
||||||
|
/* Failed to add original MAC, so clear vport_mac */
|
||||||
|
eth_zero_addr(nic_data->vport_mac);
|
||||||
|
goto reset_nic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_vadaptor:
|
||||||
|
rc2 = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
|
||||||
|
if (rc2)
|
||||||
|
goto reset_nic;
|
||||||
|
restore_filters:
|
||||||
|
down_write(&efx->filter_sem);
|
||||||
|
rc2 = efx_ef10_filter_table_probe(efx);
|
||||||
|
up_write(&efx->filter_sem);
|
||||||
|
if (rc2)
|
||||||
|
goto reset_nic;
|
||||||
|
|
||||||
|
rc2 = efx_net_open(efx->net_dev);
|
||||||
|
if (rc2)
|
||||||
|
goto reset_nic;
|
||||||
|
|
||||||
|
netif_device_attach(efx->net_dev);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
reset_nic:
|
||||||
|
netif_err(efx, drv, efx->net_dev,
|
||||||
|
"Failed to restore when changing MAC address - scheduling reset\n");
|
||||||
|
efx_schedule_reset(efx, RESET_TYPE_DATAPATH);
|
||||||
|
|
||||||
|
return rc ? rc : rc2;
|
||||||
|
}
|
||||||
|
|
||||||
static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
|
||||||
|
@ -3820,8 +3933,8 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
||||||
efx->net_dev->dev_addr);
|
efx->net_dev->dev_addr);
|
||||||
MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
|
MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
|
||||||
nic_data->vport_id);
|
nic_data->vport_id);
|
||||||
rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
|
rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
|
||||||
sizeof(inbuf), NULL, 0, NULL);
|
sizeof(inbuf), NULL, 0, NULL);
|
||||||
|
|
||||||
efx_ef10_filter_table_probe(efx);
|
efx_ef10_filter_table_probe(efx);
|
||||||
up_write(&efx->filter_sem);
|
up_write(&efx->filter_sem);
|
||||||
|
@ -3829,38 +3942,27 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
||||||
efx_net_open(efx->net_dev);
|
efx_net_open(efx->net_dev);
|
||||||
netif_device_attach(efx->net_dev);
|
netif_device_attach(efx->net_dev);
|
||||||
|
|
||||||
#if !defined(CONFIG_SFC_SRIOV)
|
#ifdef CONFIG_SFC_SRIOV
|
||||||
if (rc == -EPERM)
|
if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) {
|
||||||
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;
|
struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
|
||||||
|
|
||||||
/* Switch to PF and change MAC address on vport */
|
if (rc == -EPERM) {
|
||||||
if (efx->pci_dev->is_virtfn && pci_dev_pf) {
|
struct efx_nic *efx_pf;
|
||||||
struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
|
|
||||||
|
|
||||||
if (!efx_ef10_sriov_set_vf_mac(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,
|
nic_data->vf_index,
|
||||||
efx->net_dev->dev_addr))
|
efx->net_dev->dev_addr);
|
||||||
return 0;
|
} else if (!rc) {
|
||||||
}
|
|
||||||
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_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
|
||||||
struct efx_ef10_nic_data *nic_data = efx_pf->nic_data;
|
struct efx_ef10_nic_data *nic_data = efx_pf->nic_data;
|
||||||
unsigned int i;
|
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) {
|
for (i = 0; i < efx_pf->vf_count; ++i) {
|
||||||
struct ef10_vf *vf = nic_data->vf + i;
|
struct ef10_vf *vf = nic_data->vf + i;
|
||||||
|
|
||||||
|
@ -3871,8 +3973,24 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
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 == -ENOSYS && !efx_ef10_is_vf(efx)) {
|
||||||
|
/* If the active MCFW does not support MC_CMD_VADAPTOR_SET_MAC
|
||||||
|
* fall-back to the method of changing the MAC address on the
|
||||||
|
* vport. This only applies to PFs because such versions of
|
||||||
|
* MCFW do not support VFs.
|
||||||
|
*/
|
||||||
|
rc = efx_ef10_vport_set_mac_address(efx);
|
||||||
|
} else {
|
||||||
|
efx_mcdi_display_error(efx, MC_CMD_VADAPTOR_SET_MAC,
|
||||||
|
sizeof(inbuf), NULL, 0, rc);
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,30 +29,6 @@ static int efx_ef10_evb_port_assign(struct efx_nic *efx, unsigned int port_id,
|
||||||
NULL, 0, NULL);
|
NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efx_ef10_vport_add_mac(struct efx_nic *efx,
|
|
||||||
unsigned int port_id, u8 *mac)
|
|
||||||
{
|
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
|
|
||||||
|
|
||||||
MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
|
|
||||||
ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
|
|
||||||
|
|
||||||
return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
|
|
||||||
sizeof(inbuf), NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int efx_ef10_vport_del_mac(struct efx_nic *efx,
|
|
||||||
unsigned int port_id, u8 *mac)
|
|
||||||
{
|
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
|
|
||||||
|
|
||||||
MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
|
|
||||||
ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
|
|
||||||
|
|
||||||
return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
|
|
||||||
sizeof(inbuf), NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
|
static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
|
||||||
unsigned int vswitch_type)
|
unsigned int vswitch_type)
|
||||||
{
|
{
|
||||||
|
@ -136,24 +112,6 @@ static int efx_ef10_vport_free(struct efx_nic *efx, unsigned int port_id)
|
||||||
NULL, 0, NULL);
|
NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
|
|
||||||
{
|
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
|
|
||||||
|
|
||||||
MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
|
|
||||||
return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
|
|
||||||
NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
|
|
||||||
{
|
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
|
|
||||||
|
|
||||||
MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
|
|
||||||
return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
|
|
||||||
NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx)
|
static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
||||||
|
|
|
@ -65,5 +65,11 @@ int efx_ef10_vswitching_restore_pf(struct efx_nic *efx);
|
||||||
int efx_ef10_vswitching_restore_vf(struct efx_nic *efx);
|
int efx_ef10_vswitching_restore_vf(struct efx_nic *efx);
|
||||||
void efx_ef10_vswitching_remove_pf(struct efx_nic *efx);
|
void efx_ef10_vswitching_remove_pf(struct efx_nic *efx);
|
||||||
void efx_ef10_vswitching_remove_vf(struct efx_nic *efx);
|
void efx_ef10_vswitching_remove_vf(struct efx_nic *efx);
|
||||||
|
int efx_ef10_vport_add_mac(struct efx_nic *efx,
|
||||||
|
unsigned int port_id, u8 *mac);
|
||||||
|
int efx_ef10_vport_del_mac(struct efx_nic *efx,
|
||||||
|
unsigned int port_id, u8 *mac);
|
||||||
|
int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id);
|
||||||
|
int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id);
|
||||||
|
|
||||||
#endif /* EF10_SRIOV_H */
|
#endif /* EF10_SRIOV_H */
|
||||||
|
|
Loading…
Reference in New Issue