diff options
author | David S. Miller <davem@davemloft.net> | 2014-11-06 14:43:13 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-06 14:43:13 -0500 |
commit | f81c6906dcfb5c16c50a7ae5ecff60294c443f65 (patch) | |
tree | 8759bd88647af178390ac8c16e03b9a6f794c762 | |
parent | 7e5d7753956b374516530e156c5e8aa19652398d (diff) | |
parent | d98a4ffe0d7a8946c67d115f8b3bd8e5bb1df86d (diff) |
Merge branch 'sfc-next'
Shradha Shah says:
====================
sfc: Clean up Siena SR-IOV support in preparation for EF10 SR-IOV support
This patch series provides a base and clean up for the upcoming
EF10 SRIOV patches.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/sfc/ef10.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/falcon.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/farch.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/nic.h | 112 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/siena.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/siena_sriov.c | 269 |
9 files changed, 281 insertions, 193 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 002d4cdc319f..ff55a1983014 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -3688,6 +3688,11 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .ptp_write_host_time = efx_ef10_ptp_write_host_time, .ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events, .ptp_set_ts_config = efx_ef10_ptp_set_ts_config, + .sriov_init = efx_ef10_sriov_init, + .sriov_fini = efx_ef10_sriov_fini, + .sriov_mac_address_changed = efx_ef10_sriov_mac_address_changed, + .sriov_wanted = efx_ef10_sriov_wanted, + .sriov_reset = efx_ef10_sriov_reset, .revision = EFX_REV_HUNT_A0, .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index b2cc590dd1dd..b49d04886d4f 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1314,7 +1314,7 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx) /* If RSS is requested for the PF *and* VFs then we can't write RSS * table entries that are inaccessible to VFs */ - if (efx_sriov_wanted(efx) && efx_vf_size(efx) > 1 && + if (efx->type->sriov_wanted(efx) && efx_vf_size(efx) > 1 && count > efx_vf_size(efx)) { netif_warn(efx, probe, efx->net_dev, "Reducing number of RSS channels from %u to %u for " @@ -1426,7 +1426,9 @@ static int efx_probe_interrupts(struct efx_nic *efx) } /* RSS might be usable on VFs even if it is disabled on the PF */ - efx->rss_spread = ((efx->n_rx_channels > 1 || !efx_sriov_wanted(efx)) ? + + efx->rss_spread = ((efx->n_rx_channels > 1 || + !efx->type->sriov_wanted(efx)) ? efx->n_rx_channels : efx_vf_size(efx)); return 0; @@ -2166,7 +2168,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) } ether_addr_copy(net_dev->dev_addr, new_addr); - efx_sriov_mac_address_changed(efx); + efx->type->sriov_mac_address_changed(efx); /* Reconfigure the MAC */ mutex_lock(&efx->mac_lock); @@ -2210,10 +2212,10 @@ static const struct net_device_ops efx_farch_netdev_ops = { .ndo_set_rx_mode = efx_set_rx_mode, .ndo_set_features = efx_set_features, #ifdef CONFIG_SFC_SRIOV - .ndo_set_vf_mac = efx_sriov_set_vf_mac, - .ndo_set_vf_vlan = efx_sriov_set_vf_vlan, - .ndo_set_vf_spoofchk = efx_sriov_set_vf_spoofchk, - .ndo_get_vf_config = efx_sriov_get_vf_config, + .ndo_set_vf_mac = efx_siena_sriov_set_vf_mac, + .ndo_set_vf_vlan = efx_siena_sriov_set_vf_vlan, + .ndo_set_vf_spoofchk = efx_siena_sriov_set_vf_spoofchk, + .ndo_get_vf_config = efx_siena_sriov_get_vf_config, #endif #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = efx_netpoll, @@ -2433,7 +2435,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) if (rc) goto fail; efx_restore_filters(efx); - efx_sriov_reset(efx); + efx->type->sriov_reset(efx); mutex_unlock(&efx->mac_lock); @@ -2826,7 +2828,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx_disable_interrupts(efx); rtnl_unlock(); - efx_sriov_fini(efx); + efx->type->sriov_fini(efx); efx_unregister_netdev(efx); efx_mtd_remove(efx); @@ -3023,7 +3025,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev, if (rc) goto fail4; - rc = efx_sriov_init(efx); + rc = efx->type->sriov_init(efx); if (rc) netif_err(efx, probe, efx->net_dev, "SR-IOV can't be enabled rc %d\n", rc); diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 157037546d30..f166c8ef38a3 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -2766,6 +2766,11 @@ const struct efx_nic_type falcon_a1_nic_type = { .mtd_write = falcon_mtd_write, .mtd_sync = falcon_mtd_sync, #endif + .sriov_init = efx_falcon_sriov_init, + .sriov_fini = efx_falcon_sriov_fini, + .sriov_mac_address_changed = efx_falcon_sriov_mac_address_changed, + .sriov_wanted = efx_falcon_sriov_wanted, + .sriov_reset = efx_falcon_sriov_reset, .revision = EFX_REV_FALCON_A1, .txd_ptr_tbl_base = FR_AA_TX_DESC_PTR_TBL_KER, @@ -2862,6 +2867,11 @@ const struct efx_nic_type falcon_b0_nic_type = { .mtd_write = falcon_mtd_write, .mtd_sync = falcon_mtd_sync, #endif + .sriov_init = efx_falcon_sriov_init, + .sriov_fini = efx_falcon_sriov_fini, + .sriov_mac_address_changed = efx_falcon_sriov_mac_address_changed, + .sriov_wanted = efx_falcon_sriov_wanted, + .sriov_reset = efx_falcon_sriov_reset, .revision = EFX_REV_FALCON_B0, .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 6859437b59fb..75975328e020 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -226,6 +226,9 @@ static int efx_alloc_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer, unsigned int len) { +#ifdef CONFIG_SFC_SRIOV + struct siena_nic_data *nic_data = efx->nic_data; +#endif len = ALIGN(len, EFX_BUF_SIZE); if (efx_nic_alloc_buffer(efx, &buffer->buf, len, GFP_KERNEL)) @@ -237,8 +240,8 @@ static int efx_alloc_special_buffer(struct efx_nic *efx, buffer->index = efx->next_buffer_table; efx->next_buffer_table += buffer->entries; #ifdef CONFIG_SFC_SRIOV - BUG_ON(efx_sriov_enabled(efx) && - efx->vf_buftbl_base < efx->next_buffer_table); + BUG_ON(efx_siena_sriov_enabled(efx) && + nic_data->vf_buftbl_base < efx->next_buffer_table); #endif netif_dbg(efx, probe, efx->net_dev, @@ -667,7 +670,7 @@ static int efx_farch_do_flush(struct efx_nic *efx) * the firmware (though we will still have to poll for * completion). If that fails, fall back to the old scheme. */ - if (efx_sriov_enabled(efx)) { + if (efx_siena_sriov_enabled(efx)) { rc = efx_mcdi_flush_rxqs(efx); if (!rc) goto wait; @@ -1195,13 +1198,13 @@ efx_farch_handle_driver_event(struct efx_channel *channel, efx_qword_t *event) netif_vdbg(efx, hw, efx->net_dev, "channel %d TXQ %d flushed\n", channel->channel, ev_sub_data); efx_farch_handle_tx_flush_done(efx, event); - efx_sriov_tx_flush_done(efx, event); + efx_siena_sriov_tx_flush_done(efx, event); break; case FSE_AZ_RX_DESCQ_FLS_DONE_EV: netif_vdbg(efx, hw, efx->net_dev, "channel %d RXQ %d flushed\n", channel->channel, ev_sub_data); efx_farch_handle_rx_flush_done(efx, event); - efx_sriov_rx_flush_done(efx, event); + efx_siena_sriov_rx_flush_done(efx, event); break; case FSE_AZ_EVQ_INIT_DONE_EV: netif_dbg(efx, hw, efx->net_dev, @@ -1240,7 +1243,7 @@ efx_farch_handle_driver_event(struct efx_channel *channel, efx_qword_t *event) ev_sub_data); efx_schedule_reset(efx, RESET_TYPE_DMA_ERROR); } else - efx_sriov_desc_fetch_err(efx, ev_sub_data); + efx_siena_sriov_desc_fetch_err(efx, ev_sub_data); break; case FSE_BZ_TX_DSC_ERROR_EV: if (ev_sub_data < EFX_VI_BASE) { @@ -1250,7 +1253,7 @@ efx_farch_handle_driver_event(struct efx_channel *channel, efx_qword_t *event) ev_sub_data); efx_schedule_reset(efx, RESET_TYPE_DMA_ERROR); } else - efx_sriov_desc_fetch_err(efx, ev_sub_data); + efx_siena_sriov_desc_fetch_err(efx, ev_sub_data); break; default: netif_vdbg(efx, hw, efx->net_dev, @@ -1315,7 +1318,7 @@ int efx_farch_ev_process(struct efx_channel *channel, int budget) efx_farch_handle_driver_event(channel, &event); break; case FSE_CZ_EV_CODE_USER_EV: - efx_sriov_event(channel, &event); + efx_siena_sriov_event(channel, &event); break; case FSE_CZ_EV_CODE_MCDI_EV: efx_mcdi_process_event(channel, &event); @@ -1668,6 +1671,10 @@ void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw) { unsigned vi_count, buftbl_min; +#ifdef CONFIG_SFC_SRIOV + struct siena_nic_data *nic_data = efx->nic_data; +#endif + /* Account for the buffer table entries backing the datapath channels * and the descriptor caches for those channels. */ @@ -1678,10 +1685,10 @@ void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw) vi_count = max(efx->n_channels, efx->n_tx_channels * EFX_TXQ_TYPES); #ifdef CONFIG_SFC_SRIOV - if (efx_sriov_wanted(efx)) { + if (efx->type->sriov_wanted(efx)) { unsigned vi_dc_entries, buftbl_free, entries_per_vf, vf_limit; - efx->vf_buftbl_base = buftbl_min; + nic_data->vf_buftbl_base = buftbl_min; vi_dc_entries = RX_DC_ENTRIES + TX_DC_ENTRIES; vi_count = max(vi_count, EFX_VI_BASE); diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 5239cf9bdc56..d37928f01949 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1035,7 +1035,7 @@ void efx_mcdi_process_event(struct efx_channel *channel, /* 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)); + efx_siena_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF)); break; case MCDI_EVENT_CODE_PTP_RX: case MCDI_EVENT_CODE_PTP_FAULT: diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 9ede32064685..325dd94bca46 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -913,13 +913,6 @@ struct vfdi_status; * @vf_count: Number of VFs intended to be enabled. * @vf_init_count: Number of VFs that have been fully initialised. * @vi_scale: log2 number of vnics per VF. - * @vf_buftbl_base: The zeroth buffer table index used to back VF queues. - * @vfdi_status: Common VFDI status page to be dmad to VF address space. - * @local_addr_list: List of local addresses. Protected by %local_lock. - * @local_page_list: List of DMA addressable pages used to broadcast - * %local_addr_list. Protected by %local_lock. - * @local_lock: Mutex protecting %local_addr_list and %local_page_list. - * @peer_work: Work item to broadcast peer addresses to VMs. * @ptp_data: PTP state data * @vpd_sn: Serial number read from VPD * @monitor_work: Hardware monitor workitem @@ -1060,17 +1053,10 @@ struct efx_nic { wait_queue_head_t flush_wq; #ifdef CONFIG_SFC_SRIOV - struct efx_channel *vfdi_channel; struct efx_vf *vf; unsigned vf_count; unsigned vf_init_count; unsigned vi_scale; - unsigned vf_buftbl_base; - struct efx_buffer vfdi_status; - struct list_head local_addr_list; - struct list_head local_page_list; - struct mutex local_lock; - struct work_struct peer_work; #endif struct efx_ptp_data *ptp_data; @@ -1344,6 +1330,11 @@ struct efx_nic_type { int (*ptp_set_ts_sync_events)(struct efx_nic *efx, bool en, bool temp); int (*ptp_set_ts_config)(struct efx_nic *efx, struct hwtstamp_config *init); + int (*sriov_init)(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); + void (*sriov_reset)(struct efx_nic *efx); int revision; unsigned int txd_ptr_tbl_base; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index f77cce034ad4..93d10cbbd1cf 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -378,12 +378,30 @@ enum { /** * struct siena_nic_data - Siena NIC state + * @efx: Pointer back to main interface structure * @wol_filter_id: Wake-on-LAN packet filter id * @stats: Hardware statistics + * @vf_buftbl_base: The zeroth buffer table index used to back VF queues. + * @vfdi_status: Common VFDI status page to be dmad to VF address space. + * @local_addr_list: List of local addresses. Protected by %local_lock. + * @local_page_list: List of DMA addressable pages used to broadcast + * %local_addr_list. Protected by %local_lock. + * @local_lock: Mutex protecting %local_addr_list and %local_page_list. + * @peer_work: Work item to broadcast peer addresses to VMs. */ struct siena_nic_data { + struct efx_nic *efx; int wol_filter_id; u64 stats[SIENA_STAT_COUNT]; +#ifdef CONFIG_SFC_SRIOV + struct efx_channel *vfdi_channel; + unsigned vf_buftbl_base; + struct efx_buffer vfdi_status; + struct list_head local_addr_list; + struct list_head local_page_list; + struct mutex local_lock; + struct work_struct peer_work; +#endif }; enum { @@ -522,62 +540,88 @@ struct efx_ef10_nic_data { #ifdef CONFIG_SFC_SRIOV -static inline bool efx_sriov_wanted(struct efx_nic *efx) +/* SIENA */ +static inline bool efx_siena_sriov_wanted(struct efx_nic *efx) { return efx->vf_count != 0; } -static inline bool efx_sriov_enabled(struct efx_nic *efx) + +static inline bool efx_siena_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; } int efx_init_sriov(void); -void efx_sriov_probe(struct efx_nic *efx); -int efx_sriov_init(struct efx_nic *efx); -void efx_sriov_mac_address_changed(struct efx_nic *efx); -void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event); -void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event); -void efx_sriov_event(struct efx_channel *channel, efx_qword_t *event); -void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq); -void efx_sriov_flr(struct efx_nic *efx, unsigned flr); -void efx_sriov_reset(struct efx_nic *efx); -void efx_sriov_fini(struct efx_nic *efx); +void efx_siena_sriov_probe(struct efx_nic *efx); +int efx_siena_sriov_init(struct efx_nic *efx); +void efx_siena_sriov_mac_address_changed(struct efx_nic *efx); +void efx_siena_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event); +void efx_siena_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event); +void efx_siena_sriov_event(struct efx_channel *channel, efx_qword_t *event); +void efx_siena_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq); +void efx_siena_sriov_flr(struct efx_nic *efx, unsigned flr); +void efx_siena_sriov_reset(struct efx_nic *efx); +void efx_siena_sriov_fini(struct efx_nic *efx); void efx_fini_sriov(void); +/* EF10 */ +static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) { return false; } +static inline int efx_ef10_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +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_fini(struct efx_nic *efx) {} + #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; } +/* SIENA */ +static inline bool efx_siena_sriov_wanted(struct efx_nic *efx) { return false; } +static inline bool efx_siena_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_siena_sriov_probe(struct efx_nic *efx) {} +static inline int efx_siena_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +static inline void efx_siena_sriov_mac_address_changed(struct efx_nic *efx) {} +static inline void efx_siena_sriov_tx_flush_done(struct efx_nic *efx, + efx_qword_t *event) {} +static inline void efx_siena_sriov_rx_flush_done(struct efx_nic *efx, + efx_qword_t *event) {} +static inline void efx_siena_sriov_event(struct efx_channel *channel, + efx_qword_t *event) {} +static inline void efx_siena_sriov_desc_fetch_err(struct efx_nic *efx, + unsigned dmaq) {} +static inline void efx_siena_sriov_flr(struct efx_nic *efx, unsigned flr) {} +static inline void efx_siena_sriov_reset(struct efx_nic *efx) {} +static inline void efx_siena_sriov_fini(struct efx_nic *efx) {} static inline void efx_fini_sriov(void) {} +/* EF10 */ +static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) { return false; } +static inline int efx_ef10_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +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_fini(struct efx_nic *efx) {} + #endif -int efx_sriov_set_vf_mac(struct net_device *dev, int vf, u8 *mac); -int efx_sriov_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos); -int efx_sriov_get_vf_config(struct net_device *dev, int vf, - struct ifla_vf_info *ivf); -int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, - bool spoofchk); +/* FALCON */ +static inline bool efx_falcon_sriov_wanted(struct efx_nic *efx) { return false; } +static inline int efx_falcon_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +static inline void efx_falcon_sriov_mac_address_changed(struct efx_nic *efx) {} +static inline void efx_falcon_sriov_reset(struct efx_nic *efx) {} +static inline void efx_falcon_sriov_fini(struct efx_nic *efx) {} + +int efx_siena_sriov_set_vf_mac(struct net_device *dev, int vf, u8 *mac); +int efx_siena_sriov_set_vf_vlan(struct net_device *dev, int vf, + u16 vlan, u8 qos); +int efx_siena_sriov_get_vf_config(struct net_device *dev, int vf, + struct ifla_vf_info *ivf); +int efx_siena_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, + bool spoofchk); struct ethtool_ts_info; int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index ae696855f21a..3583f0208a6e 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -251,6 +251,7 @@ static int siena_probe_nic(struct efx_nic *efx) nic_data = kzalloc(sizeof(struct siena_nic_data), GFP_KERNEL); if (!nic_data) return -ENOMEM; + nic_data->efx = efx; efx->nic_data = nic_data; if (efx_farch_fpga_ver(efx) != 0) { @@ -306,7 +307,7 @@ static int siena_probe_nic(struct efx_nic *efx) if (rc) goto fail5; - efx_sriov_probe(efx); + efx_siena_sriov_probe(efx); efx_ptp_defer_probe_with_channel(efx); return 0; @@ -996,6 +997,11 @@ const struct efx_nic_type siena_a0_nic_type = { #endif .ptp_write_host_time = siena_ptp_write_host_time, .ptp_set_ts_config = siena_ptp_set_ts_config, + .sriov_init = efx_siena_sriov_init, + .sriov_fini = efx_siena_sriov_fini, + .sriov_mac_address_changed = efx_siena_sriov_mac_address_changed, + .sriov_wanted = efx_siena_sriov_wanted, + .sriov_reset = efx_siena_sriov_reset, .revision = EFX_REV_SIENA_A0, .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c index 43d2e64546ed..a8bbbad68a88 100644 --- a/drivers/net/ethernet/sfc/siena_sriov.c +++ b/drivers/net/ethernet/sfc/siena_sriov.c @@ -66,7 +66,7 @@ enum efx_vf_tx_filter_mode { * @status_lock: Mutex protecting @msg_seqno, @status_addr, @addr, * @peer_page_addrs and @peer_page_count from simultaneous * updates by the VM and consumption by - * efx_sriov_update_vf_addr() + * efx_siena_sriov_update_vf_addr() * @peer_page_addrs: Pointer to an array of guest pages for local addresses. * @peer_page_count: Number of entries in @peer_page_count. * @evq0_addrs: Array of guest pages backing evq0. @@ -194,8 +194,8 @@ static unsigned abs_index(struct efx_vf *vf, unsigned index) return EFX_VI_BASE + vf->index * efx_vf_size(vf->efx) + index; } -static int efx_sriov_cmd(struct efx_nic *efx, bool enable, - unsigned *vi_scale_out, unsigned *vf_total_out) +static int efx_siena_sriov_cmd(struct efx_nic *efx, bool enable, + unsigned *vi_scale_out, unsigned *vf_total_out) { MCDI_DECLARE_BUF(inbuf, MC_CMD_SRIOV_IN_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_SRIOV_OUT_LEN); @@ -227,18 +227,20 @@ static int efx_sriov_cmd(struct efx_nic *efx, bool enable, return 0; } -static void efx_sriov_usrev(struct efx_nic *efx, bool enabled) +static void efx_siena_sriov_usrev(struct efx_nic *efx, bool enabled) { + struct siena_nic_data *nic_data = efx->nic_data; efx_oword_t reg; EFX_POPULATE_OWORD_2(reg, FRF_CZ_USREV_DIS, enabled ? 0 : 1, - FRF_CZ_DFLT_EVQ, efx->vfdi_channel->channel); + FRF_CZ_DFLT_EVQ, nic_data->vfdi_channel->channel); efx_writeo(efx, ®, FR_CZ_USR_EV_CFG); } -static int efx_sriov_memcpy(struct efx_nic *efx, struct efx_memcpy_req *req, - unsigned int count) +static int efx_siena_sriov_memcpy(struct efx_nic *efx, + struct efx_memcpy_req *req, + unsigned int count) { MCDI_DECLARE_BUF(inbuf, MCDI_CTL_SDU_LEN_MAX_V1); MCDI_DECLARE_STRUCT_PTR(record); @@ -297,7 +299,7 @@ out: /* The TX filter is entirely controlled by this driver, and is modified * underneath the feet of the VF */ -static void efx_sriov_reset_tx_filter(struct efx_vf *vf) +static void efx_siena_sriov_reset_tx_filter(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; struct efx_filter_spec filter; @@ -341,7 +343,7 @@ static void efx_sriov_reset_tx_filter(struct efx_vf *vf) } /* The RX filter is managed here on behalf of the VF driver */ -static void efx_sriov_reset_rx_filter(struct efx_vf *vf) +static void efx_siena_sriov_reset_rx_filter(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; struct efx_filter_spec filter; @@ -380,22 +382,26 @@ static void efx_sriov_reset_rx_filter(struct efx_vf *vf) } } -static void __efx_sriov_update_vf_addr(struct efx_vf *vf) +static void __efx_siena_sriov_update_vf_addr(struct efx_vf *vf) { - efx_sriov_reset_tx_filter(vf); - efx_sriov_reset_rx_filter(vf); - queue_work(vfdi_workqueue, &vf->efx->peer_work); + struct efx_nic *efx = vf->efx; + struct siena_nic_data *nic_data = efx->nic_data; + + efx_siena_sriov_reset_tx_filter(vf); + efx_siena_sriov_reset_rx_filter(vf); + queue_work(vfdi_workqueue, &nic_data->peer_work); } /* Push the peer list to this VF. The caller must hold status_lock to interlock * with VFDI requests, and they must be serialised against manipulation of * local_page_list, either by acquiring local_lock or by running from - * efx_sriov_peer_work() + * efx_siena_sriov_peer_work() */ -static void __efx_sriov_push_vf_status(struct efx_vf *vf) +static void __efx_siena_sriov_push_vf_status(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; - struct vfdi_status *status = efx->vfdi_status.addr; + struct siena_nic_data *nic_data = efx->nic_data; + struct vfdi_status *status = nic_data->vfdi_status.addr; struct efx_memcpy_req copy[4]; struct efx_endpoint_page *epp; unsigned int pos, count; @@ -421,7 +427,7 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) */ data_offset = offsetof(struct vfdi_status, version); copy[1].from_rid = efx->pci_dev->devfn; - copy[1].from_addr = efx->vfdi_status.dma_addr + data_offset; + copy[1].from_addr = nic_data->vfdi_status.dma_addr + data_offset; copy[1].to_rid = vf->pci_rid; copy[1].to_addr = vf->status_addr + data_offset; copy[1].length = status->length - data_offset; @@ -429,7 +435,7 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) /* Copy the peer pages */ pos = 2; count = 0; - list_for_each_entry(epp, &efx->local_page_list, link) { + list_for_each_entry(epp, &nic_data->local_page_list, link) { if (count == vf->peer_page_count) { /* The VF driver will know they need to provide more * pages because peer_addr_count is too large. @@ -444,7 +450,7 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) copy[pos].length = EFX_PAGE_SIZE; if (++pos == ARRAY_SIZE(copy)) { - efx_sriov_memcpy(efx, copy, ARRAY_SIZE(copy)); + efx_siena_sriov_memcpy(efx, copy, ARRAY_SIZE(copy)); pos = 0; } ++count; @@ -456,7 +462,7 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) copy[pos].to_addr = vf->status_addr + offsetof(struct vfdi_status, generation_end); copy[pos].length = sizeof(status->generation_end); - efx_sriov_memcpy(efx, copy, pos + 1); + efx_siena_sriov_memcpy(efx, copy, pos + 1); /* Notify the guest */ EFX_POPULATE_QWORD_3(event, @@ -469,8 +475,8 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) &event); } -static void efx_sriov_bufs(struct efx_nic *efx, unsigned offset, - u64 *addr, unsigned count) +static void efx_siena_sriov_bufs(struct efx_nic *efx, unsigned offset, + u64 *addr, unsigned count) { efx_qword_t buf; unsigned pos; @@ -539,7 +545,7 @@ static int efx_vfdi_init_evq(struct efx_vf *vf) return VFDI_RC_EINVAL; } - efx_sriov_bufs(efx, buftbl, req->u.init_evq.addr, buf_count); + efx_siena_sriov_bufs(efx, buftbl, req->u.init_evq.addr, buf_count); EFX_POPULATE_OWORD_3(reg, FRF_CZ_TIMER_Q_EN, 1, @@ -584,7 +590,7 @@ static int efx_vfdi_init_rxq(struct efx_vf *vf) } if (__test_and_set_bit(req->u.init_rxq.index, vf->rxq_mask)) ++vf->rxq_count; - efx_sriov_bufs(efx, buftbl, req->u.init_rxq.addr, buf_count); + efx_siena_sriov_bufs(efx, buftbl, req->u.init_rxq.addr, buf_count); label = req->u.init_rxq.label & EFX_FIELD_MASK(FRF_AZ_RX_DESCQ_LABEL); EFX_POPULATE_OWORD_6(reg, @@ -628,7 +634,7 @@ static int efx_vfdi_init_txq(struct efx_vf *vf) if (__test_and_set_bit(req->u.init_txq.index, vf->txq_mask)) ++vf->txq_count; mutex_unlock(&vf->txq_lock); - efx_sriov_bufs(efx, buftbl, req->u.init_txq.addr, buf_count); + efx_siena_sriov_bufs(efx, buftbl, req->u.init_txq.addr, buf_count); eth_filt_en = vf->tx_filter_mode == VF_TX_FILTER_ON; @@ -742,8 +748,8 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) efx_writeo_table(efx, ®, FR_BZ_TIMER_TBL, vf_offset + index); } - efx_sriov_bufs(efx, vf->buftbl_base, NULL, - EFX_VF_BUFTBL_PER_VI * efx_vf_size(efx)); + efx_siena_sriov_bufs(efx, vf->buftbl_base, NULL, + EFX_VF_BUFTBL_PER_VI * efx_vf_size(efx)); efx_vfdi_flush_clear(vf); vf->evq0_count = 0; @@ -754,6 +760,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) static int efx_vfdi_insert_filter(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; + struct siena_nic_data *nic_data = efx->nic_data; struct vfdi_req *req = vf->buf.addr; unsigned vf_rxq = req->u.mac_filter.rxq; unsigned flags; @@ -776,17 +783,20 @@ static int efx_vfdi_insert_filter(struct efx_vf *vf) vf->rx_filter_qid = vf_rxq; vf->rx_filtering = true; - efx_sriov_reset_rx_filter(vf); - queue_work(vfdi_workqueue, &efx->peer_work); + efx_siena_sriov_reset_rx_filter(vf); + queue_work(vfdi_workqueue, &nic_data->peer_work); return VFDI_RC_SUCCESS; } static int efx_vfdi_remove_all_filters(struct efx_vf *vf) { + struct efx_nic *efx = vf->efx; + struct siena_nic_data *nic_data = efx->nic_data; + vf->rx_filtering = false; - efx_sriov_reset_rx_filter(vf); - queue_work(vfdi_workqueue, &vf->efx->peer_work); + efx_siena_sriov_reset_rx_filter(vf); + queue_work(vfdi_workqueue, &nic_data->peer_work); return VFDI_RC_SUCCESS; } @@ -794,6 +804,7 @@ static int efx_vfdi_remove_all_filters(struct efx_vf *vf) static int efx_vfdi_set_status_page(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; + struct siena_nic_data *nic_data = efx->nic_data; struct vfdi_req *req = vf->buf.addr; u64 page_count = req->u.set_status_page.peer_page_count; u64 max_page_count = @@ -809,7 +820,7 @@ static int efx_vfdi_set_status_page(struct efx_vf *vf) return VFDI_RC_EINVAL; } - mutex_lock(&efx->local_lock); + mutex_lock(&nic_data->local_lock); mutex_lock(&vf->status_lock); vf->status_addr = req->u.set_status_page.dma_addr; @@ -828,9 +839,9 @@ static int efx_vfdi_set_status_page(struct efx_vf *vf) } } - __efx_sriov_push_vf_status(vf); + __efx_siena_sriov_push_vf_status(vf); mutex_unlock(&vf->status_lock); - mutex_unlock(&efx->local_lock); + mutex_unlock(&nic_data->local_lock); return VFDI_RC_SUCCESS; } @@ -857,7 +868,7 @@ static const efx_vfdi_op_t vfdi_ops[VFDI_OP_LIMIT] = { [VFDI_OP_CLEAR_STATUS_PAGE] = efx_vfdi_clear_status_page, }; -static void efx_sriov_vfdi(struct work_struct *work) +static void efx_siena_sriov_vfdi(struct work_struct *work) { struct efx_vf *vf = container_of(work, struct efx_vf, req); struct efx_nic *efx = vf->efx; @@ -872,7 +883,7 @@ static void efx_sriov_vfdi(struct work_struct *work) copy[0].to_rid = efx->pci_dev->devfn; copy[0].to_addr = vf->buf.dma_addr; copy[0].length = EFX_PAGE_SIZE; - rc = efx_sriov_memcpy(efx, copy, 1); + rc = efx_siena_sriov_memcpy(efx, copy, 1); if (rc) { /* If we can't get the request, we can't reply to the caller */ if (net_ratelimit()) @@ -916,7 +927,7 @@ static void efx_sriov_vfdi(struct work_struct *work) copy[1].to_addr = vf->req_addr + offsetof(struct vfdi_req, op); copy[1].length = sizeof(req->op); - (void) efx_sriov_memcpy(efx, copy, ARRAY_SIZE(copy)); + (void)efx_siena_sriov_memcpy(efx, copy, ARRAY_SIZE(copy)); } @@ -925,7 +936,8 @@ static void efx_sriov_vfdi(struct work_struct *work) * event ring in guest memory with VFDI reset events, then (re-initialise) the * event queue to raise an interrupt. The guest driver will then recover. */ -static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) +static void efx_siena_sriov_reset_vf(struct efx_vf *vf, + struct efx_buffer *buffer) { struct efx_nic *efx = vf->efx; struct efx_memcpy_req copy_req[4]; @@ -961,7 +973,7 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) copy_req[k].to_addr = vf->evq0_addrs[pos + k]; copy_req[k].length = EFX_PAGE_SIZE; } - rc = efx_sriov_memcpy(efx, copy_req, count); + rc = efx_siena_sriov_memcpy(efx, copy_req, count); if (rc) { if (net_ratelimit()) netif_err(efx, hw, efx->net_dev, @@ -974,7 +986,7 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) /* Reinitialise, arm and trigger evq0 */ abs_evq = abs_index(vf, 0); buftbl = EFX_BUFTBL_EVQ_BASE(vf, 0); - efx_sriov_bufs(efx, buftbl, vf->evq0_addrs, vf->evq0_count); + efx_siena_sriov_bufs(efx, buftbl, vf->evq0_addrs, vf->evq0_count); EFX_POPULATE_OWORD_3(reg, FRF_CZ_TIMER_Q_EN, 1, @@ -992,19 +1004,19 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) mutex_unlock(&vf->status_lock); } -static void efx_sriov_reset_vf_work(struct work_struct *work) +static void efx_siena_sriov_reset_vf_work(struct work_struct *work) { struct efx_vf *vf = container_of(work, struct efx_vf, req); struct efx_nic *efx = vf->efx; struct efx_buffer buf; if (!efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE, GFP_NOIO)) { - efx_sriov_reset_vf(vf, &buf); + efx_siena_sriov_reset_vf(vf, &buf); efx_nic_free_buffer(efx, &buf); } } -static void efx_sriov_handle_no_channel(struct efx_nic *efx) +static void efx_siena_sriov_handle_no_channel(struct efx_nic *efx) { netif_err(efx, drv, efx->net_dev, "ERROR: IOV requires MSI-X and 1 additional interrupt" @@ -1012,35 +1024,38 @@ static void efx_sriov_handle_no_channel(struct efx_nic *efx) efx->vf_count = 0; } -static int efx_sriov_probe_channel(struct efx_channel *channel) +static int efx_siena_sriov_probe_channel(struct efx_channel *channel) { - channel->efx->vfdi_channel = channel; + struct siena_nic_data *nic_data = channel->efx->nic_data; + nic_data->vfdi_channel = channel; + return 0; } static void -efx_sriov_get_channel_name(struct efx_channel *channel, char *buf, size_t len) +efx_siena_sriov_get_channel_name(struct efx_channel *channel, + char *buf, size_t len) { snprintf(buf, len, "%s-iov", channel->efx->name); } -static const struct efx_channel_type efx_sriov_channel_type = { - .handle_no_channel = efx_sriov_handle_no_channel, - .pre_probe = efx_sriov_probe_channel, +static const struct efx_channel_type efx_siena_sriov_channel_type = { + .handle_no_channel = efx_siena_sriov_handle_no_channel, + .pre_probe = efx_siena_sriov_probe_channel, .post_remove = efx_channel_dummy_op_void, - .get_name = efx_sriov_get_channel_name, + .get_name = efx_siena_sriov_get_channel_name, /* no copy operation; channel must not be reallocated */ .keep_eventq = true, }; -void efx_sriov_probe(struct efx_nic *efx) +void efx_siena_sriov_probe(struct efx_nic *efx) { unsigned count; if (!max_vfs) return; - if (efx_sriov_cmd(efx, false, &efx->vi_scale, &count)) + if (efx_siena_sriov_cmd(efx, false, &efx->vi_scale, &count)) return; if (count > 0 && count > max_vfs) count = max_vfs; @@ -1048,17 +1063,20 @@ void efx_sriov_probe(struct efx_nic *efx) /* efx_nic_dimension_resources() will reduce vf_count as appopriate */ efx->vf_count = count; - efx->extra_channel_type[EFX_EXTRA_CHANNEL_IOV] = &efx_sriov_channel_type; + efx->extra_channel_type[EFX_EXTRA_CHANNEL_IOV] = &efx_siena_sriov_channel_type; } /* Copy the list of individual addresses into the vfdi_status.peers * array and auxillary pages, protected by %local_lock. Drop that lock * and then broadcast the address list to every VF. */ -static void efx_sriov_peer_work(struct work_struct *data) +static void efx_siena_sriov_peer_work(struct work_struct *data) { - struct efx_nic *efx = container_of(data, struct efx_nic, peer_work); - struct vfdi_status *vfdi_status = efx->vfdi_status.addr; + struct siena_nic_data *nic_data = container_of(data, + struct siena_nic_data, + peer_work); + struct efx_nic *efx = nic_data->efx; + struct vfdi_status *vfdi_status = nic_data->vfdi_status.addr; struct efx_vf *vf; struct efx_local_addr *local_addr; struct vfdi_endpoint *peer; @@ -1068,11 +1086,11 @@ static void efx_sriov_peer_work(struct work_struct *data) unsigned int peer_count; unsigned int pos; - |