Commit ff5756d0 authored by David S. Miller's avatar David S. Miller

Merge branch 'sfc-vf'

Bert Kenward says:

====================
sfc: additional virtual function support​

This introduces the client side of a mechanism to defer authorisation of
operations, for example multicast subscription. Although primarily aimed at
SRIOV VFs this can also apply to unprivileged PFs.

Also handle reboot ordering corner cases better and reduce the level of some
logging.

v2: remove #ifdef DEBUG around new WARN_ON in mcdi.c.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2e4c8baa 09a04204
...@@ -486,10 +486,17 @@ static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n) ...@@ -486,10 +486,17 @@ static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
BUILD_BUG_ON(MC_CMD_ALLOC_PIOBUF_IN_LEN != 0); BUILD_BUG_ON(MC_CMD_ALLOC_PIOBUF_IN_LEN != 0);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
rc = efx_mcdi_rpc(efx, MC_CMD_ALLOC_PIOBUF, NULL, 0, rc = efx_mcdi_rpc_quiet(efx, MC_CMD_ALLOC_PIOBUF, NULL, 0,
outbuf, sizeof(outbuf), &outlen); outbuf, sizeof(outbuf), &outlen);
if (rc) if (rc) {
/* Don't display the MC error if we didn't have space
* for a VF.
*/
if (!(efx_ef10_is_vf(efx) && rc == -ENOSPC))
efx_mcdi_display_error(efx, MC_CMD_ALLOC_PIOBUF,
0, outbuf, outlen, rc);
break; break;
}
if (outlen < MC_CMD_ALLOC_PIOBUF_OUT_LEN) { if (outlen < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
rc = -EIO; rc = -EIO;
break; break;
...@@ -3833,13 +3840,12 @@ static void efx_ef10_filter_table_remove(struct efx_nic *efx) ...@@ -3833,13 +3840,12 @@ static void efx_ef10_filter_table_remove(struct efx_nic *efx)
MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE); MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE);
MCDI_SET_QWORD(inbuf, FILTER_OP_IN_HANDLE, MCDI_SET_QWORD(inbuf, FILTER_OP_IN_HANDLE,
table->entry[filter_idx].handle); table->entry[filter_idx].handle);
rc = efx_mcdi_rpc(efx, MC_CMD_FILTER_OP, inbuf, sizeof(inbuf), rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FILTER_OP, inbuf,
NULL, 0, NULL); sizeof(inbuf), NULL, 0, NULL);
if (rc) if (rc)
netdev_WARN(efx->net_dev, netif_info(efx, drv, efx->net_dev,
"filter_idx=%#x handle=%#llx\n", "%s: filter %04x remove failed\n",
filter_idx, __func__, filter_idx);
table->entry[filter_idx].handle);
kfree(spec); kfree(spec);
} }
...@@ -3848,11 +3854,14 @@ static void efx_ef10_filter_table_remove(struct efx_nic *efx) ...@@ -3848,11 +3854,14 @@ static void efx_ef10_filter_table_remove(struct efx_nic *efx)
} }
#define EFX_EF10_FILTER_DO_MARK_OLD(id) \ #define EFX_EF10_FILTER_DO_MARK_OLD(id) \
if (id != EFX_EF10_FILTER_ID_INVALID) { \ if (id != EFX_EF10_FILTER_ID_INVALID) { \
filter_idx = efx_ef10_filter_get_unsafe_id(efx, id); \ filter_idx = efx_ef10_filter_get_unsafe_id(efx, id); \
WARN_ON(!table->entry[filter_idx].spec); \ if (!table->entry[filter_idx].spec) \
table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_AUTO_OLD; \ netif_dbg(efx, drv, efx->net_dev, \
} "%s: marked null spec old %04x:%04x\n", \
__func__, id, filter_idx); \
table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_AUTO_OLD;\
}
static void efx_ef10_filter_mark_old(struct efx_nic *efx) static void efx_ef10_filter_mark_old(struct efx_nic *efx)
{ {
struct efx_ef10_filter_table *table = efx->filter_state; struct efx_ef10_filter_table *table = efx->filter_state;
...@@ -4026,9 +4035,10 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx, bool multicast, ...@@ -4026,9 +4035,10 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx, bool multicast,
rc = efx_ef10_filter_insert(efx, &spec, true); rc = efx_ef10_filter_insert(efx, &spec, true);
if (rc < 0) { if (rc < 0) {
netif_warn(efx, drv, efx->net_dev, netif_printk(efx, drv, rc == -EPERM ? KERN_DEBUG : KERN_WARNING,
"%scast mismatch filter insert failed rc=%d\n", efx->net_dev,
multicast ? "Multi" : "Uni", rc); "%scast mismatch filter insert failed rc=%d\n",
multicast ? "Multi" : "Uni", rc);
} else if (multicast) { } else if (multicast) {
table->mcdef_id = efx_ef10_filter_get_unsafe_id(efx, rc); table->mcdef_id = efx_ef10_filter_get_unsafe_id(efx, rc);
if (!nic_data->workaround_26807) { if (!nic_data->workaround_26807) {
...@@ -4070,19 +4080,31 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx, bool multicast, ...@@ -4070,19 +4080,31 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx, bool multicast,
static void efx_ef10_filter_remove_old(struct efx_nic *efx) static void efx_ef10_filter_remove_old(struct efx_nic *efx)
{ {
struct efx_ef10_filter_table *table = efx->filter_state; struct efx_ef10_filter_table *table = efx->filter_state;
bool remove_failed = false; int remove_failed = 0;
int remove_noent = 0;
int rc;
int i; int i;
for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) { for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) {
if (ACCESS_ONCE(table->entry[i].spec) & if (ACCESS_ONCE(table->entry[i].spec) &
EFX_EF10_FILTER_FLAG_AUTO_OLD) { EFX_EF10_FILTER_FLAG_AUTO_OLD) {
if (efx_ef10_filter_remove_internal( rc = efx_ef10_filter_remove_internal(efx,
efx, 1U << EFX_FILTER_PRI_AUTO, 1U << EFX_FILTER_PRI_AUTO, i, true);
i, true) < 0) if (rc == -ENOENT)
remove_failed = true; remove_noent++;
else if (rc)
remove_failed++;
} }
} }
WARN_ON(remove_failed);
if (remove_failed)
netif_info(efx, drv, efx->net_dev,
"%s: failed to remove %d filters\n",
__func__, remove_failed);
if (remove_noent)
netif_info(efx, drv, efx->net_dev,
"%s: failed to remove %d non-existent filters\n",
__func__, remove_noent);
} }
static int efx_ef10_vport_set_mac_address(struct efx_nic *efx) static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
......
...@@ -3174,14 +3174,15 @@ static int efx_pci_probe(struct pci_dev *pci_dev, ...@@ -3174,14 +3174,15 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
rtnl_lock(); rtnl_lock();
rc = efx_mtd_probe(efx); rc = efx_mtd_probe(efx);
rtnl_unlock(); rtnl_unlock();
if (rc) if (rc && rc != -EPERM)
netif_warn(efx, probe, efx->net_dev, netif_warn(efx, probe, efx->net_dev,
"failed to create MTDs (%d)\n", rc); "failed to create MTDs (%d)\n", rc);
rc = pci_enable_pcie_error_reporting(pci_dev); rc = pci_enable_pcie_error_reporting(pci_dev);
if (rc && rc != -EINVAL) if (rc && rc != -EINVAL)
netif_warn(efx, probe, efx->net_dev, netif_notice(efx, probe, efx->net_dev,
"pci_enable_pcie_error_reporting failed (%d)\n", rc); "PCIE error reporting unavailable (%d).\n",
rc);
return 0; return 0;
......
This diff is collapsed.
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* @MCDI_STATE_RUNNING_SYNC: There is a synchronous MCDI request pending. * @MCDI_STATE_RUNNING_SYNC: There is a synchronous MCDI request pending.
* Only the thread that moved into this state is allowed to move out of it. * Only the thread that moved into this state is allowed to move out of it.
* @MCDI_STATE_RUNNING_ASYNC: There is an asynchronous MCDI request pending. * @MCDI_STATE_RUNNING_ASYNC: There is an asynchronous MCDI request pending.
* @MCDI_STATE_PROXY_WAIT: An MCDI request has completed with a response that
* indicates we must wait for a proxy try again message.
* @MCDI_STATE_COMPLETED: An MCDI request has completed, but the owning thread * @MCDI_STATE_COMPLETED: An MCDI request has completed, but the owning thread
* has not yet consumed the result. For all other threads, equivalent to * has not yet consumed the result. For all other threads, equivalent to
* %MCDI_STATE_RUNNING. * %MCDI_STATE_RUNNING.
...@@ -25,6 +27,7 @@ enum efx_mcdi_state { ...@@ -25,6 +27,7 @@ enum efx_mcdi_state {
MCDI_STATE_QUIESCENT, MCDI_STATE_QUIESCENT,
MCDI_STATE_RUNNING_SYNC, MCDI_STATE_RUNNING_SYNC,
MCDI_STATE_RUNNING_ASYNC, MCDI_STATE_RUNNING_ASYNC,
MCDI_STATE_PROXY_WAIT,
MCDI_STATE_COMPLETED, MCDI_STATE_COMPLETED,
}; };
...@@ -60,6 +63,9 @@ enum efx_mcdi_mode { ...@@ -60,6 +63,9 @@ enum efx_mcdi_mode {
* @async_timer: Timer for asynchronous request timeout * @async_timer: Timer for asynchronous request timeout
* @logging_buffer: buffer that may be used to build MCDI tracing messages * @logging_buffer: buffer that may be used to build MCDI tracing messages
* @logging_enabled: whether to trace MCDI * @logging_enabled: whether to trace MCDI
* @proxy_rx_handle: Most recently received proxy authorisation handle
* @proxy_rx_status: Status of most recent proxy authorisation
* @proxy_rx_wq: Wait queue for updates to proxy_rx_handle
*/ */
struct efx_mcdi_iface { struct efx_mcdi_iface {
struct efx_nic *efx; struct efx_nic *efx;
...@@ -71,6 +77,7 @@ struct efx_mcdi_iface { ...@@ -71,6 +77,7 @@ struct efx_mcdi_iface {
unsigned int credits; unsigned int credits;
unsigned int seqno; unsigned int seqno;
int resprc; int resprc;
int resprc_raw;
size_t resp_hdr_len; size_t resp_hdr_len;
size_t resp_data_len; size_t resp_data_len;
spinlock_t async_lock; spinlock_t async_lock;
...@@ -80,6 +87,9 @@ struct efx_mcdi_iface { ...@@ -80,6 +87,9 @@ struct efx_mcdi_iface {
char *logging_buffer; char *logging_buffer;
bool logging_enabled; bool logging_enabled;
#endif #endif
unsigned int proxy_rx_handle;
int proxy_rx_status;
wait_queue_head_t proxy_rx_wq;
}; };
struct efx_mcdi_mon { struct efx_mcdi_mon {
......
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