Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71827443 authored by Edward Cree's avatar Edward Cree Committed by David S. Miller
Browse files

sfc: support VI strides other than 8k



Medford2 can also have 16k or 64k VI stride.  This is reported by MCDI in
 GET_CAPABILITIES, which fortunately is called before the driver does
 anything sensitive to the VI stride (such as accessing or even allocating
 VIs past the zeroth).

Signed-off-by: default avatarEdward Cree <ecree@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 03714bbb
Loading
Loading
Loading
Loading
+51 −19
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ static int efx_ef10_get_vf_index(struct efx_nic *efx)

static int efx_ef10_init_datapath_caps(struct efx_nic *efx)
{
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V2_OUT_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V3_OUT_LEN);
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	size_t outlen;
	int rc;
@@ -277,6 +277,35 @@ static int efx_ef10_init_datapath_caps(struct efx_nic *efx)
		return -ENODEV;
	}

	if (outlen >= MC_CMD_GET_CAPABILITIES_V3_OUT_LEN) {
		u8 vi_window_mode = MCDI_BYTE(outbuf,
				GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE);

		switch (vi_window_mode) {
		case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_8K:
			efx->vi_stride = 8192;
			break;
		case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_16K:
			efx->vi_stride = 16384;
			break;
		case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_64K:
			efx->vi_stride = 65536;
			break;
		default:
			netif_err(efx, probe, efx->net_dev,
				  "Unrecognised VI window mode %d\n",
				  vi_window_mode);
			return -EIO;
		}
		netif_dbg(efx, probe, efx->net_dev, "vi_stride = %u\n",
			  efx->vi_stride);
	} else {
		/* keep default VI stride */
		netif_dbg(efx, probe, efx->net_dev,
			  "firmware did not report VI window mode, assuming vi_stride = %u\n",
			  efx->vi_stride);
	}

	return 0;
}

@@ -609,17 +638,6 @@ static int efx_ef10_probe(struct efx_nic *efx)
	struct efx_ef10_nic_data *nic_data;
	int i, rc;

	/* We can have one VI for each 8K region.  However, until we
	 * use TX option descriptors we need two TX queues per channel.
	 */
	efx->max_channels = min_t(unsigned int,
				  EFX_MAX_CHANNELS,
				  efx_ef10_mem_map_size(efx) /
				  (EFX_VI_PAGE_SIZE * EFX_TXQ_TYPES));
	efx->max_tx_channels = efx->max_channels;
	if (WARN_ON(efx->max_channels == 0))
		return -EIO;

	nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
	if (!nic_data)
		return -ENOMEM;
@@ -691,6 +709,20 @@ static int efx_ef10_probe(struct efx_nic *efx)
	if (rc < 0)
		goto fail5;

	/* We can have one VI for each vi_stride-byte region.
	 * However, until we use TX option descriptors we need two TX queues
	 * per channel.
	 */
	efx->max_channels = min_t(unsigned int,
				  EFX_MAX_CHANNELS,
				  efx_ef10_mem_map_size(efx) /
				  (efx->vi_stride * EFX_TXQ_TYPES));
	efx->max_tx_channels = efx->max_channels;
	if (WARN_ON(efx->max_channels == 0)) {
		rc = -EIO;
		goto fail5;
	}

	efx->rx_packet_len_offset =
		ES_DZ_RX_PREFIX_PKTLEN_OFST - ES_DZ_RX_PREFIX_SIZE;

