diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2012-02-14 00:48:07 +0000 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2012-02-16 00:25:13 +0000 |
commit | cd2d5b529cdb9bd274f3e4bc68d37d4d63b7f383 (patch) | |
tree | f21a5f98185b8e227b843a28b54d4260a0e57033 /drivers/net/ethernet/sfc/nic.h | |
parent | 28e47c498a931200125e299e9d60d22e27b4ab0d (diff) | |
download | blackbird-op-linux-cd2d5b529cdb9bd274f3e4bc68d37d4d63b7f383.tar.gz blackbird-op-linux-cd2d5b529cdb9bd274f3e4bc68d37d4d63b7f383.zip |
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 <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc/nic.h')
-rw-r--r-- | drivers/net/ethernet/sfc/nic.h | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 5df7da8b8ebf..246c4140453c 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -169,6 +169,95 @@ static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx) } #endif +/* + * On the SFC9000 family each port is associated with 1 PCI physical + * function (PF) handled by sfc and a configurable number of virtual + * functions (VFs) that may be handled by some other driver, often in + * a VM guest. The queue pointer registers are mapped in both PF and + * VF BARs such that an 8K region provides access to a single RX, TX + * and event queue (collectively a Virtual Interface, VI or VNIC). + * + * The PF has access to all 1024 VIs while VFs are mapped to VIs + * according to VI_BASE and VI_SCALE: VF i has access to VIs numbered + * in range [VI_BASE + i << VI_SCALE, VI_BASE + i + 1 << VI_SCALE). + * The number of VIs and the VI_SCALE value are configurable but must + * be established at boot time by firmware. + */ + +/* Maximum VI_SCALE parameter supported by Siena */ +#define EFX_VI_SCALE_MAX 6 +/* Base VI to use for SR-IOV. Must be aligned to (1 << EFX_VI_SCALE_MAX), + * so this is the smallest allowed value. */ +#define EFX_VI_BASE 128U +/* Maximum number of VFs allowed */ +#define EFX_VF_COUNT_MAX 127 +/* Limit EVQs on VFs to be only 8k to reduce buffer table reservation */ +#define EFX_MAX_VF_EVQ_SIZE 8192UL +/* The number of buffer table entries reserved for each VI on a VF */ +#define EFX_VF_BUFTBL_PER_VI \ + ((EFX_MAX_VF_EVQ_SIZE + 2 * EFX_MAX_DMAQ_SIZE) * \ + sizeof(efx_qword_t) / EFX_BUF_SIZE) + +#ifdef CONFIG_SFC_SRIOV + +static inline bool efx_sriov_wanted(struct efx_nic *efx) +{ + return efx->vf_count != 0; +} +static inline bool efx_sriov_enabled(struct efx_nic *efx) +{ + return efx->vf_init_count != 0; +} +static inline unsigned int efx_vf_size(struct efx_nic *efx) +{ + return 1 << efx->vi_scale; +} + +extern int efx_init_sriov(void); +extern void efx_sriov_probe(struct efx_nic *efx); +extern int efx_sriov_init(struct efx_nic *efx); +extern void efx_sriov_mac_address_changed(struct efx_nic *efx); +extern void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event); +extern void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event); +extern void efx_sriov_event(struct efx_channel *channel, efx_qword_t *event); +extern void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq); +extern void efx_sriov_flr(struct efx_nic *efx, unsigned flr); +extern void efx_sriov_reset(struct efx_nic *efx); +extern void efx_sriov_fini(struct efx_nic *efx); +extern void efx_fini_sriov(void); + +#else + +static inline bool efx_sriov_wanted(struct efx_nic *efx) { return false; } +static inline bool efx_sriov_enabled(struct efx_nic *efx) { return false; } +static inline unsigned int efx_vf_size(struct efx_nic *efx) { return 0; } + +static inline int efx_init_sriov(void) { return 0; } +static inline void efx_sriov_probe(struct efx_nic *efx) {} +static inline int efx_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +static inline void efx_sriov_mac_address_changed(struct efx_nic *efx) {} +static inline void efx_sriov_tx_flush_done(struct efx_nic *efx, + efx_qword_t *event) {} +static inline void efx_sriov_rx_flush_done(struct efx_nic *efx, + efx_qword_t *event) {} +static inline void efx_sriov_event(struct efx_channel *channel, + efx_qword_t *event) {} +static inline void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq) {} +static inline void efx_sriov_flr(struct efx_nic *efx, unsigned flr) {} +static inline void efx_sriov_reset(struct efx_nic *efx) {} +static inline void efx_sriov_fini(struct efx_nic *efx) {} +static inline void efx_fini_sriov(void) {} + +#endif + +extern int efx_sriov_set_vf_mac(struct net_device *dev, int vf, u8 *mac); +extern int efx_sriov_set_vf_vlan(struct net_device *dev, int vf, + u16 vlan, u8 qos); +extern int efx_sriov_get_vf_config(struct net_device *dev, int vf, + struct ifla_vf_info *ivf); +extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, + bool spoofchk); + extern const struct efx_nic_type falcon_a1_nic_type; extern const struct efx_nic_type falcon_b0_nic_type; extern const struct efx_nic_type siena_a0_nic_type; |