From cd2d5b529cdb9bd274f3e4bc68d37d4d63b7f383 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 14 Feb 2012 00:48:07 +0000 Subject: sfc: Add SR-IOV back-end support for SFC9000 family On the SFC9000 family, each port has 1024 Virtual Interfaces (VIs), each with an RX queue, a TX queue, an event queue and a mailbox register. These may be assigned to up to 127 SR-IOV virtual functions per port, with up to 64 VIs per VF. We allocate an extra channel (IRQ and event queue only) to receive requests from VF drivers. There is a per-port limit of 4 concurrent RX queue flushes, and queue flushes may be initiated by the MC in response to a Function Level Reset (FLR) of a VF. Therefore, when SR-IOV is in use, we submit all flush requests via the MC. The RSS indirection table is shared with VFs, so the number of RX queues used in the PF is limited to the number of VIs per VF. This is almost entirely the work of Steve Hodgson, formerly shodgson@solarflare.com. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/net/ethernet/sfc/mcdi.c') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 619f63a66ce7..17b6463e459c 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -560,6 +560,9 @@ void efx_mcdi_process_event(struct efx_channel *channel, case MCDI_EVENT_CODE_MAC_STATS_DMA: /* MAC stats are gather lazily. We can ignore this. */ break; + case MCDI_EVENT_CODE_FLR: + efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF)); + break; default: netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n", @@ -1154,6 +1157,37 @@ fail: return rc; } +int efx_mcdi_flush_rxqs(struct efx_nic *efx) +{ + struct efx_channel *channel; + struct efx_rx_queue *rx_queue; + __le32 *qid; + int rc, count; + + qid = kmalloc(EFX_MAX_CHANNELS * sizeof(*qid), GFP_KERNEL); + if (qid == NULL) + return -ENOMEM; + + count = 0; + efx_for_each_channel(channel, efx) { + efx_for_each_channel_rx_queue(rx_queue, channel) { + if (rx_queue->flush_pending) { + rx_queue->flush_pending = false; + atomic_dec(&efx->rxq_flush_pending); + qid[count++] = cpu_to_le32( + efx_rx_queue_index(rx_queue)); + } + } + } + + rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, (u8 *)qid, + count * sizeof(*qid), NULL, 0, NULL); + WARN_ON(rc > 0); + + kfree(qid); + + return rc; +} int efx_mcdi_wol_filter_reset(struct efx_nic *efx) { -- cgit v1.2.3-55-g7522