136ff6393SMartin Habets // SPDX-License-Identifier: GPL-2.0-only
236ff6393SMartin Habets /****************************************************************************
336ff6393SMartin Habets * Driver for Solarflare network controllers and boards
436ff6393SMartin Habets * Copyright 2010-2012 Solarflare Communications Inc.
536ff6393SMartin Habets */
636ff6393SMartin Habets #include <linux/pci.h>
736ff6393SMartin Habets #include <linux/module.h>
836ff6393SMartin Habets #include "net_driver.h"
936ff6393SMartin Habets #include "efx.h"
1036ff6393SMartin Habets #include "efx_channels.h"
1136ff6393SMartin Habets #include "nic.h"
1236ff6393SMartin Habets #include "io.h"
1336ff6393SMartin Habets #include "mcdi.h"
1436ff6393SMartin Habets #include "filter.h"
1536ff6393SMartin Habets #include "mcdi_pcol.h"
1636ff6393SMartin Habets #include "farch_regs.h"
1736ff6393SMartin Habets #include "siena_sriov.h"
1836ff6393SMartin Habets #include "vfdi.h"
1936ff6393SMartin Habets
2036ff6393SMartin Habets /* Number of longs required to track all the VIs in a VF */
2136ff6393SMartin Habets #define VI_MASK_LENGTH BITS_TO_LONGS(1 << EFX_VI_SCALE_MAX)
2236ff6393SMartin Habets
2336ff6393SMartin Habets /* Maximum number of RX queues supported */
2436ff6393SMartin Habets #define VF_MAX_RX_QUEUES 63
2536ff6393SMartin Habets
2636ff6393SMartin Habets /**
2736ff6393SMartin Habets * enum efx_vf_tx_filter_mode - TX MAC filtering behaviour
2836ff6393SMartin Habets * @VF_TX_FILTER_OFF: Disabled
2936ff6393SMartin Habets * @VF_TX_FILTER_AUTO: Enabled if MAC address assigned to VF and only
3036ff6393SMartin Habets * 2 TX queues allowed per VF.
3136ff6393SMartin Habets * @VF_TX_FILTER_ON: Enabled
3236ff6393SMartin Habets */
3336ff6393SMartin Habets enum efx_vf_tx_filter_mode {
3436ff6393SMartin Habets VF_TX_FILTER_OFF,
3536ff6393SMartin Habets VF_TX_FILTER_AUTO,
3636ff6393SMartin Habets VF_TX_FILTER_ON,
3736ff6393SMartin Habets };
3836ff6393SMartin Habets
3936ff6393SMartin Habets /**
4036ff6393SMartin Habets * struct siena_vf - Back-end resource and protocol state for a PCI VF
4136ff6393SMartin Habets * @efx: The Efx NIC owning this VF
4236ff6393SMartin Habets * @pci_rid: The PCI requester ID for this VF
4336ff6393SMartin Habets * @pci_name: The PCI name (formatted address) of this VF
4436ff6393SMartin Habets * @index: Index of VF within its port and PF.
4536ff6393SMartin Habets * @req: VFDI incoming request work item. Incoming USR_EV events are received
4636ff6393SMartin Habets * by the NAPI handler, but must be handled by executing MCDI requests
4736ff6393SMartin Habets * inside a work item.
4836ff6393SMartin Habets * @req_addr: VFDI incoming request DMA address (in VF's PCI address space).
4936ff6393SMartin Habets * @req_type: Expected next incoming (from VF) %VFDI_EV_TYPE member.
5036ff6393SMartin Habets * @req_seqno: Expected next incoming (from VF) %VFDI_EV_SEQ member.
5136ff6393SMartin Habets * @msg_seqno: Next %VFDI_EV_SEQ member to reply to VF. Protected by
5236ff6393SMartin Habets * @status_lock
5336ff6393SMartin Habets * @busy: VFDI request queued to be processed or being processed. Receiving
5436ff6393SMartin Habets * a VFDI request when @busy is set is an error condition.
5536ff6393SMartin Habets * @buf: Incoming VFDI requests are DMA from the VF into this buffer.
5636ff6393SMartin Habets * @buftbl_base: Buffer table entries for this VF start at this index.
5736ff6393SMartin Habets * @rx_filtering: Receive filtering has been requested by the VF driver.
5836ff6393SMartin Habets * @rx_filter_flags: The flags sent in the %VFDI_OP_INSERT_FILTER request.
5936ff6393SMartin Habets * @rx_filter_qid: VF relative qid for RX filter requested by VF.
6036ff6393SMartin Habets * @rx_filter_id: Receive MAC filter ID. Only one filter per VF is supported.
6136ff6393SMartin Habets * @tx_filter_mode: Transmit MAC filtering mode.
6236ff6393SMartin Habets * @tx_filter_id: Transmit MAC filter ID.
6336ff6393SMartin Habets * @addr: The MAC address and outer vlan tag of the VF.
6436ff6393SMartin Habets * @status_addr: VF DMA address of page for &struct vfdi_status updates.
6536ff6393SMartin Habets * @status_lock: Mutex protecting @msg_seqno, @status_addr, @addr,
6636ff6393SMartin Habets * @peer_page_addrs and @peer_page_count from simultaneous
6736ff6393SMartin Habets * updates by the VM and consumption by
6836ff6393SMartin Habets * efx_siena_sriov_update_vf_addr()
6936ff6393SMartin Habets * @peer_page_addrs: Pointer to an array of guest pages for local addresses.
7036ff6393SMartin Habets * @peer_page_count: Number of entries in @peer_page_count.
7136ff6393SMartin Habets * @evq0_addrs: Array of guest pages backing evq0.
7236ff6393SMartin Habets * @evq0_count: Number of entries in @evq0_addrs.
7336ff6393SMartin Habets * @flush_waitq: wait queue used by %VFDI_OP_FINI_ALL_QUEUES handler
7436ff6393SMartin Habets * to wait for flush completions.
7536ff6393SMartin Habets * @txq_lock: Mutex for TX queue allocation.
7636ff6393SMartin Habets * @txq_mask: Mask of initialized transmit queues.
7736ff6393SMartin Habets * @txq_count: Number of initialized transmit queues.
7836ff6393SMartin Habets * @rxq_mask: Mask of initialized receive queues.
7936ff6393SMartin Habets * @rxq_count: Number of initialized receive queues.
8036ff6393SMartin Habets * @rxq_retry_mask: Mask or receive queues that need to be flushed again
8136ff6393SMartin Habets * due to flush failure.
8236ff6393SMartin Habets * @rxq_retry_count: Number of receive queues in @rxq_retry_mask.
8336ff6393SMartin Habets * @reset_work: Work item to schedule a VF reset.
8436ff6393SMartin Habets */
8536ff6393SMartin Habets struct siena_vf {
8636ff6393SMartin Habets struct efx_nic *efx;
8736ff6393SMartin Habets unsigned int pci_rid;
8836ff6393SMartin Habets char pci_name[13]; /* dddd:bb:dd.f */
8936ff6393SMartin Habets unsigned int index;
9036ff6393SMartin Habets struct work_struct req;
9136ff6393SMartin Habets u64 req_addr;
9236ff6393SMartin Habets int req_type;
9336ff6393SMartin Habets unsigned req_seqno;
9436ff6393SMartin Habets unsigned msg_seqno;
9536ff6393SMartin Habets bool busy;
9636ff6393SMartin Habets struct efx_buffer buf;
9736ff6393SMartin Habets unsigned buftbl_base;
9836ff6393SMartin Habets bool rx_filtering;
9936ff6393SMartin Habets enum efx_filter_flags rx_filter_flags;
10036ff6393SMartin Habets unsigned rx_filter_qid;
10136ff6393SMartin Habets int rx_filter_id;
10236ff6393SMartin Habets enum efx_vf_tx_filter_mode tx_filter_mode;
10336ff6393SMartin Habets int tx_filter_id;
10436ff6393SMartin Habets struct vfdi_endpoint addr;
10536ff6393SMartin Habets u64 status_addr;
10636ff6393SMartin Habets struct mutex status_lock;
10736ff6393SMartin Habets u64 *peer_page_addrs;
10836ff6393SMartin Habets unsigned peer_page_count;
10936ff6393SMartin Habets u64 evq0_addrs[EFX_MAX_VF_EVQ_SIZE * sizeof(efx_qword_t) /
11036ff6393SMartin Habets EFX_BUF_SIZE];
11136ff6393SMartin Habets unsigned evq0_count;
11236ff6393SMartin Habets wait_queue_head_t flush_waitq;
11336ff6393SMartin Habets struct mutex txq_lock;
11436ff6393SMartin Habets unsigned long txq_mask[VI_MASK_LENGTH];
11536ff6393SMartin Habets unsigned txq_count;
11636ff6393SMartin Habets unsigned long rxq_mask[VI_MASK_LENGTH];
11736ff6393SMartin Habets unsigned rxq_count;
11836ff6393SMartin Habets unsigned long rxq_retry_mask[VI_MASK_LENGTH];
11936ff6393SMartin Habets atomic_t rxq_retry_count;
12036ff6393SMartin Habets struct work_struct reset_work;
12136ff6393SMartin Habets };
12236ff6393SMartin Habets
12336ff6393SMartin Habets struct efx_memcpy_req {
12436ff6393SMartin Habets unsigned int from_rid;
12536ff6393SMartin Habets void *from_buf;
12636ff6393SMartin Habets u64 from_addr;
12736ff6393SMartin Habets unsigned int to_rid;
12836ff6393SMartin Habets u64 to_addr;
12936ff6393SMartin Habets unsigned length;
13036ff6393SMartin Habets };
13136ff6393SMartin Habets
13236ff6393SMartin Habets /**
13336ff6393SMartin Habets * struct efx_local_addr - A MAC address on the vswitch without a VF.
13436ff6393SMartin Habets *
13536ff6393SMartin Habets * Siena does not have a switch, so VFs can't transmit data to each
13636ff6393SMartin Habets * other. Instead the VFs must be made aware of the local addresses
13736ff6393SMartin Habets * on the vswitch, so that they can arrange for an alternative
13836ff6393SMartin Habets * software datapath to be used.
13936ff6393SMartin Habets *
14036ff6393SMartin Habets * @link: List head for insertion into efx->local_addr_list.
14136ff6393SMartin Habets * @addr: Ethernet address
14236ff6393SMartin Habets */
14336ff6393SMartin Habets struct efx_local_addr {
14436ff6393SMartin Habets struct list_head link;
14536ff6393SMartin Habets u8 addr[ETH_ALEN];
14636ff6393SMartin Habets };
14736ff6393SMartin Habets
14836ff6393SMartin Habets /**
14936ff6393SMartin Habets * struct efx_endpoint_page - Page of vfdi_endpoint structures
15036ff6393SMartin Habets *
15136ff6393SMartin Habets * @link: List head for insertion into efx->local_page_list.
15236ff6393SMartin Habets * @ptr: Pointer to page.
15336ff6393SMartin Habets * @addr: DMA address of page.
15436ff6393SMartin Habets */
15536ff6393SMartin Habets struct efx_endpoint_page {
15636ff6393SMartin Habets struct list_head link;
15736ff6393SMartin Habets void *ptr;
15836ff6393SMartin Habets dma_addr_t addr;
15936ff6393SMartin Habets };
16036ff6393SMartin Habets
16136ff6393SMartin Habets /* Buffer table entries are reserved txq0,rxq0,evq0,txq1,rxq1,evq1 */
16236ff6393SMartin Habets #define EFX_BUFTBL_TXQ_BASE(_vf, _qid) \
16336ff6393SMartin Habets ((_vf)->buftbl_base + EFX_VF_BUFTBL_PER_VI * (_qid))
16436ff6393SMartin Habets #define EFX_BUFTBL_RXQ_BASE(_vf, _qid) \
16536ff6393SMartin Habets (EFX_BUFTBL_TXQ_BASE(_vf, _qid) + \
16636ff6393SMartin Habets (EFX_MAX_DMAQ_SIZE * sizeof(efx_qword_t) / EFX_BUF_SIZE))
16736ff6393SMartin Habets #define EFX_BUFTBL_EVQ_BASE(_vf, _qid) \
16836ff6393SMartin Habets (EFX_BUFTBL_TXQ_BASE(_vf, _qid) + \
16936ff6393SMartin Habets (2 * EFX_MAX_DMAQ_SIZE * sizeof(efx_qword_t) / EFX_BUF_SIZE))
17036ff6393SMartin Habets
17136ff6393SMartin Habets #define EFX_FIELD_MASK(_field) \
17236ff6393SMartin Habets ((1 << _field ## _WIDTH) - 1)
17336ff6393SMartin Habets
17436ff6393SMartin Habets /* VFs can only use this many transmit channels */
17536ff6393SMartin Habets static unsigned int vf_max_tx_channels = 2;
17636ff6393SMartin Habets module_param(vf_max_tx_channels, uint, 0444);
17736ff6393SMartin Habets MODULE_PARM_DESC(vf_max_tx_channels,
17836ff6393SMartin Habets "Limit the number of TX channels VFs can use");
17936ff6393SMartin Habets
18036ff6393SMartin Habets static int max_vfs = -1;
18136ff6393SMartin Habets module_param(max_vfs, int, 0444);
18236ff6393SMartin Habets MODULE_PARM_DESC(max_vfs,
18336ff6393SMartin Habets "Reduce the number of VFs initialized by the driver");
18436ff6393SMartin Habets
18536ff6393SMartin Habets /* Workqueue used by VFDI communication. We can't use the global
18636ff6393SMartin Habets * workqueue because it may be running the VF driver's probe()
18736ff6393SMartin Habets * routine, which will be blocked there waiting for a VFDI response.
18836ff6393SMartin Habets */
18936ff6393SMartin Habets static struct workqueue_struct *vfdi_workqueue;
19036ff6393SMartin Habets
abs_index(struct siena_vf * vf,unsigned index)19136ff6393SMartin Habets static unsigned abs_index(struct siena_vf *vf, unsigned index)
19236ff6393SMartin Habets {
19336ff6393SMartin Habets return EFX_VI_BASE + vf->index * efx_vf_size(vf->efx) + index;
19436ff6393SMartin Habets }
19536ff6393SMartin Habets
efx_siena_sriov_cmd(struct efx_nic * efx,bool enable,unsigned * vi_scale_out,unsigned * vf_total_out)19636ff6393SMartin Habets static int efx_siena_sriov_cmd(struct efx_nic *efx, bool enable,
19736ff6393SMartin Habets unsigned *vi_scale_out, unsigned *vf_total_out)
19836ff6393SMartin Habets {
19936ff6393SMartin Habets MCDI_DECLARE_BUF(inbuf, MC_CMD_SRIOV_IN_LEN);
20036ff6393SMartin Habets MCDI_DECLARE_BUF(outbuf, MC_CMD_SRIOV_OUT_LEN);
20136ff6393SMartin Habets unsigned vi_scale, vf_total;
20236ff6393SMartin Habets size_t outlen;
20336ff6393SMartin Habets int rc;
20436ff6393SMartin Habets
20536ff6393SMartin Habets MCDI_SET_DWORD(inbuf, SRIOV_IN_ENABLE, enable ? 1 : 0);
20636ff6393SMartin Habets MCDI_SET_DWORD(inbuf, SRIOV_IN_VI_BASE, EFX_VI_BASE);
20736ff6393SMartin Habets MCDI_SET_DWORD(inbuf, SRIOV_IN_VF_COUNT, efx->vf_count);
20836ff6393SMartin Habets
2094d49e5cdSMartin Habets rc = efx_siena_mcdi_rpc_quiet(efx, MC_CMD_SRIOV, inbuf,
2104d49e5cdSMartin Habets MC_CMD_SRIOV_IN_LEN, outbuf,
2114d49e5cdSMartin Habets MC_CMD_SRIOV_OUT_LEN, &outlen);
21236ff6393SMartin Habets if (rc)
21336ff6393SMartin Habets return rc;
21436ff6393SMartin Habets if (outlen < MC_CMD_SRIOV_OUT_LEN)
21536ff6393SMartin Habets return -EIO;
21636ff6393SMartin Habets
21736ff6393SMartin Habets vf_total = MCDI_DWORD(outbuf, SRIOV_OUT_VF_TOTAL);
21836ff6393SMartin Habets vi_scale = MCDI_DWORD(outbuf, SRIOV_OUT_VI_SCALE);
21936ff6393SMartin Habets if (vi_scale > EFX_VI_SCALE_MAX)
22036ff6393SMartin Habets return -EOPNOTSUPP;
22136ff6393SMartin Habets
22236ff6393SMartin Habets if (vi_scale_out)
22336ff6393SMartin Habets *vi_scale_out = vi_scale;
22436ff6393SMartin Habets if (vf_total_out)
22536ff6393SMartin Habets *vf_total_out = vf_total;
22636ff6393SMartin Habets
22736ff6393SMartin Habets return 0;
22836ff6393SMartin Habets }
22936ff6393SMartin Habets
efx_siena_sriov_usrev(struct efx_nic * efx,bool enabled)23036ff6393SMartin Habets static void efx_siena_sriov_usrev(struct efx_nic *efx, bool enabled)
23136ff6393SMartin Habets {
23236ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
23336ff6393SMartin Habets efx_oword_t reg;
23436ff6393SMartin Habets
23536ff6393SMartin Habets EFX_POPULATE_OWORD_2(reg,
23636ff6393SMartin Habets FRF_CZ_USREV_DIS, enabled ? 0 : 1,
23736ff6393SMartin Habets FRF_CZ_DFLT_EVQ, nic_data->vfdi_channel->channel);
23836ff6393SMartin Habets efx_writeo(efx, ®, FR_CZ_USR_EV_CFG);
23936ff6393SMartin Habets }
24036ff6393SMartin Habets
efx_siena_sriov_memcpy(struct efx_nic * efx,struct efx_memcpy_req * req,unsigned int count)24136ff6393SMartin Habets static int efx_siena_sriov_memcpy(struct efx_nic *efx,
24236ff6393SMartin Habets struct efx_memcpy_req *req,
24336ff6393SMartin Habets unsigned int count)
24436ff6393SMartin Habets {
24536ff6393SMartin Habets MCDI_DECLARE_BUF(inbuf, MCDI_CTL_SDU_LEN_MAX_V1);
24636ff6393SMartin Habets MCDI_DECLARE_STRUCT_PTR(record);
24736ff6393SMartin Habets unsigned int index, used;
24836ff6393SMartin Habets u64 from_addr;
24936ff6393SMartin Habets u32 from_rid;
25036ff6393SMartin Habets int rc;
25136ff6393SMartin Habets
25236ff6393SMartin Habets mb(); /* Finish writing source/reading dest before DMA starts */
25336ff6393SMartin Habets
25436ff6393SMartin Habets if (WARN_ON(count > MC_CMD_MEMCPY_IN_RECORD_MAXNUM))
25536ff6393SMartin Habets return -ENOBUFS;
25636ff6393SMartin Habets used = MC_CMD_MEMCPY_IN_LEN(count);
25736ff6393SMartin Habets
25836ff6393SMartin Habets for (index = 0; index < count; index++) {
25936ff6393SMartin Habets record = MCDI_ARRAY_STRUCT_PTR(inbuf, MEMCPY_IN_RECORD, index);
26036ff6393SMartin Habets MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_NUM_RECORDS,
26136ff6393SMartin Habets count);
26236ff6393SMartin Habets MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_TO_RID,
26336ff6393SMartin Habets req->to_rid);
26436ff6393SMartin Habets MCDI_SET_QWORD(record, MEMCPY_RECORD_TYPEDEF_TO_ADDR,
26536ff6393SMartin Habets req->to_addr);
26636ff6393SMartin Habets if (req->from_buf == NULL) {
26736ff6393SMartin Habets from_rid = req->from_rid;
26836ff6393SMartin Habets from_addr = req->from_addr;
26936ff6393SMartin Habets } else {
27036ff6393SMartin Habets if (WARN_ON(used + req->length >
27136ff6393SMartin Habets MCDI_CTL_SDU_LEN_MAX_V1)) {
27236ff6393SMartin Habets rc = -ENOBUFS;
27336ff6393SMartin Habets goto out;
27436ff6393SMartin Habets }
27536ff6393SMartin Habets
27636ff6393SMartin Habets from_rid = MC_CMD_MEMCPY_RECORD_TYPEDEF_RID_INLINE;
27736ff6393SMartin Habets from_addr = used;
27836ff6393SMartin Habets memcpy(_MCDI_PTR(inbuf, used), req->from_buf,
27936ff6393SMartin Habets req->length);
28036ff6393SMartin Habets used += req->length;
28136ff6393SMartin Habets }
28236ff6393SMartin Habets
28336ff6393SMartin Habets MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_FROM_RID, from_rid);
28436ff6393SMartin Habets MCDI_SET_QWORD(record, MEMCPY_RECORD_TYPEDEF_FROM_ADDR,
28536ff6393SMartin Habets from_addr);
28636ff6393SMartin Habets MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_LENGTH,
28736ff6393SMartin Habets req->length);
28836ff6393SMartin Habets
28936ff6393SMartin Habets ++req;
29036ff6393SMartin Habets }
29136ff6393SMartin Habets
2924d49e5cdSMartin Habets rc = efx_siena_mcdi_rpc(efx, MC_CMD_MEMCPY, inbuf, used, NULL, 0, NULL);
29336ff6393SMartin Habets out:
29436ff6393SMartin Habets mb(); /* Don't write source/read dest before DMA is complete */
29536ff6393SMartin Habets
29636ff6393SMartin Habets return rc;
29736ff6393SMartin Habets }
29836ff6393SMartin Habets
29936ff6393SMartin Habets /* The TX filter is entirely controlled by this driver, and is modified
30036ff6393SMartin Habets * underneath the feet of the VF
30136ff6393SMartin Habets */
efx_siena_sriov_reset_tx_filter(struct siena_vf * vf)30236ff6393SMartin Habets static void efx_siena_sriov_reset_tx_filter(struct siena_vf *vf)
30336ff6393SMartin Habets {
30436ff6393SMartin Habets struct efx_nic *efx = vf->efx;
30536ff6393SMartin Habets struct efx_filter_spec filter;
30636ff6393SMartin Habets u16 vlan;
30736ff6393SMartin Habets int rc;
30836ff6393SMartin Habets
30936ff6393SMartin Habets if (vf->tx_filter_id != -1) {
31036ff6393SMartin Habets efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
31136ff6393SMartin Habets vf->tx_filter_id);
31236ff6393SMartin Habets netif_dbg(efx, hw, efx->net_dev, "Removed vf %s tx filter %d\n",
31336ff6393SMartin Habets vf->pci_name, vf->tx_filter_id);
31436ff6393SMartin Habets vf->tx_filter_id = -1;
31536ff6393SMartin Habets }
31636ff6393SMartin Habets
31736ff6393SMartin Habets if (is_zero_ether_addr(vf->addr.mac_addr))
31836ff6393SMartin Habets return;
31936ff6393SMartin Habets
32036ff6393SMartin Habets /* Turn on TX filtering automatically if not explicitly
32136ff6393SMartin Habets * enabled or disabled.
32236ff6393SMartin Habets */
32336ff6393SMartin Habets if (vf->tx_filter_mode == VF_TX_FILTER_AUTO && vf_max_tx_channels <= 2)
32436ff6393SMartin Habets vf->tx_filter_mode = VF_TX_FILTER_ON;
32536ff6393SMartin Habets
32636ff6393SMartin Habets vlan = ntohs(vf->addr.tci) & VLAN_VID_MASK;
32736ff6393SMartin Habets efx_filter_init_tx(&filter, abs_index(vf, 0));
32836ff6393SMartin Habets rc = efx_filter_set_eth_local(&filter,
32936ff6393SMartin Habets vlan ? vlan : EFX_FILTER_VID_UNSPEC,
33036ff6393SMartin Habets vf->addr.mac_addr);
33136ff6393SMartin Habets BUG_ON(rc);
33236ff6393SMartin Habets
33336ff6393SMartin Habets rc = efx_filter_insert_filter(efx, &filter, true);
33436ff6393SMartin Habets if (rc < 0) {
33536ff6393SMartin Habets netif_warn(efx, hw, efx->net_dev,
33636ff6393SMartin Habets "Unable to migrate tx filter for vf %s\n",
33736ff6393SMartin Habets vf->pci_name);
33836ff6393SMartin Habets } else {
33936ff6393SMartin Habets netif_dbg(efx, hw, efx->net_dev, "Inserted vf %s tx filter %d\n",
34036ff6393SMartin Habets vf->pci_name, rc);
34136ff6393SMartin Habets vf->tx_filter_id = rc;
34236ff6393SMartin Habets }
34336ff6393SMartin Habets }
34436ff6393SMartin Habets
34536ff6393SMartin Habets /* The RX filter is managed here on behalf of the VF driver */
efx_siena_sriov_reset_rx_filter(struct siena_vf * vf)34636ff6393SMartin Habets static void efx_siena_sriov_reset_rx_filter(struct siena_vf *vf)
34736ff6393SMartin Habets {
34836ff6393SMartin Habets struct efx_nic *efx = vf->efx;
34936ff6393SMartin Habets struct efx_filter_spec filter;
35036ff6393SMartin Habets u16 vlan;
35136ff6393SMartin Habets int rc;
35236ff6393SMartin Habets
35336ff6393SMartin Habets if (vf->rx_filter_id != -1) {
35436ff6393SMartin Habets efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
35536ff6393SMartin Habets vf->rx_filter_id);
35636ff6393SMartin Habets netif_dbg(efx, hw, efx->net_dev, "Removed vf %s rx filter %d\n",
35736ff6393SMartin Habets vf->pci_name, vf->rx_filter_id);
35836ff6393SMartin Habets vf->rx_filter_id = -1;
35936ff6393SMartin Habets }
36036ff6393SMartin Habets
36136ff6393SMartin Habets if (!vf->rx_filtering || is_zero_ether_addr(vf->addr.mac_addr))
36236ff6393SMartin Habets return;
36336ff6393SMartin Habets
36436ff6393SMartin Habets vlan = ntohs(vf->addr.tci) & VLAN_VID_MASK;
36536ff6393SMartin Habets efx_filter_init_rx(&filter, EFX_FILTER_PRI_REQUIRED,
36636ff6393SMartin Habets vf->rx_filter_flags,
36736ff6393SMartin Habets abs_index(vf, vf->rx_filter_qid));
36836ff6393SMartin Habets rc = efx_filter_set_eth_local(&filter,
36936ff6393SMartin Habets vlan ? vlan : EFX_FILTER_VID_UNSPEC,
37036ff6393SMartin Habets vf->addr.mac_addr);
37136ff6393SMartin Habets BUG_ON(rc);
37236ff6393SMartin Habets
37336ff6393SMartin Habets rc = efx_filter_insert_filter(efx, &filter, true);
37436ff6393SMartin Habets if (rc < 0) {
37536ff6393SMartin Habets netif_warn(efx, hw, efx->net_dev,
37636ff6393SMartin Habets "Unable to insert rx filter for vf %s\n",
37736ff6393SMartin Habets vf->pci_name);
37836ff6393SMartin Habets } else {
37936ff6393SMartin Habets netif_dbg(efx, hw, efx->net_dev, "Inserted vf %s rx filter %d\n",
38036ff6393SMartin Habets vf->pci_name, rc);
38136ff6393SMartin Habets vf->rx_filter_id = rc;
38236ff6393SMartin Habets }
38336ff6393SMartin Habets }
38436ff6393SMartin Habets
__efx_siena_sriov_update_vf_addr(struct siena_vf * vf)38536ff6393SMartin Habets static void __efx_siena_sriov_update_vf_addr(struct siena_vf *vf)
38636ff6393SMartin Habets {
38736ff6393SMartin Habets struct efx_nic *efx = vf->efx;
38836ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
38936ff6393SMartin Habets
39036ff6393SMartin Habets efx_siena_sriov_reset_tx_filter(vf);
39136ff6393SMartin Habets efx_siena_sriov_reset_rx_filter(vf);
39236ff6393SMartin Habets queue_work(vfdi_workqueue, &nic_data->peer_work);
39336ff6393SMartin Habets }
39436ff6393SMartin Habets
39536ff6393SMartin Habets /* Push the peer list to this VF. The caller must hold status_lock to interlock
39636ff6393SMartin Habets * with VFDI requests, and they must be serialised against manipulation of
39736ff6393SMartin Habets * local_page_list, either by acquiring local_lock or by running from
39836ff6393SMartin Habets * efx_siena_sriov_peer_work()
39936ff6393SMartin Habets */
__efx_siena_sriov_push_vf_status(struct siena_vf * vf)40036ff6393SMartin Habets static void __efx_siena_sriov_push_vf_status(struct siena_vf *vf)
40136ff6393SMartin Habets {
40236ff6393SMartin Habets struct efx_nic *efx = vf->efx;
40336ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
40436ff6393SMartin Habets struct vfdi_status *status = nic_data->vfdi_status.addr;
40536ff6393SMartin Habets struct efx_memcpy_req copy[4];
40636ff6393SMartin Habets struct efx_endpoint_page *epp;
40736ff6393SMartin Habets unsigned int pos, count;
40836ff6393SMartin Habets unsigned data_offset;
40936ff6393SMartin Habets efx_qword_t event;
41036ff6393SMartin Habets
41136ff6393SMartin Habets WARN_ON(!mutex_is_locked(&vf->status_lock));
41236ff6393SMartin Habets WARN_ON(!vf->status_addr);
41336ff6393SMartin Habets
41436ff6393SMartin Habets status->local = vf->addr;
41536ff6393SMartin Habets status->generation_end = ++status->generation_start;
41636ff6393SMartin Habets
41736ff6393SMartin Habets memset(copy, '\0', sizeof(copy));
41836ff6393SMartin Habets /* Write generation_start */
41936ff6393SMartin Habets copy[0].from_buf = &status->generation_start;
42036ff6393SMartin Habets copy[0].to_rid = vf->pci_rid;
42136ff6393SMartin Habets copy[0].to_addr = vf->status_addr + offsetof(struct vfdi_status,
42236ff6393SMartin Habets generation_start);
42336ff6393SMartin Habets copy[0].length = sizeof(status->generation_start);
42436ff6393SMartin Habets /* DMA the rest of the structure (excluding the generations). This
42536ff6393SMartin Habets * assumes that the non-generation portion of vfdi_status is in
42636ff6393SMartin Habets * one chunk starting at the version member.
42736ff6393SMartin Habets */
42836ff6393SMartin Habets data_offset = offsetof(struct vfdi_status, version);
42936ff6393SMartin Habets copy[1].from_rid = efx->pci_dev->devfn;
43036ff6393SMartin Habets copy[1].from_addr = nic_data->vfdi_status.dma_addr + data_offset;
43136ff6393SMartin Habets copy[1].to_rid = vf->pci_rid;
43236ff6393SMartin Habets copy[1].to_addr = vf->status_addr + data_offset;
43336ff6393SMartin Habets copy[1].length = status->length - data_offset;
43436ff6393SMartin Habets
43536ff6393SMartin Habets /* Copy the peer pages */
43636ff6393SMartin Habets pos = 2;
43736ff6393SMartin Habets count = 0;
43836ff6393SMartin Habets list_for_each_entry(epp, &nic_data->local_page_list, link) {
43936ff6393SMartin Habets if (count == vf->peer_page_count) {
44036ff6393SMartin Habets /* The VF driver will know they need to provide more
44136ff6393SMartin Habets * pages because peer_addr_count is too large.
44236ff6393SMartin Habets */
44336ff6393SMartin Habets break;
44436ff6393SMartin Habets }
44536ff6393SMartin Habets copy[pos].from_buf = NULL;
44636ff6393SMartin Habets copy[pos].from_rid = efx->pci_dev->devfn;
44736ff6393SMartin Habets copy[pos].from_addr = epp->addr;
44836ff6393SMartin Habets copy[pos].to_rid = vf->pci_rid;
44936ff6393SMartin Habets copy[pos].to_addr = vf->peer_page_addrs[count];
45036ff6393SMartin Habets copy[pos].length = EFX_PAGE_SIZE;
45136ff6393SMartin Habets
45236ff6393SMartin Habets if (++pos == ARRAY_SIZE(copy)) {
45336ff6393SMartin Habets efx_siena_sriov_memcpy(efx, copy, ARRAY_SIZE(copy));
45436ff6393SMartin Habets pos = 0;
45536ff6393SMartin Habets }
45636ff6393SMartin Habets ++count;
45736ff6393SMartin Habets }
45836ff6393SMartin Habets
45936ff6393SMartin Habets /* Write generation_end */
46036ff6393SMartin Habets copy[pos].from_buf = &status->generation_end;
46136ff6393SMartin Habets copy[pos].to_rid = vf->pci_rid;
46236ff6393SMartin Habets copy[pos].to_addr = vf->status_addr + offsetof(struct vfdi_status,
46336ff6393SMartin Habets generation_end);
46436ff6393SMartin Habets copy[pos].length = sizeof(status->generation_end);
46536ff6393SMartin Habets efx_siena_sriov_memcpy(efx, copy, pos + 1);
46636ff6393SMartin Habets
46736ff6393SMartin Habets /* Notify the guest */
46836ff6393SMartin Habets EFX_POPULATE_QWORD_3(event,
46936ff6393SMartin Habets FSF_AZ_EV_CODE, FSE_CZ_EV_CODE_USER_EV,
47036ff6393SMartin Habets VFDI_EV_SEQ, (vf->msg_seqno & 0xff),
47136ff6393SMartin Habets VFDI_EV_TYPE, VFDI_EV_TYPE_STATUS);
47236ff6393SMartin Habets ++vf->msg_seqno;
47336ff6393SMartin Habets efx_farch_generate_event(efx,
47436ff6393SMartin Habets EFX_VI_BASE + vf->index * efx_vf_size(efx),
47536ff6393SMartin Habets &event);
47636ff6393SMartin Habets }
47736ff6393SMartin Habets
efx_siena_sriov_bufs(struct efx_nic * efx,unsigned offset,u64 * addr,unsigned count)47836ff6393SMartin Habets static void efx_siena_sriov_bufs(struct efx_nic *efx, unsigned offset,
47936ff6393SMartin Habets u64 *addr, unsigned count)
48036ff6393SMartin Habets {
48136ff6393SMartin Habets efx_qword_t buf;
48236ff6393SMartin Habets unsigned pos;
48336ff6393SMartin Habets
48436ff6393SMartin Habets for (pos = 0; pos < count; ++pos) {
48536ff6393SMartin Habets EFX_POPULATE_QWORD_3(buf,
48636ff6393SMartin Habets FRF_AZ_BUF_ADR_REGION, 0,
48736ff6393SMartin Habets FRF_AZ_BUF_ADR_FBUF,
48836ff6393SMartin Habets addr ? addr[pos] >> 12 : 0,
48936ff6393SMartin Habets FRF_AZ_BUF_OWNER_ID_FBUF, 0);
49036ff6393SMartin Habets efx_sram_writeq(efx, efx->membase + FR_BZ_BUF_FULL_TBL,
49136ff6393SMartin Habets &buf, offset + pos);
49236ff6393SMartin Habets }
49336ff6393SMartin Habets }
49436ff6393SMartin Habets
bad_vf_index(struct efx_nic * efx,unsigned index)49536ff6393SMartin Habets static bool bad_vf_index(struct efx_nic *efx, unsigned index)
49636ff6393SMartin Habets {
49736ff6393SMartin Habets return index >= efx_vf_size(efx);
49836ff6393SMartin Habets }
49936ff6393SMartin Habets
bad_buf_count(unsigned buf_count,unsigned max_entry_count)50036ff6393SMartin Habets static bool bad_buf_count(unsigned buf_count, unsigned max_entry_count)
50136ff6393SMartin Habets {
50236ff6393SMartin Habets unsigned max_buf_count = max_entry_count *
50336ff6393SMartin Habets sizeof(efx_qword_t) / EFX_BUF_SIZE;
50436ff6393SMartin Habets
50536ff6393SMartin Habets return ((buf_count & (buf_count - 1)) || buf_count > max_buf_count);
50636ff6393SMartin Habets }
50736ff6393SMartin Habets
50836ff6393SMartin Habets /* Check that VI specified by per-port index belongs to a VF.
50936ff6393SMartin Habets * Optionally set VF index and VI index within the VF.
51036ff6393SMartin Habets */
map_vi_index(struct efx_nic * efx,unsigned abs_index,struct siena_vf ** vf_out,unsigned * rel_index_out)51136ff6393SMartin Habets static bool map_vi_index(struct efx_nic *efx, unsigned abs_index,
51236ff6393SMartin Habets struct siena_vf **vf_out, unsigned *rel_index_out)
51336ff6393SMartin Habets {
51436ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
51536ff6393SMartin Habets unsigned vf_i;
51636ff6393SMartin Habets
51736ff6393SMartin Habets if (abs_index < EFX_VI_BASE)
51836ff6393SMartin Habets return true;
51936ff6393SMartin Habets vf_i = (abs_index - EFX_VI_BASE) / efx_vf_size(efx);
52036ff6393SMartin Habets if (vf_i >= efx->vf_init_count)
52136ff6393SMartin Habets return true;
52236ff6393SMartin Habets
52336ff6393SMartin Habets if (vf_out)
52436ff6393SMartin Habets *vf_out = nic_data->vf + vf_i;
52536ff6393SMartin Habets if (rel_index_out)
52636ff6393SMartin Habets *rel_index_out = abs_index % efx_vf_size(efx);
52736ff6393SMartin Habets return false;
52836ff6393SMartin Habets }
52936ff6393SMartin Habets
efx_vfdi_init_evq(struct siena_vf * vf)53036ff6393SMartin Habets static int efx_vfdi_init_evq(struct siena_vf *vf)
53136ff6393SMartin Habets {
53236ff6393SMartin Habets struct efx_nic *efx = vf->efx;
53336ff6393SMartin Habets struct vfdi_req *req = vf->buf.addr;
53436ff6393SMartin Habets unsigned vf_evq = req->u.init_evq.index;
53536ff6393SMartin Habets unsigned buf_count = req->u.init_evq.buf_count;
53636ff6393SMartin Habets unsigned abs_evq = abs_index(vf, vf_evq);
53736ff6393SMartin Habets unsigned buftbl = EFX_BUFTBL_EVQ_BASE(vf, vf_evq);
53836ff6393SMartin Habets efx_oword_t reg;
53936ff6393SMartin Habets
54036ff6393SMartin Habets if (bad_vf_index(efx, vf_evq) ||
54136ff6393SMartin Habets bad_buf_count(buf_count, EFX_MAX_VF_EVQ_SIZE)) {
54236ff6393SMartin Habets if (net_ratelimit())
54336ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
54436ff6393SMartin Habets "ERROR: Invalid INIT_EVQ from %s: evq %d bufs %d\n",
54536ff6393SMartin Habets vf->pci_name, vf_evq, buf_count);
54636ff6393SMartin Habets return VFDI_RC_EINVAL;
54736ff6393SMartin Habets }
54836ff6393SMartin Habets
54936ff6393SMartin Habets efx_siena_sriov_bufs(efx, buftbl, req->u.init_evq.addr, buf_count);
55036ff6393SMartin Habets
55136ff6393SMartin Habets EFX_POPULATE_OWORD_3(reg,
55236ff6393SMartin Habets FRF_CZ_TIMER_Q_EN, 1,
55336ff6393SMartin Habets FRF_CZ_HOST_NOTIFY_MODE, 0,
55436ff6393SMartin Habets FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS);
55536ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_TIMER_TBL, abs_evq);
55636ff6393SMartin Habets EFX_POPULATE_OWORD_3(reg,
55736ff6393SMartin Habets FRF_AZ_EVQ_EN, 1,
55836ff6393SMartin Habets FRF_AZ_EVQ_SIZE, __ffs(buf_count),
55936ff6393SMartin Habets FRF_AZ_EVQ_BUF_BASE_ID, buftbl);
56036ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_EVQ_PTR_TBL, abs_evq);
56136ff6393SMartin Habets
56236ff6393SMartin Habets if (vf_evq == 0) {
56336ff6393SMartin Habets memcpy(vf->evq0_addrs, req->u.init_evq.addr,
56436ff6393SMartin Habets buf_count * sizeof(u64));
56536ff6393SMartin Habets vf->evq0_count = buf_count;
56636ff6393SMartin Habets }
56736ff6393SMartin Habets
56836ff6393SMartin Habets return VFDI_RC_SUCCESS;
56936ff6393SMartin Habets }
57036ff6393SMartin Habets
efx_vfdi_init_rxq(struct siena_vf * vf)57136ff6393SMartin Habets static int efx_vfdi_init_rxq(struct siena_vf *vf)
57236ff6393SMartin Habets {
57336ff6393SMartin Habets struct efx_nic *efx = vf->efx;
57436ff6393SMartin Habets struct vfdi_req *req = vf->buf.addr;
57536ff6393SMartin Habets unsigned vf_rxq = req->u.init_rxq.index;
57636ff6393SMartin Habets unsigned vf_evq = req->u.init_rxq.evq;
57736ff6393SMartin Habets unsigned buf_count = req->u.init_rxq.buf_count;
57836ff6393SMartin Habets unsigned buftbl = EFX_BUFTBL_RXQ_BASE(vf, vf_rxq);
57936ff6393SMartin Habets unsigned label;
58036ff6393SMartin Habets efx_oword_t reg;
58136ff6393SMartin Habets
58236ff6393SMartin Habets if (bad_vf_index(efx, vf_evq) || bad_vf_index(efx, vf_rxq) ||
58336ff6393SMartin Habets vf_rxq >= VF_MAX_RX_QUEUES ||
58436ff6393SMartin Habets bad_buf_count(buf_count, EFX_MAX_DMAQ_SIZE)) {
58536ff6393SMartin Habets if (net_ratelimit())
58636ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
58736ff6393SMartin Habets "ERROR: Invalid INIT_RXQ from %s: rxq %d evq %d "
58836ff6393SMartin Habets "buf_count %d\n", vf->pci_name, vf_rxq,
58936ff6393SMartin Habets vf_evq, buf_count);
59036ff6393SMartin Habets return VFDI_RC_EINVAL;
59136ff6393SMartin Habets }
59236ff6393SMartin Habets if (__test_and_set_bit(req->u.init_rxq.index, vf->rxq_mask))
59336ff6393SMartin Habets ++vf->rxq_count;
59436ff6393SMartin Habets efx_siena_sriov_bufs(efx, buftbl, req->u.init_rxq.addr, buf_count);
59536ff6393SMartin Habets
59636ff6393SMartin Habets label = req->u.init_rxq.label & EFX_FIELD_MASK(FRF_AZ_RX_DESCQ_LABEL);
59736ff6393SMartin Habets EFX_POPULATE_OWORD_6(reg,
59836ff6393SMartin Habets FRF_AZ_RX_DESCQ_BUF_BASE_ID, buftbl,
59936ff6393SMartin Habets FRF_AZ_RX_DESCQ_EVQ_ID, abs_index(vf, vf_evq),
60036ff6393SMartin Habets FRF_AZ_RX_DESCQ_LABEL, label,
60136ff6393SMartin Habets FRF_AZ_RX_DESCQ_SIZE, __ffs(buf_count),
60236ff6393SMartin Habets FRF_AZ_RX_DESCQ_JUMBO,
60336ff6393SMartin Habets !!(req->u.init_rxq.flags &
60436ff6393SMartin Habets VFDI_RXQ_FLAG_SCATTER_EN),
60536ff6393SMartin Habets FRF_AZ_RX_DESCQ_EN, 1);
60636ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_RX_DESC_PTR_TBL,
60736ff6393SMartin Habets abs_index(vf, vf_rxq));
60836ff6393SMartin Habets
60936ff6393SMartin Habets return VFDI_RC_SUCCESS;
61036ff6393SMartin Habets }
61136ff6393SMartin Habets
efx_vfdi_init_txq(struct siena_vf * vf)61236ff6393SMartin Habets static int efx_vfdi_init_txq(struct siena_vf *vf)
61336ff6393SMartin Habets {
61436ff6393SMartin Habets struct efx_nic *efx = vf->efx;
61536ff6393SMartin Habets struct vfdi_req *req = vf->buf.addr;
61636ff6393SMartin Habets unsigned vf_txq = req->u.init_txq.index;
61736ff6393SMartin Habets unsigned vf_evq = req->u.init_txq.evq;
61836ff6393SMartin Habets unsigned buf_count = req->u.init_txq.buf_count;
61936ff6393SMartin Habets unsigned buftbl = EFX_BUFTBL_TXQ_BASE(vf, vf_txq);
62036ff6393SMartin Habets unsigned label, eth_filt_en;
62136ff6393SMartin Habets efx_oword_t reg;
62236ff6393SMartin Habets
62336ff6393SMartin Habets if (bad_vf_index(efx, vf_evq) || bad_vf_index(efx, vf_txq) ||
62436ff6393SMartin Habets vf_txq >= vf_max_tx_channels ||
62536ff6393SMartin Habets bad_buf_count(buf_count, EFX_MAX_DMAQ_SIZE)) {
62636ff6393SMartin Habets if (net_ratelimit())
62736ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
62836ff6393SMartin Habets "ERROR: Invalid INIT_TXQ from %s: txq %d evq %d "
62936ff6393SMartin Habets "buf_count %d\n", vf->pci_name, vf_txq,
63036ff6393SMartin Habets vf_evq, buf_count);
63136ff6393SMartin Habets return VFDI_RC_EINVAL;
63236ff6393SMartin Habets }
63336ff6393SMartin Habets
63436ff6393SMartin Habets mutex_lock(&vf->txq_lock);
63536ff6393SMartin Habets if (__test_and_set_bit(req->u.init_txq.index, vf->txq_mask))
63636ff6393SMartin Habets ++vf->txq_count;
63736ff6393SMartin Habets mutex_unlock(&vf->txq_lock);
63836ff6393SMartin Habets efx_siena_sriov_bufs(efx, buftbl, req->u.init_txq.addr, buf_count);
63936ff6393SMartin Habets
64036ff6393SMartin Habets eth_filt_en = vf->tx_filter_mode == VF_TX_FILTER_ON;
64136ff6393SMartin Habets
64236ff6393SMartin Habets label = req->u.init_txq.label & EFX_FIELD_MASK(FRF_AZ_TX_DESCQ_LABEL);
64336ff6393SMartin Habets EFX_POPULATE_OWORD_8(reg,
64436ff6393SMartin Habets FRF_CZ_TX_DPT_Q_MASK_WIDTH, min(efx->vi_scale, 1U),
64536ff6393SMartin Habets FRF_CZ_TX_DPT_ETH_FILT_EN, eth_filt_en,
64636ff6393SMartin Habets FRF_AZ_TX_DESCQ_EN, 1,
64736ff6393SMartin Habets FRF_AZ_TX_DESCQ_BUF_BASE_ID, buftbl,
64836ff6393SMartin Habets FRF_AZ_TX_DESCQ_EVQ_ID, abs_index(vf, vf_evq),
64936ff6393SMartin Habets FRF_AZ_TX_DESCQ_LABEL, label,
65036ff6393SMartin Habets FRF_AZ_TX_DESCQ_SIZE, __ffs(buf_count),
65136ff6393SMartin Habets FRF_BZ_TX_NON_IP_DROP_DIS, 1);
65236ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_TX_DESC_PTR_TBL,
65336ff6393SMartin Habets abs_index(vf, vf_txq));
65436ff6393SMartin Habets
65536ff6393SMartin Habets return VFDI_RC_SUCCESS;
65636ff6393SMartin Habets }
65736ff6393SMartin Habets
65836ff6393SMartin Habets /* Returns true when efx_vfdi_fini_all_queues should wake */
efx_vfdi_flush_wake(struct siena_vf * vf)65936ff6393SMartin Habets static bool efx_vfdi_flush_wake(struct siena_vf *vf)
66036ff6393SMartin Habets {
66136ff6393SMartin Habets /* Ensure that all updates are visible to efx_vfdi_fini_all_queues() */
66236ff6393SMartin Habets smp_mb();
66336ff6393SMartin Habets
66436ff6393SMartin Habets return (!vf->txq_count && !vf->rxq_count) ||
66536ff6393SMartin Habets atomic_read(&vf->rxq_retry_count);
66636ff6393SMartin Habets }
66736ff6393SMartin Habets
efx_vfdi_flush_clear(struct siena_vf * vf)66836ff6393SMartin Habets static void efx_vfdi_flush_clear(struct siena_vf *vf)
66936ff6393SMartin Habets {
67036ff6393SMartin Habets memset(vf->txq_mask, 0, sizeof(vf->txq_mask));
67136ff6393SMartin Habets vf->txq_count = 0;
67236ff6393SMartin Habets memset(vf->rxq_mask, 0, sizeof(vf->rxq_mask));
67336ff6393SMartin Habets vf->rxq_count = 0;
67436ff6393SMartin Habets memset(vf->rxq_retry_mask, 0, sizeof(vf->rxq_retry_mask));
67536ff6393SMartin Habets atomic_set(&vf->rxq_retry_count, 0);
67636ff6393SMartin Habets }
67736ff6393SMartin Habets
efx_vfdi_fini_all_queues(struct siena_vf * vf)67836ff6393SMartin Habets static int efx_vfdi_fini_all_queues(struct siena_vf *vf)
67936ff6393SMartin Habets {
68036ff6393SMartin Habets struct efx_nic *efx = vf->efx;
68136ff6393SMartin Habets efx_oword_t reg;
68236ff6393SMartin Habets unsigned count = efx_vf_size(efx);
68336ff6393SMartin Habets unsigned vf_offset = EFX_VI_BASE + vf->index * efx_vf_size(efx);
68436ff6393SMartin Habets unsigned timeout = HZ;
68536ff6393SMartin Habets unsigned index, rxqs_count;
68636ff6393SMartin Habets MCDI_DECLARE_BUF(inbuf, MC_CMD_FLUSH_RX_QUEUES_IN_LENMAX);
68736ff6393SMartin Habets int rc;
68836ff6393SMartin Habets
68936ff6393SMartin Habets BUILD_BUG_ON(VF_MAX_RX_QUEUES >
69036ff6393SMartin Habets MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
69136ff6393SMartin Habets
69236ff6393SMartin Habets rtnl_lock();
693956f2d86SMartin Habets efx_siena_prepare_flush(efx);
69436ff6393SMartin Habets rtnl_unlock();
69536ff6393SMartin Habets
69636ff6393SMartin Habets /* Flush all the initialized queues */
69736ff6393SMartin Habets rxqs_count = 0;
69836ff6393SMartin Habets for (index = 0; index < count; ++index) {
69936ff6393SMartin Habets if (test_bit(index, vf->txq_mask)) {
70036ff6393SMartin Habets EFX_POPULATE_OWORD_2(reg,
70136ff6393SMartin Habets FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
70236ff6393SMartin Habets FRF_AZ_TX_FLUSH_DESCQ,
70336ff6393SMartin Habets vf_offset + index);
70436ff6393SMartin Habets efx_writeo(efx, ®, FR_AZ_TX_FLUSH_DESCQ);
70536ff6393SMartin Habets }
70636ff6393SMartin Habets if (test_bit(index, vf->rxq_mask)) {
70736ff6393SMartin Habets MCDI_SET_ARRAY_DWORD(
70836ff6393SMartin Habets inbuf, FLUSH_RX_QUEUES_IN_QID_OFST,
70936ff6393SMartin Habets rxqs_count, vf_offset + index);
71036ff6393SMartin Habets rxqs_count++;
71136ff6393SMartin Habets }
71236ff6393SMartin Habets }
71336ff6393SMartin Habets
71436ff6393SMartin Habets atomic_set(&vf->rxq_retry_count, 0);
71536ff6393SMartin Habets while (timeout && (vf->rxq_count || vf->txq_count)) {
7164d49e5cdSMartin Habets rc = efx_siena_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, inbuf,
71736ff6393SMartin Habets MC_CMD_FLUSH_RX_QUEUES_IN_LEN(rxqs_count),
71836ff6393SMartin Habets NULL, 0, NULL);
71936ff6393SMartin Habets WARN_ON(rc < 0);
72036ff6393SMartin Habets
72136ff6393SMartin Habets timeout = wait_event_timeout(vf->flush_waitq,
72236ff6393SMartin Habets efx_vfdi_flush_wake(vf),
72336ff6393SMartin Habets timeout);
72436ff6393SMartin Habets rxqs_count = 0;
72536ff6393SMartin Habets for (index = 0; index < count; ++index) {
72636ff6393SMartin Habets if (test_and_clear_bit(index, vf->rxq_retry_mask)) {
72736ff6393SMartin Habets atomic_dec(&vf->rxq_retry_count);
72836ff6393SMartin Habets MCDI_SET_ARRAY_DWORD(
72936ff6393SMartin Habets inbuf, FLUSH_RX_QUEUES_IN_QID_OFST,
73036ff6393SMartin Habets rxqs_count, vf_offset + index);
73136ff6393SMartin Habets rxqs_count++;
73236ff6393SMartin Habets }
73336ff6393SMartin Habets }
73436ff6393SMartin Habets }
73536ff6393SMartin Habets
73636ff6393SMartin Habets rtnl_lock();
73736ff6393SMartin Habets siena_finish_flush(efx);
73836ff6393SMartin Habets rtnl_unlock();
73936ff6393SMartin Habets
74036ff6393SMartin Habets /* Irrespective of success/failure, fini the queues */
74136ff6393SMartin Habets EFX_ZERO_OWORD(reg);
74236ff6393SMartin Habets for (index = 0; index < count; ++index) {
74336ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_RX_DESC_PTR_TBL,
74436ff6393SMartin Habets vf_offset + index);
74536ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_TX_DESC_PTR_TBL,
74636ff6393SMartin Habets vf_offset + index);
74736ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_EVQ_PTR_TBL,
74836ff6393SMartin Habets vf_offset + index);
74936ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_TIMER_TBL,
75036ff6393SMartin Habets vf_offset + index);
75136ff6393SMartin Habets }
75236ff6393SMartin Habets efx_siena_sriov_bufs(efx, vf->buftbl_base, NULL,
75336ff6393SMartin Habets EFX_VF_BUFTBL_PER_VI * efx_vf_size(efx));
75436ff6393SMartin Habets efx_vfdi_flush_clear(vf);
75536ff6393SMartin Habets
75636ff6393SMartin Habets vf->evq0_count = 0;
75736ff6393SMartin Habets
75836ff6393SMartin Habets return timeout ? 0 : VFDI_RC_ETIMEDOUT;
75936ff6393SMartin Habets }
76036ff6393SMartin Habets
efx_vfdi_insert_filter(struct siena_vf * vf)76136ff6393SMartin Habets static int efx_vfdi_insert_filter(struct siena_vf *vf)
76236ff6393SMartin Habets {
76336ff6393SMartin Habets struct efx_nic *efx = vf->efx;
76436ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
76536ff6393SMartin Habets struct vfdi_req *req = vf->buf.addr;
76636ff6393SMartin Habets unsigned vf_rxq = req->u.mac_filter.rxq;
76736ff6393SMartin Habets unsigned flags;
76836ff6393SMartin Habets
76936ff6393SMartin Habets if (bad_vf_index(efx, vf_rxq) || vf->rx_filtering) {
77036ff6393SMartin Habets if (net_ratelimit())
77136ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
77236ff6393SMartin Habets "ERROR: Invalid INSERT_FILTER from %s: rxq %d "
77336ff6393SMartin Habets "flags 0x%x\n", vf->pci_name, vf_rxq,
77436ff6393SMartin Habets req->u.mac_filter.flags);
77536ff6393SMartin Habets return VFDI_RC_EINVAL;
77636ff6393SMartin Habets }
77736ff6393SMartin Habets
77836ff6393SMartin Habets flags = 0;
77936ff6393SMartin Habets if (req->u.mac_filter.flags & VFDI_MAC_FILTER_FLAG_RSS)
78036ff6393SMartin Habets flags |= EFX_FILTER_FLAG_RX_RSS;
78136ff6393SMartin Habets if (req->u.mac_filter.flags & VFDI_MAC_FILTER_FLAG_SCATTER)
78236ff6393SMartin Habets flags |= EFX_FILTER_FLAG_RX_SCATTER;
78336ff6393SMartin Habets vf->rx_filter_flags = flags;
78436ff6393SMartin Habets vf->rx_filter_qid = vf_rxq;
78536ff6393SMartin Habets vf->rx_filtering = true;
78636ff6393SMartin Habets
78736ff6393SMartin Habets efx_siena_sriov_reset_rx_filter(vf);
78836ff6393SMartin Habets queue_work(vfdi_workqueue, &nic_data->peer_work);
78936ff6393SMartin Habets
79036ff6393SMartin Habets return VFDI_RC_SUCCESS;
79136ff6393SMartin Habets }
79236ff6393SMartin Habets
efx_vfdi_remove_all_filters(struct siena_vf * vf)79336ff6393SMartin Habets static int efx_vfdi_remove_all_filters(struct siena_vf *vf)
79436ff6393SMartin Habets {
79536ff6393SMartin Habets struct efx_nic *efx = vf->efx;
79636ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
79736ff6393SMartin Habets
79836ff6393SMartin Habets vf->rx_filtering = false;
79936ff6393SMartin Habets efx_siena_sriov_reset_rx_filter(vf);
80036ff6393SMartin Habets queue_work(vfdi_workqueue, &nic_data->peer_work);
80136ff6393SMartin Habets
80236ff6393SMartin Habets return VFDI_RC_SUCCESS;
80336ff6393SMartin Habets }
80436ff6393SMartin Habets
efx_vfdi_set_status_page(struct siena_vf * vf)80536ff6393SMartin Habets static int efx_vfdi_set_status_page(struct siena_vf *vf)
80636ff6393SMartin Habets {
80736ff6393SMartin Habets struct efx_nic *efx = vf->efx;
80836ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
80936ff6393SMartin Habets struct vfdi_req *req = vf->buf.addr;
81036ff6393SMartin Habets u64 page_count = req->u.set_status_page.peer_page_count;
81136ff6393SMartin Habets u64 max_page_count =
81236ff6393SMartin Habets (EFX_PAGE_SIZE -
81336ff6393SMartin Habets offsetof(struct vfdi_req, u.set_status_page.peer_page_addr[0]))
81436ff6393SMartin Habets / sizeof(req->u.set_status_page.peer_page_addr[0]);
81536ff6393SMartin Habets
81636ff6393SMartin Habets if (!req->u.set_status_page.dma_addr || page_count > max_page_count) {
81736ff6393SMartin Habets if (net_ratelimit())
81836ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
81936ff6393SMartin Habets "ERROR: Invalid SET_STATUS_PAGE from %s\n",
82036ff6393SMartin Habets vf->pci_name);
82136ff6393SMartin Habets return VFDI_RC_EINVAL;
82236ff6393SMartin Habets }
82336ff6393SMartin Habets
82436ff6393SMartin Habets mutex_lock(&nic_data->local_lock);
82536ff6393SMartin Habets mutex_lock(&vf->status_lock);
82636ff6393SMartin Habets vf->status_addr = req->u.set_status_page.dma_addr;
82736ff6393SMartin Habets
82836ff6393SMartin Habets kfree(vf->peer_page_addrs);
82936ff6393SMartin Habets vf->peer_page_addrs = NULL;
83036ff6393SMartin Habets vf->peer_page_count = 0;
83136ff6393SMartin Habets
83236ff6393SMartin Habets if (page_count) {
83336ff6393SMartin Habets vf->peer_page_addrs = kcalloc(page_count, sizeof(u64),
83436ff6393SMartin Habets GFP_KERNEL);
83536ff6393SMartin Habets if (vf->peer_page_addrs) {
83636ff6393SMartin Habets memcpy(vf->peer_page_addrs,
83736ff6393SMartin Habets req->u.set_status_page.peer_page_addr,
83836ff6393SMartin Habets page_count * sizeof(u64));
83936ff6393SMartin Habets vf->peer_page_count = page_count;
84036ff6393SMartin Habets }
84136ff6393SMartin Habets }
84236ff6393SMartin Habets
84336ff6393SMartin Habets __efx_siena_sriov_push_vf_status(vf);
84436ff6393SMartin Habets mutex_unlock(&vf->status_lock);
84536ff6393SMartin Habets mutex_unlock(&nic_data->local_lock);
84636ff6393SMartin Habets
84736ff6393SMartin Habets return VFDI_RC_SUCCESS;
84836ff6393SMartin Habets }
84936ff6393SMartin Habets
efx_vfdi_clear_status_page(struct siena_vf * vf)85036ff6393SMartin Habets static int efx_vfdi_clear_status_page(struct siena_vf *vf)
85136ff6393SMartin Habets {
85236ff6393SMartin Habets mutex_lock(&vf->status_lock);
85336ff6393SMartin Habets vf->status_addr = 0;
85436ff6393SMartin Habets mutex_unlock(&vf->status_lock);
85536ff6393SMartin Habets
85636ff6393SMartin Habets return VFDI_RC_SUCCESS;
85736ff6393SMartin Habets }
85836ff6393SMartin Habets
85936ff6393SMartin Habets typedef int (*efx_vfdi_op_t)(struct siena_vf *vf);
86036ff6393SMartin Habets
86136ff6393SMartin Habets static const efx_vfdi_op_t vfdi_ops[VFDI_OP_LIMIT] = {
86236ff6393SMartin Habets [VFDI_OP_INIT_EVQ] = efx_vfdi_init_evq,
86336ff6393SMartin Habets [VFDI_OP_INIT_TXQ] = efx_vfdi_init_txq,
86436ff6393SMartin Habets [VFDI_OP_INIT_RXQ] = efx_vfdi_init_rxq,
86536ff6393SMartin Habets [VFDI_OP_FINI_ALL_QUEUES] = efx_vfdi_fini_all_queues,
86636ff6393SMartin Habets [VFDI_OP_INSERT_FILTER] = efx_vfdi_insert_filter,
86736ff6393SMartin Habets [VFDI_OP_REMOVE_ALL_FILTERS] = efx_vfdi_remove_all_filters,
86836ff6393SMartin Habets [VFDI_OP_SET_STATUS_PAGE] = efx_vfdi_set_status_page,
86936ff6393SMartin Habets [VFDI_OP_CLEAR_STATUS_PAGE] = efx_vfdi_clear_status_page,
87036ff6393SMartin Habets };
87136ff6393SMartin Habets
efx_siena_sriov_vfdi(struct work_struct * work)87236ff6393SMartin Habets static void efx_siena_sriov_vfdi(struct work_struct *work)
87336ff6393SMartin Habets {
87436ff6393SMartin Habets struct siena_vf *vf = container_of(work, struct siena_vf, req);
87536ff6393SMartin Habets struct efx_nic *efx = vf->efx;
87636ff6393SMartin Habets struct vfdi_req *req = vf->buf.addr;
87736ff6393SMartin Habets struct efx_memcpy_req copy[2];
87836ff6393SMartin Habets int rc;
87936ff6393SMartin Habets
88036ff6393SMartin Habets /* Copy this page into the local address space */
88136ff6393SMartin Habets memset(copy, '\0', sizeof(copy));
88236ff6393SMartin Habets copy[0].from_rid = vf->pci_rid;
88336ff6393SMartin Habets copy[0].from_addr = vf->req_addr;
88436ff6393SMartin Habets copy[0].to_rid = efx->pci_dev->devfn;
88536ff6393SMartin Habets copy[0].to_addr = vf->buf.dma_addr;
88636ff6393SMartin Habets copy[0].length = EFX_PAGE_SIZE;
88736ff6393SMartin Habets rc = efx_siena_sriov_memcpy(efx, copy, 1);
88836ff6393SMartin Habets if (rc) {
88936ff6393SMartin Habets /* If we can't get the request, we can't reply to the caller */
89036ff6393SMartin Habets if (net_ratelimit())
89136ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
89236ff6393SMartin Habets "ERROR: Unable to fetch VFDI request from %s rc %d\n",
89336ff6393SMartin Habets vf->pci_name, -rc);
89436ff6393SMartin Habets vf->busy = false;
89536ff6393SMartin Habets return;
89636ff6393SMartin Habets }
89736ff6393SMartin Habets
89836ff6393SMartin Habets if (req->op < VFDI_OP_LIMIT && vfdi_ops[req->op] != NULL) {
89936ff6393SMartin Habets rc = vfdi_ops[req->op](vf);
90036ff6393SMartin Habets if (rc == 0) {
90136ff6393SMartin Habets netif_dbg(efx, hw, efx->net_dev,
90236ff6393SMartin Habets "vfdi request %d from %s ok\n",
90336ff6393SMartin Habets req->op, vf->pci_name);
90436ff6393SMartin Habets }
90536ff6393SMartin Habets } else {
90636ff6393SMartin Habets netif_dbg(efx, hw, efx->net_dev,
90736ff6393SMartin Habets "ERROR: Unrecognised request %d from VF %s addr "
90836ff6393SMartin Habets "%llx\n", req->op, vf->pci_name,
90936ff6393SMartin Habets (unsigned long long)vf->req_addr);
91036ff6393SMartin Habets rc = VFDI_RC_EOPNOTSUPP;
91136ff6393SMartin Habets }
91236ff6393SMartin Habets
91336ff6393SMartin Habets /* Allow subsequent VF requests */
91436ff6393SMartin Habets vf->busy = false;
91536ff6393SMartin Habets smp_wmb();
91636ff6393SMartin Habets
91736ff6393SMartin Habets /* Respond to the request */
91836ff6393SMartin Habets req->rc = rc;
91936ff6393SMartin Habets req->op = VFDI_OP_RESPONSE;
92036ff6393SMartin Habets
92136ff6393SMartin Habets memset(copy, '\0', sizeof(copy));
92236ff6393SMartin Habets copy[0].from_buf = &req->rc;
92336ff6393SMartin Habets copy[0].to_rid = vf->pci_rid;
92436ff6393SMartin Habets copy[0].to_addr = vf->req_addr + offsetof(struct vfdi_req, rc);
92536ff6393SMartin Habets copy[0].length = sizeof(req->rc);
92636ff6393SMartin Habets copy[1].from_buf = &req->op;
92736ff6393SMartin Habets copy[1].to_rid = vf->pci_rid;
92836ff6393SMartin Habets copy[1].to_addr = vf->req_addr + offsetof(struct vfdi_req, op);
92936ff6393SMartin Habets copy[1].length = sizeof(req->op);
93036ff6393SMartin Habets
93136ff6393SMartin Habets (void)efx_siena_sriov_memcpy(efx, copy, ARRAY_SIZE(copy));
93236ff6393SMartin Habets }
93336ff6393SMartin Habets
93436ff6393SMartin Habets
93536ff6393SMartin Habets
93636ff6393SMartin Habets /* After a reset the event queues inside the guests no longer exist. Fill the
93736ff6393SMartin Habets * event ring in guest memory with VFDI reset events, then (re-initialise) the
93836ff6393SMartin Habets * event queue to raise an interrupt. The guest driver will then recover.
93936ff6393SMartin Habets */
94036ff6393SMartin Habets
efx_siena_sriov_reset_vf(struct siena_vf * vf,struct efx_buffer * buffer)94136ff6393SMartin Habets static void efx_siena_sriov_reset_vf(struct siena_vf *vf,
94236ff6393SMartin Habets struct efx_buffer *buffer)
94336ff6393SMartin Habets {
94436ff6393SMartin Habets struct efx_nic *efx = vf->efx;
94536ff6393SMartin Habets struct efx_memcpy_req copy_req[4];
94636ff6393SMartin Habets efx_qword_t event;
94736ff6393SMartin Habets unsigned int pos, count, k, buftbl, abs_evq;
94836ff6393SMartin Habets efx_oword_t reg;
94936ff6393SMartin Habets efx_dword_t ptr;
95036ff6393SMartin Habets int rc;
95136ff6393SMartin Habets
95236ff6393SMartin Habets BUG_ON(buffer->len != EFX_PAGE_SIZE);
95336ff6393SMartin Habets
95436ff6393SMartin Habets if (!vf->evq0_count)
95536ff6393SMartin Habets return;
95636ff6393SMartin Habets BUG_ON(vf->evq0_count & (vf->evq0_count - 1));
95736ff6393SMartin Habets
95836ff6393SMartin Habets mutex_lock(&vf->status_lock);
95936ff6393SMartin Habets EFX_POPULATE_QWORD_3(event,
96036ff6393SMartin Habets FSF_AZ_EV_CODE, FSE_CZ_EV_CODE_USER_EV,
96136ff6393SMartin Habets VFDI_EV_SEQ, vf->msg_seqno,
96236ff6393SMartin Habets VFDI_EV_TYPE, VFDI_EV_TYPE_RESET);
96336ff6393SMartin Habets vf->msg_seqno++;
96436ff6393SMartin Habets for (pos = 0; pos < EFX_PAGE_SIZE; pos += sizeof(event))
96536ff6393SMartin Habets memcpy(buffer->addr + pos, &event, sizeof(event));
96636ff6393SMartin Habets
96736ff6393SMartin Habets for (pos = 0; pos < vf->evq0_count; pos += count) {
96836ff6393SMartin Habets count = min_t(unsigned, vf->evq0_count - pos,
96936ff6393SMartin Habets ARRAY_SIZE(copy_req));
97036ff6393SMartin Habets for (k = 0; k < count; k++) {
97136ff6393SMartin Habets copy_req[k].from_buf = NULL;
97236ff6393SMartin Habets copy_req[k].from_rid = efx->pci_dev->devfn;
97336ff6393SMartin Habets copy_req[k].from_addr = buffer->dma_addr;
97436ff6393SMartin Habets copy_req[k].to_rid = vf->pci_rid;
97536ff6393SMartin Habets copy_req[k].to_addr = vf->evq0_addrs[pos + k];
97636ff6393SMartin Habets copy_req[k].length = EFX_PAGE_SIZE;
97736ff6393SMartin Habets }
97836ff6393SMartin Habets rc = efx_siena_sriov_memcpy(efx, copy_req, count);
97936ff6393SMartin Habets if (rc) {
98036ff6393SMartin Habets if (net_ratelimit())
98136ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
98236ff6393SMartin Habets "ERROR: Unable to notify %s of reset"
98336ff6393SMartin Habets ": %d\n", vf->pci_name, -rc);
98436ff6393SMartin Habets break;
98536ff6393SMartin Habets }
98636ff6393SMartin Habets }
98736ff6393SMartin Habets
98836ff6393SMartin Habets /* Reinitialise, arm and trigger evq0 */
98936ff6393SMartin Habets abs_evq = abs_index(vf, 0);
99036ff6393SMartin Habets buftbl = EFX_BUFTBL_EVQ_BASE(vf, 0);
99136ff6393SMartin Habets efx_siena_sriov_bufs(efx, buftbl, vf->evq0_addrs, vf->evq0_count);
99236ff6393SMartin Habets
99336ff6393SMartin Habets EFX_POPULATE_OWORD_3(reg,
99436ff6393SMartin Habets FRF_CZ_TIMER_Q_EN, 1,
99536ff6393SMartin Habets FRF_CZ_HOST_NOTIFY_MODE, 0,
99636ff6393SMartin Habets FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS);
99736ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_TIMER_TBL, abs_evq);
99836ff6393SMartin Habets EFX_POPULATE_OWORD_3(reg,
99936ff6393SMartin Habets FRF_AZ_EVQ_EN, 1,
100036ff6393SMartin Habets FRF_AZ_EVQ_SIZE, __ffs(vf->evq0_count),
100136ff6393SMartin Habets FRF_AZ_EVQ_BUF_BASE_ID, buftbl);
100236ff6393SMartin Habets efx_writeo_table(efx, ®, FR_BZ_EVQ_PTR_TBL, abs_evq);
100336ff6393SMartin Habets EFX_POPULATE_DWORD_1(ptr, FRF_AZ_EVQ_RPTR, 0);
100436ff6393SMartin Habets efx_writed(efx, &ptr, FR_BZ_EVQ_RPTR + FR_BZ_EVQ_RPTR_STEP * abs_evq);
100536ff6393SMartin Habets
100636ff6393SMartin Habets mutex_unlock(&vf->status_lock);
100736ff6393SMartin Habets }
100836ff6393SMartin Habets
efx_siena_sriov_reset_vf_work(struct work_struct * work)100936ff6393SMartin Habets static void efx_siena_sriov_reset_vf_work(struct work_struct *work)
101036ff6393SMartin Habets {
101136ff6393SMartin Habets struct siena_vf *vf = container_of(work, struct siena_vf, req);
101236ff6393SMartin Habets struct efx_nic *efx = vf->efx;
101336ff6393SMartin Habets struct efx_buffer buf;
101436ff6393SMartin Habets
1015*c8443b69SMartin Habets if (!efx_siena_alloc_buffer(efx, &buf, EFX_PAGE_SIZE, GFP_NOIO)) {
101636ff6393SMartin Habets efx_siena_sriov_reset_vf(vf, &buf);
1017*c8443b69SMartin Habets efx_siena_free_buffer(efx, &buf);
101836ff6393SMartin Habets }
101936ff6393SMartin Habets }
102036ff6393SMartin Habets
efx_siena_sriov_handle_no_channel(struct efx_nic * efx)102136ff6393SMartin Habets static void efx_siena_sriov_handle_no_channel(struct efx_nic *efx)
102236ff6393SMartin Habets {
102336ff6393SMartin Habets netif_err(efx, drv, efx->net_dev,
102436ff6393SMartin Habets "ERROR: IOV requires MSI-X and 1 additional interrupt"
102536ff6393SMartin Habets "vector. IOV disabled\n");
102636ff6393SMartin Habets efx->vf_count = 0;
102736ff6393SMartin Habets }
102836ff6393SMartin Habets
efx_siena_sriov_probe_channel(struct efx_channel * channel)102936ff6393SMartin Habets static int efx_siena_sriov_probe_channel(struct efx_channel *channel)
103036ff6393SMartin Habets {
103136ff6393SMartin Habets struct siena_nic_data *nic_data = channel->efx->nic_data;
103236ff6393SMartin Habets nic_data->vfdi_channel = channel;
103336ff6393SMartin Habets
103436ff6393SMartin Habets return 0;
103536ff6393SMartin Habets }
103636ff6393SMartin Habets
103736ff6393SMartin Habets static void
efx_siena_sriov_get_channel_name(struct efx_channel * channel,char * buf,size_t len)103836ff6393SMartin Habets efx_siena_sriov_get_channel_name(struct efx_channel *channel,
103936ff6393SMartin Habets char *buf, size_t len)
104036ff6393SMartin Habets {
104136ff6393SMartin Habets snprintf(buf, len, "%s-iov", channel->efx->name);
104236ff6393SMartin Habets }
104336ff6393SMartin Habets
104436ff6393SMartin Habets static const struct efx_channel_type efx_siena_sriov_channel_type = {
104536ff6393SMartin Habets .handle_no_channel = efx_siena_sriov_handle_no_channel,
104636ff6393SMartin Habets .pre_probe = efx_siena_sriov_probe_channel,
104771ad88f6SMartin Habets .post_remove = efx_siena_channel_dummy_op_void,
104836ff6393SMartin Habets .get_name = efx_siena_sriov_get_channel_name,
104936ff6393SMartin Habets /* no copy operation; channel must not be reallocated */
105036ff6393SMartin Habets .keep_eventq = true,
105136ff6393SMartin Habets };
105236ff6393SMartin Habets
efx_siena_sriov_probe(struct efx_nic * efx)105336ff6393SMartin Habets void efx_siena_sriov_probe(struct efx_nic *efx)
105436ff6393SMartin Habets {
105536ff6393SMartin Habets unsigned count;
105636ff6393SMartin Habets
105736ff6393SMartin Habets if (!max_vfs)
105836ff6393SMartin Habets return;
105936ff6393SMartin Habets
106036ff6393SMartin Habets if (efx_siena_sriov_cmd(efx, false, &efx->vi_scale, &count)) {
106136ff6393SMartin Habets pci_info(efx->pci_dev, "no SR-IOV VFs probed\n");
106236ff6393SMartin Habets return;
106336ff6393SMartin Habets }
106436ff6393SMartin Habets if (count > 0 && count > max_vfs)
106536ff6393SMartin Habets count = max_vfs;
106636ff6393SMartin Habets
106736ff6393SMartin Habets /* efx_nic_dimension_resources() will reduce vf_count as appopriate */
106836ff6393SMartin Habets efx->vf_count = count;
106936ff6393SMartin Habets
107036ff6393SMartin Habets efx->extra_channel_type[EFX_EXTRA_CHANNEL_IOV] = &efx_siena_sriov_channel_type;
107136ff6393SMartin Habets }
107236ff6393SMartin Habets
107336ff6393SMartin Habets /* Copy the list of individual addresses into the vfdi_status.peers
107436ff6393SMartin Habets * array and auxiliary pages, protected by %local_lock. Drop that lock
107536ff6393SMartin Habets * and then broadcast the address list to every VF.
107636ff6393SMartin Habets */
efx_siena_sriov_peer_work(struct work_struct * data)107736ff6393SMartin Habets static void efx_siena_sriov_peer_work(struct work_struct *data)
107836ff6393SMartin Habets {
107936ff6393SMartin Habets struct siena_nic_data *nic_data = container_of(data,
108036ff6393SMartin Habets struct siena_nic_data,
108136ff6393SMartin Habets peer_work);
108236ff6393SMartin Habets struct efx_nic *efx = nic_data->efx;
108336ff6393SMartin Habets struct vfdi_status *vfdi_status = nic_data->vfdi_status.addr;
108436ff6393SMartin Habets struct siena_vf *vf;
108536ff6393SMartin Habets struct efx_local_addr *local_addr;
108636ff6393SMartin Habets struct vfdi_endpoint *peer;
108736ff6393SMartin Habets struct efx_endpoint_page *epp;
108836ff6393SMartin Habets struct list_head pages;
108936ff6393SMartin Habets unsigned int peer_space;
109036ff6393SMartin Habets unsigned int peer_count;
109136ff6393SMartin Habets unsigned int pos;
109236ff6393SMartin Habets
109336ff6393SMartin Habets mutex_lock(&nic_data->local_lock);
109436ff6393SMartin Habets
109536ff6393SMartin Habets /* Move the existing peer pages off %local_page_list */
109636ff6393SMartin Habets INIT_LIST_HEAD(&pages);
109736ff6393SMartin Habets list_splice_tail_init(&nic_data->local_page_list, &pages);
109836ff6393SMartin Habets
109936ff6393SMartin Habets /* Populate the VF addresses starting from entry 1 (entry 0 is
110036ff6393SMartin Habets * the PF address)
110136ff6393SMartin Habets */
110236ff6393SMartin Habets peer = vfdi_status->peers + 1;
110336ff6393SMartin Habets peer_space = ARRAY_SIZE(vfdi_status->peers) - 1;
110436ff6393SMartin Habets peer_count = 1;
110536ff6393SMartin Habets for (pos = 0; pos < efx->vf_count; ++pos) {
110636ff6393SMartin Habets vf = nic_data->vf + pos;
110736ff6393SMartin Habets
110836ff6393SMartin Habets mutex_lock(&vf->status_lock);
110936ff6393SMartin Habets if (vf->rx_filtering && !is_zero_ether_addr(vf->addr.mac_addr)) {
111036ff6393SMartin Habets *peer++ = vf->addr;
111136ff6393SMartin Habets ++peer_count;
111236ff6393SMartin Habets --peer_space;
111336ff6393SMartin Habets BUG_ON(peer_space == 0);
111436ff6393SMartin Habets }
111536ff6393SMartin Habets mutex_unlock(&vf->status_lock);
111636ff6393SMartin Habets }
111736ff6393SMartin Habets
111836ff6393SMartin Habets /* Fill the remaining addresses */
111936ff6393SMartin Habets list_for_each_entry(local_addr, &nic_data->local_addr_list, link) {
112036ff6393SMartin Habets ether_addr_copy(peer->mac_addr, local_addr->addr);
112136ff6393SMartin Habets peer->tci = 0;
112236ff6393SMartin Habets ++peer;
112336ff6393SMartin Habets ++peer_count;
112436ff6393SMartin Habets if (--peer_space == 0) {
112536ff6393SMartin Habets if (list_empty(&pages)) {
112636ff6393SMartin Habets epp = kmalloc(sizeof(*epp), GFP_KERNEL);
112736ff6393SMartin Habets if (!epp)
112836ff6393SMartin Habets break;
112936ff6393SMartin Habets epp->ptr = dma_alloc_coherent(
113036ff6393SMartin Habets &efx->pci_dev->dev, EFX_PAGE_SIZE,
113136ff6393SMartin Habets &epp->addr, GFP_KERNEL);
113236ff6393SMartin Habets if (!epp->ptr) {
113336ff6393SMartin Habets kfree(epp);
113436ff6393SMartin Habets break;
113536ff6393SMartin Habets }
113636ff6393SMartin Habets } else {
113736ff6393SMartin Habets epp = list_first_entry(
113836ff6393SMartin Habets &pages, struct efx_endpoint_page, link);
113936ff6393SMartin Habets list_del(&epp->link);
114036ff6393SMartin Habets }
114136ff6393SMartin Habets
114236ff6393SMartin Habets list_add_tail(&epp->link, &nic_data->local_page_list);
114336ff6393SMartin Habets peer = (struct vfdi_endpoint *)epp->ptr;
114436ff6393SMartin Habets peer_space = EFX_PAGE_SIZE / sizeof(struct vfdi_endpoint);
114536ff6393SMartin Habets }
114636ff6393SMartin Habets }
114736ff6393SMartin Habets vfdi_status->peer_count = peer_count;
114836ff6393SMartin Habets mutex_unlock(&nic_data->local_lock);
114936ff6393SMartin Habets
115036ff6393SMartin Habets /* Free any now unused endpoint pages */
115136ff6393SMartin Habets while (!list_empty(&pages)) {
115236ff6393SMartin Habets epp = list_first_entry(
115336ff6393SMartin Habets &pages, struct efx_endpoint_page, link);
115436ff6393SMartin Habets list_del(&epp->link);
115536ff6393SMartin Habets dma_free_coherent(&efx->pci_dev->dev, EFX_PAGE_SIZE,
115636ff6393SMartin Habets epp->ptr, epp->addr);
115736ff6393SMartin Habets kfree(epp);
115836ff6393SMartin Habets }
115936ff6393SMartin Habets
116036ff6393SMartin Habets /* Finally, push the pages */
116136ff6393SMartin Habets for (pos = 0; pos < efx->vf_count; ++pos) {
116236ff6393SMartin Habets vf = nic_data->vf + pos;
116336ff6393SMartin Habets
116436ff6393SMartin Habets mutex_lock(&vf->status_lock);
116536ff6393SMartin Habets if (vf->status_addr)
116636ff6393SMartin Habets __efx_siena_sriov_push_vf_status(vf);
116736ff6393SMartin Habets mutex_unlock(&vf->status_lock);
116836ff6393SMartin Habets }
116936ff6393SMartin Habets }
117036ff6393SMartin Habets
efx_siena_sriov_free_local(struct efx_nic * efx)117136ff6393SMartin Habets static void efx_siena_sriov_free_local(struct efx_nic *efx)
117236ff6393SMartin Habets {
117336ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
117436ff6393SMartin Habets struct efx_local_addr *local_addr;
117536ff6393SMartin Habets struct efx_endpoint_page *epp;
117636ff6393SMartin Habets
117736ff6393SMartin Habets while (!list_empty(&nic_data->local_addr_list)) {
117836ff6393SMartin Habets local_addr = list_first_entry(&nic_data->local_addr_list,
117936ff6393SMartin Habets struct efx_local_addr, link);
118036ff6393SMartin Habets list_del(&local_addr->link);
118136ff6393SMartin Habets kfree(local_addr);
118236ff6393SMartin Habets }
118336ff6393SMartin Habets
118436ff6393SMartin Habets while (!list_empty(&nic_data->local_page_list)) {
118536ff6393SMartin Habets epp = list_first_entry(&nic_data->local_page_list,
118636ff6393SMartin Habets struct efx_endpoint_page, link);
118736ff6393SMartin Habets list_del(&epp->link);
118836ff6393SMartin Habets dma_free_coherent(&efx->pci_dev->dev, EFX_PAGE_SIZE,
118936ff6393SMartin Habets epp->ptr, epp->addr);
119036ff6393SMartin Habets kfree(epp);
119136ff6393SMartin Habets }
119236ff6393SMartin Habets }
119336ff6393SMartin Habets
efx_siena_sriov_vf_alloc(struct efx_nic * efx)119436ff6393SMartin Habets static int efx_siena_sriov_vf_alloc(struct efx_nic *efx)
119536ff6393SMartin Habets {
119636ff6393SMartin Habets unsigned index;
119736ff6393SMartin Habets struct siena_vf *vf;
119836ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
119936ff6393SMartin Habets
120036ff6393SMartin Habets nic_data->vf = kcalloc(efx->vf_count, sizeof(*nic_data->vf),
120136ff6393SMartin Habets GFP_KERNEL);
120236ff6393SMartin Habets if (!nic_data->vf)
120336ff6393SMartin Habets return -ENOMEM;
120436ff6393SMartin Habets
120536ff6393SMartin Habets for (index = 0; index < efx->vf_count; ++index) {
120636ff6393SMartin Habets vf = nic_data->vf + index;
120736ff6393SMartin Habets
120836ff6393SMartin Habets vf->efx = efx;
120936ff6393SMartin Habets vf->index = index;
121036ff6393SMartin Habets vf->rx_filter_id = -1;
121136ff6393SMartin Habets vf->tx_filter_mode = VF_TX_FILTER_AUTO;
121236ff6393SMartin Habets vf->tx_filter_id = -1;
121336ff6393SMartin Habets INIT_WORK(&vf->req, efx_siena_sriov_vfdi);
121436ff6393SMartin Habets INIT_WORK(&vf->reset_work, efx_siena_sriov_reset_vf_work);
121536ff6393SMartin Habets init_waitqueue_head(&vf->flush_waitq);
121636ff6393SMartin Habets mutex_init(&vf->status_lock);
121736ff6393SMartin Habets mutex_init(&vf->txq_lock);
121836ff6393SMartin Habets }
121936ff6393SMartin Habets
122036ff6393SMartin Habets return 0;
122136ff6393SMartin Habets }
122236ff6393SMartin Habets
efx_siena_sriov_vfs_fini(struct efx_nic * efx)122336ff6393SMartin Habets static void efx_siena_sriov_vfs_fini(struct efx_nic *efx)
122436ff6393SMartin Habets {
122536ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
122636ff6393SMartin Habets struct siena_vf *vf;
122736ff6393SMartin Habets unsigned int pos;
122836ff6393SMartin Habets
122936ff6393SMartin Habets for (pos = 0; pos < efx->vf_count; ++pos) {
123036ff6393SMartin Habets vf = nic_data->vf + pos;
123136ff6393SMartin Habets
1232*c8443b69SMartin Habets efx_siena_free_buffer(efx, &vf->buf);
123336ff6393SMartin Habets kfree(vf->peer_page_addrs);
123436ff6393SMartin Habets vf->peer_page_addrs = NULL;
123536ff6393SMartin Habets vf->peer_page_count = 0;
123636ff6393SMartin Habets
123736ff6393SMartin Habets vf->evq0_count = 0;
123836ff6393SMartin Habets }
123936ff6393SMartin Habets }
124036ff6393SMartin Habets
efx_siena_sriov_vfs_init(struct efx_nic * efx)124136ff6393SMartin Habets static int efx_siena_sriov_vfs_init(struct efx_nic *efx)
124236ff6393SMartin Habets {
124336ff6393SMartin Habets struct pci_dev *pci_dev = efx->pci_dev;
124436ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
124536ff6393SMartin Habets unsigned index, devfn, sriov, buftbl_base;
124636ff6393SMartin Habets u16 offset, stride;
124736ff6393SMartin Habets struct siena_vf *vf;
124836ff6393SMartin Habets int rc;
124936ff6393SMartin Habets
125036ff6393SMartin Habets sriov = pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV);
125136ff6393SMartin Habets if (!sriov)
125236ff6393SMartin Habets return -ENOENT;
125336ff6393SMartin Habets
125436ff6393SMartin Habets pci_read_config_word(pci_dev, sriov + PCI_SRIOV_VF_OFFSET, &offset);
125536ff6393SMartin Habets pci_read_config_word(pci_dev, sriov + PCI_SRIOV_VF_STRIDE, &stride);
125636ff6393SMartin Habets
125736ff6393SMartin Habets buftbl_base = nic_data->vf_buftbl_base;
125836ff6393SMartin Habets devfn = pci_dev->devfn + offset;
125936ff6393SMartin Habets for (index = 0; index < efx->vf_count; ++index) {
126036ff6393SMartin Habets vf = nic_data->vf + index;
126136ff6393SMartin Habets
126236ff6393SMartin Habets /* Reserve buffer entries */
126336ff6393SMartin Habets vf->buftbl_base = buftbl_base;
126436ff6393SMartin Habets buftbl_base += EFX_VF_BUFTBL_PER_VI * efx_vf_size(efx);
126536ff6393SMartin Habets
126636ff6393SMartin Habets vf->pci_rid = devfn;
126736ff6393SMartin Habets snprintf(vf->pci_name, sizeof(vf->pci_name),
126836ff6393SMartin Habets "%04x:%02x:%02x.%d",
126936ff6393SMartin Habets pci_domain_nr(pci_dev->bus), pci_dev->bus->number,
127036ff6393SMartin Habets PCI_SLOT(devfn), PCI_FUNC(devfn));
127136ff6393SMartin Habets
1272*c8443b69SMartin Habets rc = efx_siena_alloc_buffer(efx, &vf->buf, EFX_PAGE_SIZE,
127336ff6393SMartin Habets GFP_KERNEL);
127436ff6393SMartin Habets if (rc)
127536ff6393SMartin Habets goto fail;
127636ff6393SMartin Habets
127736ff6393SMartin Habets devfn += stride;
127836ff6393SMartin Habets }
127936ff6393SMartin Habets
128036ff6393SMartin Habets return 0;
128136ff6393SMartin Habets
128236ff6393SMartin Habets fail:
128336ff6393SMartin Habets efx_siena_sriov_vfs_fini(efx);
128436ff6393SMartin Habets return rc;
128536ff6393SMartin Habets }
128636ff6393SMartin Habets
efx_siena_sriov_init(struct efx_nic * efx)128736ff6393SMartin Habets int efx_siena_sriov_init(struct efx_nic *efx)
128836ff6393SMartin Habets {
128936ff6393SMartin Habets struct net_device *net_dev = efx->net_dev;
129036ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
129136ff6393SMartin Habets struct vfdi_status *vfdi_status;
129236ff6393SMartin Habets int rc;
129336ff6393SMartin Habets
129436ff6393SMartin Habets /* Ensure there's room for vf_channel */
129536ff6393SMartin Habets BUILD_BUG_ON(EFX_MAX_CHANNELS + 1 >= EFX_VI_BASE);
129636ff6393SMartin Habets /* Ensure that VI_BASE is aligned on VI_SCALE */
129736ff6393SMartin Habets BUILD_BUG_ON(EFX_VI_BASE & ((1 << EFX_VI_SCALE_MAX) - 1));
129836ff6393SMartin Habets
129936ff6393SMartin Habets if (efx->vf_count == 0)
130036ff6393SMartin Habets return 0;
130136ff6393SMartin Habets
130236ff6393SMartin Habets rc = efx_siena_sriov_cmd(efx, true, NULL, NULL);
130336ff6393SMartin Habets if (rc)
130436ff6393SMartin Habets goto fail_cmd;
130536ff6393SMartin Habets
1306*c8443b69SMartin Habets rc = efx_siena_alloc_buffer(efx, &nic_data->vfdi_status,
130736ff6393SMartin Habets sizeof(*vfdi_status), GFP_KERNEL);
130836ff6393SMartin Habets if (rc)
130936ff6393SMartin Habets goto fail_status;
131036ff6393SMartin Habets vfdi_status = nic_data->vfdi_status.addr;
131136ff6393SMartin Habets memset(vfdi_status, 0, sizeof(*vfdi_status));
131236ff6393SMartin Habets vfdi_status->version = 1;
131336ff6393SMartin Habets vfdi_status->length = sizeof(*vfdi_status);
131436ff6393SMartin Habets vfdi_status->max_tx_channels = vf_max_tx_channels;
131536ff6393SMartin Habets vfdi_status->vi_scale = efx->vi_scale;
131636ff6393SMartin Habets vfdi_status->rss_rxq_count = efx->rss_spread;
131736ff6393SMartin Habets vfdi_status->peer_count = 1 + efx->vf_count;
131836ff6393SMartin Habets vfdi_status->timer_quantum_ns = efx->timer_quantum_ns;
131936ff6393SMartin Habets
132036ff6393SMartin Habets rc = efx_siena_sriov_vf_alloc(efx);
132136ff6393SMartin Habets if (rc)
132236ff6393SMartin Habets goto fail_alloc;
132336ff6393SMartin Habets
132436ff6393SMartin Habets mutex_init(&nic_data->local_lock);
132536ff6393SMartin Habets INIT_WORK(&nic_data->peer_work, efx_siena_sriov_peer_work);
132636ff6393SMartin Habets INIT_LIST_HEAD(&nic_data->local_addr_list);
132736ff6393SMartin Habets INIT_LIST_HEAD(&nic_data->local_page_list);
132836ff6393SMartin Habets
132936ff6393SMartin Habets rc = efx_siena_sriov_vfs_init(efx);
133036ff6393SMartin Habets if (rc)
133136ff6393SMartin Habets goto fail_vfs;
133236ff6393SMartin Habets
133336ff6393SMartin Habets rtnl_lock();
133436ff6393SMartin Habets ether_addr_copy(vfdi_status->peers[0].mac_addr, net_dev->dev_addr);
133536ff6393SMartin Habets efx->vf_init_count = efx->vf_count;
133636ff6393SMartin Habets rtnl_unlock();
133736ff6393SMartin Habets
133836ff6393SMartin Habets efx_siena_sriov_usrev(efx, true);
133936ff6393SMartin Habets
134036ff6393SMartin Habets /* At this point we must be ready to accept VFDI requests */
134136ff6393SMartin Habets
134236ff6393SMartin Habets rc = pci_enable_sriov(efx->pci_dev, efx->vf_count);
134336ff6393SMartin Habets if (rc)
134436ff6393SMartin Habets goto fail_pci;
134536ff6393SMartin Habets
134636ff6393SMartin Habets netif_info(efx, probe, net_dev,
134736ff6393SMartin Habets "enabled SR-IOV for %d VFs, %d VI per VF\n",
134836ff6393SMartin Habets efx->vf_count, efx_vf_size(efx));
134936ff6393SMartin Habets return 0;
135036ff6393SMartin Habets
135136ff6393SMartin Habets fail_pci:
135236ff6393SMartin Habets efx_siena_sriov_usrev(efx, false);
135336ff6393SMartin Habets rtnl_lock();
135436ff6393SMartin Habets efx->vf_init_count = 0;
135536ff6393SMartin Habets rtnl_unlock();
135636ff6393SMartin Habets efx_siena_sriov_vfs_fini(efx);
135736ff6393SMartin Habets fail_vfs:
135836ff6393SMartin Habets cancel_work_sync(&nic_data->peer_work);
135936ff6393SMartin Habets efx_siena_sriov_free_local(efx);
136036ff6393SMartin Habets kfree(nic_data->vf);
136136ff6393SMartin Habets fail_alloc:
1362*c8443b69SMartin Habets efx_siena_free_buffer(efx, &nic_data->vfdi_status);
136336ff6393SMartin Habets fail_status:
136436ff6393SMartin Habets efx_siena_sriov_cmd(efx, false, NULL, NULL);
136536ff6393SMartin Habets fail_cmd:
136636ff6393SMartin Habets return rc;
136736ff6393SMartin Habets }
136836ff6393SMartin Habets
efx_siena_sriov_fini(struct efx_nic * efx)136936ff6393SMartin Habets void efx_siena_sriov_fini(struct efx_nic *efx)
137036ff6393SMartin Habets {
137136ff6393SMartin Habets struct siena_vf *vf;
137236ff6393SMartin Habets unsigned int pos;
137336ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
137436ff6393SMartin Habets
137536ff6393SMartin Habets if (efx->vf_init_count == 0)
137636ff6393SMartin Habets return;
137736ff6393SMartin Habets
137836ff6393SMartin Habets /* Disable all interfaces to reconfiguration */
137936ff6393SMartin Habets BUG_ON(nic_data->vfdi_channel->enabled);
138036ff6393SMartin Habets efx_siena_sriov_usrev(efx, false);
138136ff6393SMartin Habets rtnl_lock();
138236ff6393SMartin Habets efx->vf_init_count = 0;
138336ff6393SMartin Habets rtnl_unlock();
138436ff6393SMartin Habets
138536ff6393SMartin Habets /* Flush all reconfiguration work */
138636ff6393SMartin Habets for (pos = 0; pos < efx->vf_count; ++pos) {
138736ff6393SMartin Habets vf = nic_data->vf + pos;
138836ff6393SMartin Habets cancel_work_sync(&vf->req);
138936ff6393SMartin Habets cancel_work_sync(&vf->reset_work);
139036ff6393SMartin Habets }
139136ff6393SMartin Habets cancel_work_sync(&nic_data->peer_work);
139236ff6393SMartin Habets
139336ff6393SMartin Habets pci_disable_sriov(efx->pci_dev);
139436ff6393SMartin Habets
139536ff6393SMartin Habets /* Tear down back-end state */
139636ff6393SMartin Habets efx_siena_sriov_vfs_fini(efx);
139736ff6393SMartin Habets efx_siena_sriov_free_local(efx);
139836ff6393SMartin Habets kfree(nic_data->vf);
1399*c8443b69SMartin Habets efx_siena_free_buffer(efx, &nic_data->vfdi_status);
140036ff6393SMartin Habets efx_siena_sriov_cmd(efx, false, NULL, NULL);
140136ff6393SMartin Habets }
140236ff6393SMartin Habets
efx_siena_sriov_event(struct efx_channel * channel,efx_qword_t * event)140336ff6393SMartin Habets void efx_siena_sriov_event(struct efx_channel *channel, efx_qword_t *event)
140436ff6393SMartin Habets {
140536ff6393SMartin Habets struct efx_nic *efx = channel->efx;
140636ff6393SMartin Habets struct siena_vf *vf;
140736ff6393SMartin Habets unsigned qid, seq, type, data;
140836ff6393SMartin Habets
140936ff6393SMartin Habets qid = EFX_QWORD_FIELD(*event, FSF_CZ_USER_QID);
141036ff6393SMartin Habets
141136ff6393SMartin Habets /* USR_EV_REG_VALUE is dword0, so access the VFDI_EV fields directly */
141236ff6393SMartin Habets BUILD_BUG_ON(FSF_CZ_USER_EV_REG_VALUE_LBN != 0);
141336ff6393SMartin Habets seq = EFX_QWORD_FIELD(*event, VFDI_EV_SEQ);
141436ff6393SMartin Habets type = EFX_QWORD_FIELD(*event, VFDI_EV_TYPE);
141536ff6393SMartin Habets data = EFX_QWORD_FIELD(*event, VFDI_EV_DATA);
141636ff6393SMartin Habets
141736ff6393SMartin Habets netif_vdbg(efx, hw, efx->net_dev,
141836ff6393SMartin Habets "USR_EV event from qid %d seq 0x%x type %d data 0x%x\n",
141936ff6393SMartin Habets qid, seq, type, data);
142036ff6393SMartin Habets
142136ff6393SMartin Habets if (map_vi_index(efx, qid, &vf, NULL))
142236ff6393SMartin Habets return;
142336ff6393SMartin Habets if (vf->busy)
142436ff6393SMartin Habets goto error;
142536ff6393SMartin Habets
142636ff6393SMartin Habets if (type == VFDI_EV_TYPE_REQ_WORD0) {
142736ff6393SMartin Habets /* Resynchronise */
142836ff6393SMartin Habets vf->req_type = VFDI_EV_TYPE_REQ_WORD0;
142936ff6393SMartin Habets vf->req_seqno = seq + 1;
143036ff6393SMartin Habets vf->req_addr = 0;
143136ff6393SMartin Habets } else if (seq != (vf->req_seqno++ & 0xff) || type != vf->req_type)
143236ff6393SMartin Habets goto error;
143336ff6393SMartin Habets
143436ff6393SMartin Habets switch (vf->req_type) {
143536ff6393SMartin Habets case VFDI_EV_TYPE_REQ_WORD0:
143636ff6393SMartin Habets case VFDI_EV_TYPE_REQ_WORD1:
143736ff6393SMartin Habets case VFDI_EV_TYPE_REQ_WORD2:
143836ff6393SMartin Habets vf->req_addr |= (u64)data << (vf->req_type << 4);
143936ff6393SMartin Habets ++vf->req_type;
144036ff6393SMartin Habets return;
144136ff6393SMartin Habets
144236ff6393SMartin Habets case VFDI_EV_TYPE_REQ_WORD3:
144336ff6393SMartin Habets vf->req_addr |= (u64)data << 48;
144436ff6393SMartin Habets vf->req_type = VFDI_EV_TYPE_REQ_WORD0;
144536ff6393SMartin Habets vf->busy = true;
144636ff6393SMartin Habets queue_work(vfdi_workqueue, &vf->req);
144736ff6393SMartin Habets return;
144836ff6393SMartin Habets }
144936ff6393SMartin Habets
145036ff6393SMartin Habets error:
145136ff6393SMartin Habets if (net_ratelimit())
145236ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
145336ff6393SMartin Habets "ERROR: Screaming VFDI request from %s\n",
145436ff6393SMartin Habets vf->pci_name);
145536ff6393SMartin Habets /* Reset the request and sequence number */
145636ff6393SMartin Habets vf->req_type = VFDI_EV_TYPE_REQ_WORD0;
145736ff6393SMartin Habets vf->req_seqno = seq + 1;
145836ff6393SMartin Habets }
145936ff6393SMartin Habets
efx_siena_sriov_flr(struct efx_nic * efx,unsigned vf_i)146036ff6393SMartin Habets void efx_siena_sriov_flr(struct efx_nic *efx, unsigned vf_i)
146136ff6393SMartin Habets {
146236ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
146336ff6393SMartin Habets struct siena_vf *vf;
146436ff6393SMartin Habets
146536ff6393SMartin Habets if (vf_i > efx->vf_init_count)
146636ff6393SMartin Habets return;
146736ff6393SMartin Habets vf = nic_data->vf + vf_i;
146836ff6393SMartin Habets netif_info(efx, hw, efx->net_dev,
146936ff6393SMartin Habets "FLR on VF %s\n", vf->pci_name);
147036ff6393SMartin Habets
147136ff6393SMartin Habets vf->status_addr = 0;
147236ff6393SMartin Habets efx_vfdi_remove_all_filters(vf);
147336ff6393SMartin Habets efx_vfdi_flush_clear(vf);
147436ff6393SMartin Habets
147536ff6393SMartin Habets vf->evq0_count = 0;
147636ff6393SMartin Habets }
147736ff6393SMartin Habets
efx_siena_sriov_mac_address_changed(struct efx_nic * efx)147836ff6393SMartin Habets int efx_siena_sriov_mac_address_changed(struct efx_nic *efx)
147936ff6393SMartin Habets {
148036ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
148136ff6393SMartin Habets struct vfdi_status *vfdi_status = nic_data->vfdi_status.addr;
148236ff6393SMartin Habets
148336ff6393SMartin Habets if (!efx->vf_init_count)
148436ff6393SMartin Habets return 0;
148536ff6393SMartin Habets ether_addr_copy(vfdi_status->peers[0].mac_addr,
148636ff6393SMartin Habets efx->net_dev->dev_addr);
148736ff6393SMartin Habets queue_work(vfdi_workqueue, &nic_data->peer_work);
148836ff6393SMartin Habets
148936ff6393SMartin Habets return 0;
149036ff6393SMartin Habets }
149136ff6393SMartin Habets
efx_siena_sriov_tx_flush_done(struct efx_nic * efx,efx_qword_t * event)149236ff6393SMartin Habets void efx_siena_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
149336ff6393SMartin Habets {
149436ff6393SMartin Habets struct siena_vf *vf;
149536ff6393SMartin Habets unsigned queue, qid;
149636ff6393SMartin Habets
149736ff6393SMartin Habets queue = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBDATA);
149836ff6393SMartin Habets if (map_vi_index(efx, queue, &vf, &qid))
149936ff6393SMartin Habets return;
150036ff6393SMartin Habets /* Ignore flush completions triggered by an FLR */
150136ff6393SMartin Habets if (!test_bit(qid, vf->txq_mask))
150236ff6393SMartin Habets return;
150336ff6393SMartin Habets
150436ff6393SMartin Habets __clear_bit(qid, vf->txq_mask);
150536ff6393SMartin Habets --vf->txq_count;
150636ff6393SMartin Habets
150736ff6393SMartin Habets if (efx_vfdi_flush_wake(vf))
150836ff6393SMartin Habets wake_up(&vf->flush_waitq);
150936ff6393SMartin Habets }
151036ff6393SMartin Habets
efx_siena_sriov_rx_flush_done(struct efx_nic * efx,efx_qword_t * event)151136ff6393SMartin Habets void efx_siena_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event)
151236ff6393SMartin Habets {
151336ff6393SMartin Habets struct siena_vf *vf;
151436ff6393SMartin Habets unsigned ev_failed, queue, qid;
151536ff6393SMartin Habets
151636ff6393SMartin Habets queue = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_RX_DESCQ_ID);
151736ff6393SMartin Habets ev_failed = EFX_QWORD_FIELD(*event,
151836ff6393SMartin Habets FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
151936ff6393SMartin Habets if (map_vi_index(efx, queue, &vf, &qid))
152036ff6393SMartin Habets return;
152136ff6393SMartin Habets if (!test_bit(qid, vf->rxq_mask))
152236ff6393SMartin Habets return;
152336ff6393SMartin Habets
152436ff6393SMartin Habets if (ev_failed) {
152536ff6393SMartin Habets set_bit(qid, vf->rxq_retry_mask);
152636ff6393SMartin Habets atomic_inc(&vf->rxq_retry_count);
152736ff6393SMartin Habets } else {
152836ff6393SMartin Habets __clear_bit(qid, vf->rxq_mask);
152936ff6393SMartin Habets --vf->rxq_count;
153036ff6393SMartin Habets }
153136ff6393SMartin Habets if (efx_vfdi_flush_wake(vf))
153236ff6393SMartin Habets wake_up(&vf->flush_waitq);
153336ff6393SMartin Habets }
153436ff6393SMartin Habets
153536ff6393SMartin Habets /* Called from napi. Schedule the reset work item */
efx_siena_sriov_desc_fetch_err(struct efx_nic * efx,unsigned dmaq)153636ff6393SMartin Habets void efx_siena_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq)
153736ff6393SMartin Habets {
153836ff6393SMartin Habets struct siena_vf *vf;
153936ff6393SMartin Habets unsigned int rel;
154036ff6393SMartin Habets
154136ff6393SMartin Habets if (map_vi_index(efx, dmaq, &vf, &rel))
154236ff6393SMartin Habets return;
154336ff6393SMartin Habets
154436ff6393SMartin Habets if (net_ratelimit())
154536ff6393SMartin Habets netif_err(efx, hw, efx->net_dev,
154636ff6393SMartin Habets "VF %d DMA Q %d reports descriptor fetch error.\n",
154736ff6393SMartin Habets vf->index, rel);
154836ff6393SMartin Habets queue_work(vfdi_workqueue, &vf->reset_work);
154936ff6393SMartin Habets }
155036ff6393SMartin Habets
155136ff6393SMartin Habets /* Reset all VFs */
efx_siena_sriov_reset(struct efx_nic * efx)155236ff6393SMartin Habets void efx_siena_sriov_reset(struct efx_nic *efx)
155336ff6393SMartin Habets {
155436ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
155536ff6393SMartin Habets unsigned int vf_i;
155636ff6393SMartin Habets struct efx_buffer buf;
155736ff6393SMartin Habets struct siena_vf *vf;
155836ff6393SMartin Habets
155936ff6393SMartin Habets ASSERT_RTNL();
156036ff6393SMartin Habets
156136ff6393SMartin Habets if (efx->vf_init_count == 0)
156236ff6393SMartin Habets return;
156336ff6393SMartin Habets
156436ff6393SMartin Habets efx_siena_sriov_usrev(efx, true);
156536ff6393SMartin Habets (void)efx_siena_sriov_cmd(efx, true, NULL, NULL);
156636ff6393SMartin Habets
1567*c8443b69SMartin Habets if (efx_siena_alloc_buffer(efx, &buf, EFX_PAGE_SIZE, GFP_NOIO))
156836ff6393SMartin Habets return;
156936ff6393SMartin Habets
157036ff6393SMartin Habets for (vf_i = 0; vf_i < efx->vf_init_count; ++vf_i) {
157136ff6393SMartin Habets vf = nic_data->vf + vf_i;
157236ff6393SMartin Habets efx_siena_sriov_reset_vf(vf, &buf);
157336ff6393SMartin Habets }
157436ff6393SMartin Habets
1575*c8443b69SMartin Habets efx_siena_free_buffer(efx, &buf);
157636ff6393SMartin Habets }
157736ff6393SMartin Habets
efx_init_sriov(void)157836ff6393SMartin Habets int efx_init_sriov(void)
157936ff6393SMartin Habets {
158036ff6393SMartin Habets /* A single threaded workqueue is sufficient. efx_siena_sriov_vfdi() and
158136ff6393SMartin Habets * efx_siena_sriov_peer_work() spend almost all their time sleeping for
158236ff6393SMartin Habets * MCDI to complete anyway
158336ff6393SMartin Habets */
158436ff6393SMartin Habets vfdi_workqueue = create_singlethread_workqueue("sfc_vfdi");
158536ff6393SMartin Habets if (!vfdi_workqueue)
158636ff6393SMartin Habets return -ENOMEM;
158736ff6393SMartin Habets return 0;
158836ff6393SMartin Habets }
158936ff6393SMartin Habets
efx_fini_sriov(void)159036ff6393SMartin Habets void efx_fini_sriov(void)
159136ff6393SMartin Habets {
159236ff6393SMartin Habets destroy_workqueue(vfdi_workqueue);
159336ff6393SMartin Habets }
159436ff6393SMartin Habets
efx_siena_sriov_set_vf_mac(struct efx_nic * efx,int vf_i,const u8 * mac)159536ff6393SMartin Habets int efx_siena_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac)
159636ff6393SMartin Habets {
159736ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
159836ff6393SMartin Habets struct siena_vf *vf;
159936ff6393SMartin Habets
160036ff6393SMartin Habets if (vf_i >= efx->vf_init_count)
160136ff6393SMartin Habets return -EINVAL;
160236ff6393SMartin Habets vf = nic_data->vf + vf_i;
160336ff6393SMartin Habets
160436ff6393SMartin Habets mutex_lock(&vf->status_lock);
160536ff6393SMartin Habets ether_addr_copy(vf->addr.mac_addr, mac);
160636ff6393SMartin Habets __efx_siena_sriov_update_vf_addr(vf);
160736ff6393SMartin Habets mutex_unlock(&vf->status_lock);
160836ff6393SMartin Habets
160936ff6393SMartin Habets return 0;
161036ff6393SMartin Habets }
161136ff6393SMartin Habets
efx_siena_sriov_set_vf_vlan(struct efx_nic * efx,int vf_i,u16 vlan,u8 qos)161236ff6393SMartin Habets int efx_siena_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i,
161336ff6393SMartin Habets u16 vlan, u8 qos)
161436ff6393SMartin Habets {
161536ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
161636ff6393SMartin Habets struct siena_vf *vf;
161736ff6393SMartin Habets u16 tci;
161836ff6393SMartin Habets
161936ff6393SMartin Habets if (vf_i >= efx->vf_init_count)
162036ff6393SMartin Habets return -EINVAL;
162136ff6393SMartin Habets vf = nic_data->vf + vf_i;
162236ff6393SMartin Habets
162336ff6393SMartin Habets mutex_lock(&vf->status_lock);
162436ff6393SMartin Habets tci = (vlan & VLAN_VID_MASK) | ((qos & 0x7) << VLAN_PRIO_SHIFT);
162536ff6393SMartin Habets vf->addr.tci = htons(tci);
162636ff6393SMartin Habets __efx_siena_sriov_update_vf_addr(vf);
162736ff6393SMartin Habets mutex_unlock(&vf->status_lock);
162836ff6393SMartin Habets
162936ff6393SMartin Habets return 0;
163036ff6393SMartin Habets }
163136ff6393SMartin Habets
efx_siena_sriov_set_vf_spoofchk(struct efx_nic * efx,int vf_i,bool spoofchk)163236ff6393SMartin Habets int efx_siena_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf_i,
163336ff6393SMartin Habets bool spoofchk)
163436ff6393SMartin Habets {
163536ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
163636ff6393SMartin Habets struct siena_vf *vf;
163736ff6393SMartin Habets int rc;
163836ff6393SMartin Habets
163936ff6393SMartin Habets if (vf_i >= efx->vf_init_count)
164036ff6393SMartin Habets return -EINVAL;
164136ff6393SMartin Habets vf = nic_data->vf + vf_i;
164236ff6393SMartin Habets
164336ff6393SMartin Habets mutex_lock(&vf->txq_lock);
164436ff6393SMartin Habets if (vf->txq_count == 0) {
164536ff6393SMartin Habets vf->tx_filter_mode =
164636ff6393SMartin Habets spoofchk ? VF_TX_FILTER_ON : VF_TX_FILTER_OFF;
164736ff6393SMartin Habets rc = 0;
164836ff6393SMartin Habets } else {
164936ff6393SMartin Habets /* This cannot be changed while TX queues are running */
165036ff6393SMartin Habets rc = -EBUSY;
165136ff6393SMartin Habets }
165236ff6393SMartin Habets mutex_unlock(&vf->txq_lock);
165336ff6393SMartin Habets return rc;
165436ff6393SMartin Habets }
165536ff6393SMartin Habets
efx_siena_sriov_get_vf_config(struct efx_nic * efx,int vf_i,struct ifla_vf_info * ivi)165636ff6393SMartin Habets int efx_siena_sriov_get_vf_config(struct efx_nic *efx, int vf_i,
165736ff6393SMartin Habets struct ifla_vf_info *ivi)
165836ff6393SMartin Habets {
165936ff6393SMartin Habets struct siena_nic_data *nic_data = efx->nic_data;
166036ff6393SMartin Habets struct siena_vf *vf;
166136ff6393SMartin Habets u16 tci;
166236ff6393SMartin Habets
166336ff6393SMartin Habets if (vf_i >= efx->vf_init_count)
166436ff6393SMartin Habets return -EINVAL;
166536ff6393SMartin Habets vf = nic_data->vf + vf_i;
166636ff6393SMartin Habets
166736ff6393SMartin Habets ivi->vf = vf_i;
166836ff6393SMartin Habets ether_addr_copy(ivi->mac, vf->addr.mac_addr);
166936ff6393SMartin Habets ivi->max_tx_rate = 0;
167036ff6393SMartin Habets ivi->min_tx_rate = 0;
167136ff6393SMartin Habets tci = ntohs(vf->addr.tci);
167236ff6393SMartin Habets ivi->vlan = tci & VLAN_VID_MASK;
167336ff6393SMartin Habets ivi->qos = (tci >> VLAN_PRIO_SHIFT) & 0x7;
167436ff6393SMartin Habets ivi->spoofchk = vf->tx_filter_mode == VF_TX_FILTER_ON;
167536ff6393SMartin Habets
167636ff6393SMartin Habets return 0;
167736ff6393SMartin Habets }
167836ff6393SMartin Habets
efx_siena_sriov_wanted(struct efx_nic * efx)167936ff6393SMartin Habets bool efx_siena_sriov_wanted(struct efx_nic *efx)
168036ff6393SMartin Habets {
168136ff6393SMartin Habets return efx->vf_count != 0;
168236ff6393SMartin Habets }
168336ff6393SMartin Habets
efx_siena_sriov_configure(struct efx_nic * efx,int num_vfs)168436ff6393SMartin Habets int efx_siena_sriov_configure(struct efx_nic *efx, int num_vfs)
168536ff6393SMartin Habets {
168636ff6393SMartin Habets return 0;
168736ff6393SMartin Habets }
1688