Commit 4e7b3be4 authored by David S. Miller's avatar David S. Miller

Merge branch 'sfc-next'

Shradha Shah says:

====================
sfc: Get/Set MAC address and ndo_[set/get]_vf_* entrypoint functions

This is the second installment of patches towards supporting EF10 SRIOV.

This patch series implements the ndo_get_vf_config, ndo_set_vf_mac,
ndo_set_vf_vlan and ndo_set_vf_spoofcheck function callbacks for EF10.

This patch series also introduces privileges for the MCDI commands
based on which functions are allowed to call them, i.e. Link control
or primary function.

The patch series has been tested with and without CONFIG_SFC_SRIOV.

The ndo function callbacks are tested using ip link.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4ec49a37 910c8789
This diff is collapsed.
This diff is collapsed.
...@@ -14,14 +14,19 @@ ...@@ -14,14 +14,19 @@
/** /**
* struct ef10_vf - PF's store of VF data * struct ef10_vf - PF's store of VF data
* @efx: efx_nic struct for the current VF
* @vport_id: vport ID for the VF * @vport_id: vport ID for the VF
* @vport_assigned: record whether the vport is currently assigned to the VF * @vport_assigned: record whether the vport is currently assigned to the VF
* @mac: MAC address for the VF, zero when address is removed from the vport * @mac: MAC address for the VF, zero when address is removed from the vport
* @vlan: Default VLAN for the VF or #EFX_EF10_NO_VLAN
*/ */
struct ef10_vf { struct ef10_vf {
struct efx_nic *efx;
unsigned int vport_id; unsigned int vport_id;
unsigned int vport_assigned; unsigned int vport_assigned;
u8 mac[ETH_ALEN]; u8 mac[ETH_ALEN];
u16 vlan;
#define EFX_EF10_NO_VLAN 0
}; };
static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx)
...@@ -31,34 +36,23 @@ static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) ...@@ -31,34 +36,23 @@ 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 void efx_ef10_sriov_mac_address_changed(struct efx_nic *efx) {}
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) {}
static inline int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf, int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf, u8 *mac);
u8 *mac)
{
return -EOPNOTSUPP;
}
static inline int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf, int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i,
u16 vlan, u8 qos) u16 vlan, u8 qos);
{
return -EOPNOTSUPP;
}
static inline int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf, int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf,
bool spoofchk) bool spoofchk);
{
return -EOPNOTSUPP;
}
static inline int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf, int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf_i,
struct ifla_vf_info *ivf) struct ifla_vf_info *ivf);
{
return -EOPNOTSUPP; int efx_ef10_sriov_set_vf_link_state(struct efx_nic *efx, int vf_i,
} int link_state);
int efx_ef10_vswitching_probe_pf(struct efx_nic *efx); int efx_ef10_vswitching_probe_pf(struct efx_nic *efx);
int efx_ef10_vswitching_probe_vf(struct efx_nic *efx); int efx_ef10_vswitching_probe_vf(struct efx_nic *efx);
......
...@@ -77,6 +77,7 @@ const char *const efx_reset_type_names[] = { ...@@ -77,6 +77,7 @@ const char *const efx_reset_type_names[] = {
[RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL", [RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL",
[RESET_TYPE_WORLD] = "WORLD", [RESET_TYPE_WORLD] = "WORLD",
[RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE", [RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE",
[RESET_TYPE_DATAPATH] = "DATAPATH",
[RESET_TYPE_MC_BIST] = "MC_BIST", [RESET_TYPE_MC_BIST] = "MC_BIST",
[RESET_TYPE_DISABLE] = "DISABLE", [RESET_TYPE_DISABLE] = "DISABLE",
[RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG", [RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG",
...@@ -949,6 +950,16 @@ void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc) ...@@ -949,6 +950,16 @@ void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc)
static void efx_fini_port(struct efx_nic *efx); static void efx_fini_port(struct efx_nic *efx);
/* We assume that efx->type->reconfigure_mac will always try to sync RX
* filters and therefore needs to read-lock the filter table against freeing
*/
void efx_mac_reconfigure(struct efx_nic *efx)
{
down_read(&efx->filter_sem);
efx->type->reconfigure_mac(efx);
up_read(&efx->filter_sem);
}
/* Push loopback/power/transmit disable settings to the PHY, and reconfigure /* Push loopback/power/transmit disable settings to the PHY, and reconfigure
* the MAC appropriately. All other PHY configuration changes are pushed * the MAC appropriately. All other PHY configuration changes are pushed
* through phy_op->set_settings(), and pushed asynchronously to the MAC * through phy_op->set_settings(), and pushed asynchronously to the MAC
...@@ -1002,7 +1013,7 @@ static void efx_mac_work(struct work_struct *data) ...@@ -1002,7 +1013,7 @@ static void efx_mac_work(struct work_struct *data)
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
if (efx->port_enabled) if (efx->port_enabled)
efx->type->reconfigure_mac(efx); efx_mac_reconfigure(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
} }
...@@ -1042,7 +1053,7 @@ static int efx_init_port(struct efx_nic *efx) ...@@ -1042,7 +1053,7 @@ static int efx_init_port(struct efx_nic *efx)
/* Reconfigure the MAC before creating dma queues (required for /* Reconfigure the MAC before creating dma queues (required for
* Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */ * Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */
efx->type->reconfigure_mac(efx); efx_mac_reconfigure(efx);
/* Ensure the PHY advertises the correct flow control settings */ /* Ensure the PHY advertises the correct flow control settings */
rc = efx->phy_op->reconfigure(efx); rc = efx->phy_op->reconfigure(efx);
...@@ -1068,7 +1079,7 @@ static void efx_start_port(struct efx_nic *efx) ...@@ -1068,7 +1079,7 @@ static void efx_start_port(struct efx_nic *efx)
efx->port_enabled = true; efx->port_enabled = true;
/* Ensure MAC ingress/egress is enabled */ /* Ensure MAC ingress/egress is enabled */
efx->type->reconfigure_mac(efx); efx_mac_reconfigure(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
} }
...@@ -1672,10 +1683,11 @@ static int efx_probe_filters(struct efx_nic *efx) ...@@ -1672,10 +1683,11 @@ static int efx_probe_filters(struct efx_nic *efx)
int rc; int rc;
spin_lock_init(&efx->filter_lock); spin_lock_init(&efx->filter_lock);
init_rwsem(&efx->filter_sem);
down_write(&efx->filter_sem);
rc = efx->type->filter_table_probe(efx); rc = efx->type->filter_table_probe(efx);
if (rc) if (rc)
return rc; goto out_unlock;
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
if (efx->type->offload_features & NETIF_F_NTUPLE) { if (efx->type->offload_features & NETIF_F_NTUPLE) {
...@@ -1684,12 +1696,14 @@ static int efx_probe_filters(struct efx_nic *efx) ...@@ -1684,12 +1696,14 @@ static int efx_probe_filters(struct efx_nic *efx)
GFP_KERNEL); GFP_KERNEL);
if (!efx->rps_flow_id) { if (!efx->rps_flow_id) {
efx->type->filter_table_remove(efx); efx->type->filter_table_remove(efx);
return -ENOMEM; rc = -ENOMEM;
goto out_unlock;
} }
} }
#endif #endif
out_unlock:
return 0; up_write(&efx->filter_sem);
return rc;
} }
static void efx_remove_filters(struct efx_nic *efx) static void efx_remove_filters(struct efx_nic *efx)
...@@ -1697,12 +1711,16 @@ static void efx_remove_filters(struct efx_nic *efx) ...@@ -1697,12 +1711,16 @@ static void efx_remove_filters(struct efx_nic *efx)
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
kfree(efx->rps_flow_id); kfree(efx->rps_flow_id);
#endif #endif
down_write(&efx->filter_sem);
efx->type->filter_table_remove(efx); efx->type->filter_table_remove(efx);
up_write(&efx->filter_sem);
} }
static void efx_restore_filters(struct efx_nic *efx) static void efx_restore_filters(struct efx_nic *efx)
{ {
down_read(&efx->filter_sem);
efx->type->filter_table_restore(efx); efx->type->filter_table_restore(efx);
up_read(&efx->filter_sem);
} }
/************************************************************************** /**************************************************************************
...@@ -2096,7 +2114,7 @@ static int efx_busy_poll(struct napi_struct *napi) ...@@ -2096,7 +2114,7 @@ static int efx_busy_poll(struct napi_struct *napi)
*************************************************************************/ *************************************************************************/
/* Context: process, rtnl_lock() held. */ /* Context: process, rtnl_lock() held. */
static int efx_net_open(struct net_device *net_dev) int efx_net_open(struct net_device *net_dev)
{ {
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
int rc; int rc;
...@@ -2125,7 +2143,7 @@ static int efx_net_open(struct net_device *net_dev) ...@@ -2125,7 +2143,7 @@ static int efx_net_open(struct net_device *net_dev)
* Note that the kernel will ignore our return code; this method * Note that the kernel will ignore our return code; this method
* should really be a void. * should really be a void.
*/ */
static int efx_net_stop(struct net_device *net_dev) int efx_net_stop(struct net_device *net_dev)
{ {
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
...@@ -2183,7 +2201,7 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) ...@@ -2183,7 +2201,7 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
net_dev->mtu = new_mtu; net_dev->mtu = new_mtu;
efx->type->reconfigure_mac(efx); efx_mac_reconfigure(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
efx_start_all(efx); efx_start_all(efx);
...@@ -2196,6 +2214,8 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) ...@@ -2196,6 +2214,8 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
struct sockaddr *addr = data; struct sockaddr *addr = data;
u8 *new_addr = addr->sa_data; u8 *new_addr = addr->sa_data;
u8 old_addr[6];
int rc;
if (!is_valid_ether_addr(new_addr)) { if (!is_valid_ether_addr(new_addr)) {
netif_err(efx, drv, efx->net_dev, netif_err(efx, drv, efx->net_dev,
...@@ -2204,13 +2224,20 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) ...@@ -2204,13 +2224,20 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
} }
/* save old address */
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) {
efx->type->sriov_mac_address_changed(efx); rc = efx->type->set_mac_address(efx);
if (rc) {
ether_addr_copy(net_dev->dev_addr, old_addr);
return rc;
}
}
/* Reconfigure the MAC */ /* Reconfigure the MAC */
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
efx->type->reconfigure_mac(efx); efx_mac_reconfigure(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
return 0; return 0;
...@@ -2254,6 +2281,7 @@ static const struct net_device_ops efx_netdev_ops = { ...@@ -2254,6 +2281,7 @@ static const struct net_device_ops efx_netdev_ops = {
.ndo_set_vf_vlan = efx_sriov_set_vf_vlan, .ndo_set_vf_vlan = efx_sriov_set_vf_vlan,
.ndo_set_vf_spoofchk = efx_sriov_set_vf_spoofchk, .ndo_set_vf_spoofchk = efx_sriov_set_vf_spoofchk,
.ndo_get_vf_config = efx_sriov_get_vf_config, .ndo_get_vf_config = efx_sriov_get_vf_config,
.ndo_set_vf_link_state = efx_sriov_set_vf_link_state,
#endif #endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll, .ndo_poll_controller = efx_netpoll,
...@@ -2404,7 +2432,8 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method) ...@@ -2404,7 +2432,8 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
efx_disable_interrupts(efx); efx_disable_interrupts(efx);
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
method != RESET_TYPE_DATAPATH)
efx->phy_op->fini(efx); efx->phy_op->fini(efx);
efx->type->fini(efx); efx->type->fini(efx);
} }
...@@ -2433,7 +2462,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) ...@@ -2433,7 +2462,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
if (!ok) if (!ok)
goto fail; goto fail;
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) { if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
method != RESET_TYPE_DATAPATH) {
rc = efx->phy_op->init(efx); rc = efx->phy_op->init(efx);
if (rc) if (rc)
goto fail; goto fail;
...@@ -2455,7 +2485,9 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) ...@@ -2455,7 +2485,9 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
" VFs may not function\n", rc); " VFs may not function\n", rc);
#endif #endif
down_read(&efx->filter_sem);
efx_restore_filters(efx); efx_restore_filters(efx);
up_read(&efx->filter_sem);
if (efx->type->sriov_reset) if (efx->type->sriov_reset)
efx->type->sriov_reset(efx); efx->type->sriov_reset(efx);
...@@ -2627,6 +2659,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) ...@@ -2627,6 +2659,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
case RESET_TYPE_WORLD: case RESET_TYPE_WORLD:
case RESET_TYPE_DISABLE: case RESET_TYPE_DISABLE:
case RESET_TYPE_RECOVER_OR_DISABLE: case RESET_TYPE_RECOVER_OR_DISABLE:
case RESET_TYPE_DATAPATH:
case RESET_TYPE_MC_BIST: case RESET_TYPE_MC_BIST:
case RESET_TYPE_MCDI_TIMEOUT: case RESET_TYPE_MCDI_TIMEOUT:
method = type; method = type;
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
#define EFX_MEM_BAR 2 #define EFX_MEM_BAR 2
#define EFX_MEM_VF_BAR 0 #define EFX_MEM_VF_BAR 0
int efx_net_open(struct net_device *net_dev);
int efx_net_stop(struct net_device *net_dev);
/* TX */ /* TX */
int efx_probe_tx_queue(struct efx_tx_queue *tx_queue); int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
void efx_remove_tx_queue(struct efx_tx_queue *tx_queue); void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
...@@ -74,6 +77,8 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); ...@@ -74,6 +77,8 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
/* Filters */ /* Filters */
void efx_mac_reconfigure(struct efx_nic *efx);
/** /**
* efx_filter_insert_filter - add or replace a filter * efx_filter_insert_filter - add or replace a filter
* @efx: NIC in which to insert the filter * @efx: NIC in which to insert the filter
......
...@@ -143,6 +143,7 @@ enum efx_loopback_mode { ...@@ -143,6 +143,7 @@ enum efx_loopback_mode {
* @RESET_TYPE_WORLD: Reset as much as possible * @RESET_TYPE_WORLD: Reset as much as possible
* @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if * @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if
* unsuccessful. * unsuccessful.
* @RESET_TYPE_DATAPATH: Reset datapath only.
* @RESET_TYPE_MC_BIST: MC entering BIST mode. * @RESET_TYPE_MC_BIST: MC entering BIST mode.
* @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled * @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled
* @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog
...@@ -159,6 +160,7 @@ enum reset_type { ...@@ -159,6 +160,7 @@ enum reset_type {
RESET_TYPE_ALL, RESET_TYPE_ALL,
RESET_TYPE_WORLD, RESET_TYPE_WORLD,
RESET_TYPE_RECOVER_OR_DISABLE, RESET_TYPE_RECOVER_OR_DISABLE,
RESET_TYPE_DATAPATH,
RESET_TYPE_MC_BIST, RESET_TYPE_MC_BIST,
RESET_TYPE_DISABLE, RESET_TYPE_DISABLE,
RESET_TYPE_MAX_METHOD, RESET_TYPE_MAX_METHOD,
......
...@@ -734,7 +734,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, ...@@ -734,7 +734,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
/* Reconfigure the MAC. The PHY *may* generate a link state change event /* Reconfigure the MAC. The PHY *may* generate a link state change event
* if the user just changed the advertised capabilities, but there's no * if the user just changed the advertised capabilities, but there's no
* harm doing this twice */ * harm doing this twice */
efx->type->reconfigure_mac(efx); efx_mac_reconfigure(efx);
out: out:
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
......
...@@ -406,7 +406,7 @@ static bool efx_mcdi_complete_async(struct efx_mcdi_iface *mcdi, bool timeout) ...@@ -406,7 +406,7 @@ static bool efx_mcdi_complete_async(struct efx_mcdi_iface *mcdi, bool timeout)
struct efx_mcdi_async_param *async; struct efx_mcdi_async_param *async;
size_t hdr_len, data_len, err_len; size_t hdr_len, data_len, err_len;
efx_dword_t *outbuf; efx_dword_t *outbuf;
MCDI_DECLARE_BUF_OUT_OR_ERR(errbuf, 0); MCDI_DECLARE_BUF_ERR(errbuf);
int rc; int rc;
if (cmpxchg(&mcdi->state, if (cmpxchg(&mcdi->state,
...@@ -534,7 +534,7 @@ static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, ...@@ -534,7 +534,7 @@ static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
size_t *outlen_actual, bool quiet) size_t *outlen_actual, bool quiet)
{ {
struct efx_mcdi_iface *mcdi = efx_mcdi(efx); struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
MCDI_DECLARE_BUF_OUT_OR_ERR(errbuf, 0); MCDI_DECLARE_BUF_ERR(errbuf);
int rc; int rc;
if (mcdi->mode == MCDI_MODE_POLL) if (mcdi->mode == MCDI_MODE_POLL)
...@@ -1389,7 +1389,7 @@ int efx_mcdi_nvram_test_all(struct efx_nic *efx) ...@@ -1389,7 +1389,7 @@ int efx_mcdi_nvram_test_all(struct efx_nic *efx)
static int efx_mcdi_read_assertion(struct efx_nic *efx) static int efx_mcdi_read_assertion(struct efx_nic *efx)
{ {
MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_ASSERTS_IN_LEN); MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_ASSERTS_IN_LEN);
MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN);
unsigned int flags, index; unsigned int flags, index;
const char *reason; const char *reason;
size_t outlen; size_t outlen;
...@@ -1558,7 +1558,9 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method) ...@@ -1558,7 +1558,9 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
if (rc) if (rc)
return rc; return rc;
if (method == RESET_TYPE_WORLD) if (method == RESET_TYPE_DATAPATH)
return 0;
else if (method == RESET_TYPE_WORLD)
return efx_mcdi_reset_mc(efx); return efx_mcdi_reset_mc(efx);
else else
return efx_mcdi_reset_func(efx); return efx_mcdi_reset_func(efx);
...@@ -1699,7 +1701,7 @@ int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled) ...@@ -1699,7 +1701,7 @@ int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled)
int efx_mcdi_get_workarounds(struct efx_nic *efx, unsigned int *impl_out, int efx_mcdi_get_workarounds(struct efx_nic *efx, unsigned int *impl_out,
unsigned int *enabled_out) unsigned int *enabled_out)
{ {
MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, MC_CMD_GET_WORKAROUNDS_OUT_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_WORKAROUNDS_OUT_LEN);
size_t outlen; size_t outlen;
int rc; int rc;
......
...@@ -176,10 +176,12 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); ...@@ -176,10 +176,12 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
* 32-bit-aligned. Also, on Siena we must copy to the MC shared * 32-bit-aligned. Also, on Siena we must copy to the MC shared
* memory strictly 32 bits at a time, so add any necessary padding. * memory strictly 32 bits at a time, so add any necessary padding.
*/ */
#define MCDI_DECLARE_BUF(_name, _len) \ #define _MCDI_DECLARE_BUF(_name, _len) \
efx_dword_t _name[DIV_ROUND_UP(_len, 4)] efx_dword_t _name[DIV_ROUND_UP(_len, 4)]
#define MCDI_DECLARE_BUF_OUT_OR_ERR(_name, _len) \ #define MCDI_DECLARE_BUF(_name, _len) \
MCDI_DECLARE_BUF(_name, max_t(size_t, _len, 8)) _MCDI_DECLARE_BUF(_name, _len) = {{{0}}}
#define MCDI_DECLARE_BUF_ERR(_name) \
MCDI_DECLARE_BUF(_name, 8)
#define _MCDI_PTR(_buf, _offset) \ #define _MCDI_PTR(_buf, _offset) \
((u8 *)(_buf) + (_offset)) ((u8 *)(_buf) + (_offset))
#define MCDI_PTR(_buf, _field) \ #define MCDI_PTR(_buf, _field) \
......
This diff is collapsed.
...@@ -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);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
...@@ -896,7 +897,8 @@ struct vfdi_status; ...@@ -896,7 +897,8 @@ struct vfdi_status;
* @loopback_mode: Loopback status * @loopback_mode: Loopback status
* @loopback_modes: Supported loopback mode bitmask * @loopback_modes: Supported loopback mode bitmask
* @loopback_selftest: Offline self-test private state * @loopback_selftest: Offline self-test private state
* @filter_lock: Filter table lock * @filter_sem: Filter table rw_semaphore, for freeing the table
* @filter_lock: Filter table lock, for mere content changes
* @filter_state: Architecture-dependent filter table state * @filter_state: Architecture-dependent filter table state
* @rps_flow_id: Flow IDs of filters allocated for accelerated RFS, * @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
* indexed by filter ID * indexed by filter ID
...@@ -1038,6 +1040,7 @@ struct efx_nic { ...@@ -1038,6 +1040,7 @@ struct efx_nic {
void *loopback_selftest; void *loopback_selftest;
struct rw_semaphore filter_sem;
spinlock_t filter_lock; spinlock_t filter_lock;
void *filter_state; void *filter_state;
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
...@@ -1202,6 +1205,7 @@ struct efx_mtd_partition { ...@@ -1202,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
...@@ -1334,7 +1338,6 @@ struct efx_nic_type { ...@@ -1334,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);
void (*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);
...@@ -1345,9 +1348,13 @@ struct efx_nic_type { ...@@ -1345,9 +1348,13 @@ struct efx_nic_type {
bool spoofchk); bool spoofchk);
int (*sriov_get_vf_config)(struct efx_nic *efx, int vf_i, int (*sriov_get_vf_config)(struct efx_nic *efx, int vf_i,
struct ifla_vf_info *ivi); struct ifla_vf_info *ivi);
int (*sriov_set_vf_link_state)(struct efx_nic *efx, int vf_i,
int link_state);
int (*vswitching_probe)(struct efx_nic *efx); int (*vswitching_probe)(struct efx_nic *efx);
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 (*set_mac_address)(struct efx_nic *efx);
int revision; int revision;
unsigned int txd_ptr_tbl_base; unsigned int txd_ptr_tbl_base;
......
...@@ -525,6 +525,7 @@ struct efx_ef10_nic_data { ...@@ -525,6 +525,7 @@ struct efx_ef10_nic_data {
bool must_probe_vswitching; bool must_probe_vswitching;
unsigned int pf_index; unsigned int pf_index;
#ifdef CONFIG_SFC_SRIOV #ifdef CONFIG_SFC_SRIOV
unsigned int vf_index;
struct ef10_vf *vf; struct ef10_vf *vf;
#endif #endif
u8 vport_mac[ETH_ALEN]; u8 vport_mac[ETH_ALEN];
......
...@@ -306,7 +306,7 @@ struct efx_ptp_data { ...@@ -306,7 +306,7 @@ struct efx_ptp_data {
struct work_struct pps_work; struct work_struct pps_work;
struct workqueue_struct *pps_workwq; struct workqueue_struct *pps_workwq;
bool nic_ts_enabled; bool nic_ts_enabled;
MCDI_DECLARE_BUF(txbuf, MC_CMD_PTP_IN_TRANSMIT_LENMAX); _MCDI_DECLARE_BUF(txbuf, MC_CMD_PTP_IN_TRANSMIT_LENMAX);
unsigned int good_syncs; unsigned int good_syncs;
unsigned int fast_syncs; unsigned int fast_syncs;
...@@ -573,7 +573,7 @@ static int efx_ptp_get_timestamp_corrections(struct efx_nic *efx) ...@@ -573,7 +573,7 @@ static int efx_ptp_get_timestamp_corrections(struct efx_nic *efx)
static int efx_ptp_enable(struct efx_nic *efx) static int efx_ptp_enable(struct efx_nic *efx)
{ {
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ENABLE_LEN); MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ENABLE_LEN);
MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, 0); MCDI_DECLARE_BUF_ERR(outbuf);
int rc; int rc;
MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ENABLE); MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ENABLE);
...@@ -601,7 +601,7 @@ static int efx_ptp_enable(struct efx_nic *efx) ...@@ -601,7 +601,7 @@ static int efx_ptp_enable(struct efx_nic *efx)
static int efx_ptp_disable(struct efx_nic *efx) static int efx_ptp_disable(struct efx_nic *efx)
{ {
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_DISABLE_LEN); MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_DISABLE_LEN);
MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, 0); MCDI_DECLARE_BUF_ERR(outbuf);
int rc; int rc;
MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_DISABLE); MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_DISABLE);
......
...@@ -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,
......
...@@ -1476,16 +1476,18 @@ void efx_siena_sriov_flr(struct efx_nic *efx, unsigned vf_i) ...@@ -1476,16 +1476,18 @@ void efx_siena_sriov_flr(struct efx_nic *efx, unsigned vf_i)
vf->evq0_count = 0; vf->evq0_count = 0;
} }
void efx_siena_sriov_mac_address_changed(struct efx_nic *efx) int efx_siena_sriov_mac_address_changed(struct efx_nic *efx)
{ {
struct siena_nic_data *nic_data = efx->nic_data; struct siena_nic_data *nic_data = efx->nic_data;
struct vfdi_status *vfdi_status = nic_data->vfdi_status.addr; struct vfdi_status *vfdi_status = nic_data->vfdi_status.addr;
if (!efx->vf_init_count) if (!efx->vf_init_count)
return; return 0;
ether_addr_copy(vfdi_status->peers[0].mac_addr, ether_addr_copy(vfdi_status->peers[0].mac_addr,
efx->net_dev->dev_addr); efx->net_dev->dev_addr);
queue_work(vfdi_workqueue, &nic_data->peer_work); queue_work(vfdi_workqueue, &nic_data->peer_work);
return 0;
} }
void efx_siena_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event) void efx_siena_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
int efx_siena_sriov_configure(struct efx_nic *efx, int num_vfs); int efx_siena_sriov_configure(struct efx_nic *efx, int num_vfs);
int efx_siena_sriov_init(struct efx_nic *efx); int efx_siena_sriov_init(struct efx_nic *efx);
void efx_siena_sriov_fini(struct efx_nic *efx); void efx_siena_sriov_fini(struct efx_nic *efx);
void efx_siena_sriov_mac_address_changed(struct efx_nic *efx); int efx_siena_sriov_mac_address_changed(struct efx_nic *efx);
bool efx_siena_sriov_wanted(struct efx_nic *efx); bool efx_siena_sriov_wanted(struct efx_nic *efx);
void efx_siena_sriov_reset(struct efx_nic *efx); void efx_siena_sriov_reset(struct efx_nic *efx);
void efx_siena_sriov_flr(struct efx_nic *efx, unsigned flr); void efx_siena_sriov_flr(struct efx_nic *efx, unsigned flr);
......
...@@ -58,3 +58,15 @@ int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i, ...@@ -58,3 +58,15 @@ int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i,
else else
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
int efx_sriov_set_vf_link_state(struct net_device *net_dev, int vf_i,
int link_state)
{
struct efx_nic *efx = netdev_priv(net_dev);
if (efx->type->sriov_set_vf_link_state)
return efx->type->sriov_set_vf_link_state(efx, vf_i,
link_state);
else
return -EOPNOTSUPP;
}
...@@ -21,6 +21,8 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf_i, ...@@ -21,6 +21,8 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf_i,
bool spoofchk); bool spoofchk);
int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i, int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i,
struct ifla_vf_info *ivi); struct ifla_vf_info *ivi);
int efx_sriov_set_vf_link_state(struct net_device *net_dev, int vf_i,
int link_state);
#endif /* CONFIG_SFC_SRIOV */ #endif /* CONFIG_SFC_SRIOV */
......
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