@@ -927,7 +959,7 @@ static int efx_ef10_link_piobufs(struct efx_nic *efx)
			} else {
				tx_queue->piobuf =
					nic_data->pio_write_base +
					index * EFX_VI_PAGE_SIZE + offset;
					index * efx->vi_stride + offset;
				tx_queue->piobuf_offset = offset;
				netif_dbg(efx, probe, efx->net_dev,
					  "linked VI %u to PIO buffer %u offset %x addr %p\n",
@@ -1273,19 +1305,19 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
	 * for writing PIO buffers through.
	 *
	 * The UC mapping contains (channel_vis - 1) complete VIs and the
	 * first half of the next VI.  Then the WC mapping begins with
	 * the second half of this last VI.
	 * first 4K of the next VI.  Then the WC mapping begins with
	 * the remainder of this last VI.
	 */
	uc_mem_map_size = PAGE_ALIGN((channel_vis - 1) * EFX_VI_PAGE_SIZE +
	uc_mem_map_size = PAGE_ALIGN((channel_vis - 1) * efx->vi_stride +
				     ER_DZ_TX_PIOBUF);
	if (nic_data->n_piobufs) {
		/* pio_write_vi_base rounds down to give the number of complete
		 * VIs inside the UC mapping.
		 */
		pio_write_vi_base = uc_mem_map_size / EFX_VI_PAGE_SIZE;
		pio_write_vi_base = uc_mem_map_size / efx->vi_stride;
		wc_mem_map_size = (PAGE_ALIGN((pio_write_vi_base +
					       nic_data->n_piobufs) *
					      EFX_VI_PAGE_SIZE) -
					      efx->vi_stride) -
				   uc_mem_map_size);
		max_vis = pio_write_vi_base + nic_data->n_piobufs;
	} else {
@@ -1357,7 +1389,7 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
		nic_data->pio_write_vi_base = pio_write_vi_base;
		nic_data->pio_write_base =
			nic_data->wc_membase +
			(pio_write_vi_base * EFX_VI_PAGE_SIZE + ER_DZ_TX_PIOBUF -
			(pio_write_vi_base * efx->vi_stride + ER_DZ_TX_PIOBUF -
			 uc_mem_map_size);

		rc = efx_ef10_link_piobufs(efx);
+2 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <net/udp_tunnel.h>
#include "efx.h"
#include "nic.h"
#include "io.h"
#include "selftest.h"
#include "sriov.h"

@@ -2977,6 +2978,7 @@ static int efx_init_struct(struct efx_nic *efx,
	efx->rx_packet_ts_offset =
		efx->type->rx_ts_offset - efx->type->rx_prefix_size;
	spin_lock_init(&efx->stats_lock);
	efx->vi_stride = EFX_DEFAULT_VI_STRIDE;
	mutex_init(&efx->mac_lock);
	efx->phy_op = &efx_dummy_phy_operations;
	efx->mdio.dev = net_dev;
+11 −8
Original line number Diff line number Diff line
@@ -222,18 +222,21 @@ static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value,
	efx_reado(efx, value, reg + index * sizeof(efx_oword_t));
}

/* Page size used as step between per-VI registers */
#define EFX_VI_PAGE_SIZE 0x2000
/* default VI stride (step between per-VI registers) is 8K */
#define EFX_DEFAULT_VI_STRIDE 0x2000

/* Calculate offset to page-mapped register */
#define EFX_PAGED_REG(page, reg) \
	((page) * EFX_VI_PAGE_SIZE + (reg))
static inline unsigned int efx_paged_reg(struct efx_nic *efx, unsigned int page,
					 unsigned int reg)
{
	return page * efx->vi_stride + reg;
}

/* Write the whole of RX_DESC_UPD or TX_DESC_UPD */
static inline void _efx_writeo_page(struct efx_nic *efx, efx_oword_t *value,
				    unsigned int reg, unsigned int page)
{
	reg = EFX_PAGED_REG(page, reg);
	reg = efx_paged_reg(efx, page, reg);

	netif_vdbg(efx, hw, efx->net_dev,
		   "writing register %x with " EFX_OWORD_FMT "\n", reg,
@@ -262,7 +265,7 @@ static inline void
_efx_writed_page(struct efx_nic *efx, const efx_dword_t *value,
		 unsigned int reg, unsigned int page)
{
	efx_writed(efx, value, EFX_PAGED_REG(page, reg));
	efx_writed(efx, value, efx_paged_reg(efx, page, reg));
}
#define efx_writed_page(efx, value, reg, page)				\
	_efx_writed_page(efx, value,					\
@@ -288,10 +291,10 @@ static inline void _efx_writed_page_locked(struct efx_nic *efx,

	if (page == 0) {
		spin_lock_irqsave(&efx->biu_lock, flags);
		efx_writed(efx, value, EFX_PAGED_REG(page, reg));
		efx_writed(efx, value, efx_paged_reg(efx, page, reg));
		spin_unlock_irqrestore(&efx->biu_lock, flags);
	} else {
		efx_writed(efx, value, EFX_PAGED_REG(page, reg));
		efx_writed(efx, value, efx_paged_reg(efx, page, reg));
	}
}
#define efx_writed_page_locked(efx, value, reg, page)			\
+3 −0
Original line number Diff line number Diff line
@@ -208,6 +208,9 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define _MCDI_DWORD(_buf, _field)					\
	((_buf) + (_MCDI_CHECK_ALIGN(MC_CMD_ ## _field ## _OFST, 4) >> 2))

#define MCDI_BYTE(_buf, _field)						\
	((void)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 1),	\
	 *MCDI_PTR(_buf, _field))
#define MCDI_WORD(_buf, _field)						\
	((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) +	\
	 le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field)))
+3 −0
Original line number Diff line number Diff line
@@ -708,6 +708,7 @@ struct vfdi_status;
 * @reset_work: Scheduled reset workitem
 * @membase_phys: Memory BAR value as physical address
 * @membase: Memory BAR value
 * @vi_stride: step between per-VI registers / memory regions
 * @interrupt_mode: Interrupt mode
 * @timer_quantum_ns: Interrupt timer quantum, in nanoseconds
 * @timer_max_ns: Interrupt timer maximum value, in nanoseconds
@@ -842,6 +843,8 @@ struct efx_nic {
	resource_size_t membase_phys;
	void __iomem *membase;

	unsigned int vi_stride;

	enum efx_int_mode interrupt_mode;
	unsigned int timer_quantum_ns;
	unsigned int timer_max_ns;