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

Commit 4e7b3be4 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sfc-next'



Shradha Shah says:

====================
sfc: Get/Set MAC address and ndo_[set/get]_vf_* entrypoint functions

This is the second installment of patches towards supporting EF10 SRIOV.

This patch series implements the ndo_get_vf_config, ndo_set_vf_mac,
ndo_set_vf_vlan and ndo_set_vf_spoofcheck function callbacks for EF10.

This patch series also introduces privileges for the MCDI commands
based on which functions are allowed to call them, i.e. Link control
or primary function.

The patch series has been tested with and without CONFIG_SFC_SRIOV.

The ndo function callbacks are tested using ip link.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4ec49a37 910c8789
Loading
Loading
Loading
Loading
+243 −36
Original line number Original line Diff line number Diff line
@@ -119,6 +119,26 @@ static int efx_ef10_get_pf_index(struct efx_nic *efx)
	return 0;
	return 0;
}
}


#ifdef CONFIG_SFC_SRIOV
static int efx_ef10_get_vf_index(struct efx_nic *efx)
{
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN);
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	size_t outlen;
	int rc;

	rc = efx_mcdi_rpc(efx, MC_CMD_GET_FUNCTION_INFO, NULL, 0, outbuf,
			  sizeof(outbuf), &outlen);
	if (rc)
		return rc;
	if (outlen < sizeof(outbuf))
		return -EIO;

	nic_data->vf_index = MCDI_DWORD(outbuf, GET_FUNCTION_INFO_OUT_VF);
	return 0;
}
#endif

static int efx_ef10_init_datapath_caps(struct efx_nic *efx)
static int efx_ef10_init_datapath_caps(struct efx_nic *efx)
{
{
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_OUT_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_OUT_LEN);
@@ -178,7 +198,7 @@ static int efx_ef10_get_sysclk_freq(struct efx_nic *efx)
	return rc > 0 ? rc : -ERANGE;
	return rc > 0 ? rc : -ERANGE;
}
}


static int efx_ef10_get_mac_address(struct efx_nic *efx, u8 *mac_address)
static int efx_ef10_get_mac_address_pf(struct efx_nic *efx, u8 *mac_address)
{
{
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
	size_t outlen;
	size_t outlen;
@@ -198,6 +218,34 @@ static int efx_ef10_get_mac_address(struct efx_nic *efx, u8 *mac_address)
	return 0;
	return 0;
}
}


static int efx_ef10_get_mac_address_vf(struct efx_nic *efx, u8 *mac_address)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX);
	size_t outlen;
	int num_addrs, rc;

	MCDI_SET_DWORD(inbuf, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID,
		       EVB_PORT_ID_ASSIGNED);
	rc = efx_mcdi_rpc(efx, MC_CMD_VPORT_GET_MAC_ADDRESSES, inbuf,
			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);

	if (rc)
		return rc;
	if (outlen < MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN)
		return -EIO;

	num_addrs = MCDI_DWORD(outbuf,
			       VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT);

	WARN_ON(num_addrs != 1);

	ether_addr_copy(mac_address,
			MCDI_PTR(outbuf, VPORT_GET_MAC_ADDRESSES_OUT_MACADDR));

	return 0;
}

static int efx_ef10_probe(struct efx_nic *efx)
static int efx_ef10_probe(struct efx_nic *efx)
{
{
	struct efx_ef10_nic_data *nic_data;
	struct efx_ef10_nic_data *nic_data;
@@ -279,7 +327,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
		goto fail3;
		goto fail3;
	efx->port_num = rc;
	efx->port_num = rc;


	rc = efx_ef10_get_mac_address(efx, efx->net_dev->perm_addr);
	rc = efx->type->get_mac_address(efx, efx->net_dev->perm_addr);
	if (rc)
	if (rc)
		goto fail3;
		goto fail3;


@@ -328,26 +376,9 @@ static int efx_ef10_probe(struct efx_nic *efx)
	return rc;
	return rc;
}
}


static int efx_ef10_probe_pf(struct efx_nic *efx)
{
	return efx_ef10_probe(efx);
}

#ifdef CONFIG_SFC_SRIOV
static int efx_ef10_probe_vf(struct efx_nic *efx)
{
	return efx_ef10_probe(efx);
}
#else
static int efx_ef10_probe_vf(struct efx_nic *efx __attribute__ ((unused)))
{
	return 0;
}
#endif

static int efx_ef10_free_vis(struct efx_nic *efx)
static int efx_ef10_free_vis(struct efx_nic *efx)
{
{
	MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, 0);
	MCDI_DECLARE_BUF_ERR(outbuf);
	size_t outlen;
	size_t outlen;
	int rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FREE_VIS, NULL, 0,
	int rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FREE_VIS, NULL, 0,
				    outbuf, sizeof(outbuf), &outlen);
				    outbuf, sizeof(outbuf), &outlen);
@@ -418,7 +449,7 @@ static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
static int efx_ef10_link_piobufs(struct efx_nic *efx)
static int efx_ef10_link_piobufs(struct efx_nic *efx)
{
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	MCDI_DECLARE_BUF(inbuf,
	_MCDI_DECLARE_BUF(inbuf,
			  max(MC_CMD_LINK_PIOBUF_IN_LEN,
			  max(MC_CMD_LINK_PIOBUF_IN_LEN,
			      MC_CMD_UNLINK_PIOBUF_IN_LEN));
			      MC_CMD_UNLINK_PIOBUF_IN_LEN));
	struct efx_channel *channel;
	struct efx_channel *channel;
@@ -429,6 +460,8 @@ static int efx_ef10_link_piobufs(struct efx_nic *efx)
	BUILD_BUG_ON(MC_CMD_LINK_PIOBUF_OUT_LEN != 0);
	BUILD_BUG_ON(MC_CMD_LINK_PIOBUF_OUT_LEN != 0);
	BUILD_BUG_ON(MC_CMD_UNLINK_PIOBUF_OUT_LEN != 0);
	BUILD_BUG_ON(MC_CMD_UNLINK_PIOBUF_OUT_LEN != 0);


	memset(inbuf, 0, sizeof(inbuf));

	/* Link a buffer to each VI in the write-combining mapping */
	/* Link a buffer to each VI in the write-combining mapping */
	for (index = 0; index < nic_data->n_piobufs; ++index) {
	for (index = 0; index < nic_data->n_piobufs; ++index) {
		MCDI_SET_DWORD(inbuf, LINK_PIOBUF_IN_PIOBUF_HANDLE,
		MCDI_SET_DWORD(inbuf, LINK_PIOBUF_IN_PIOBUF_HANDLE,
@@ -541,6 +574,25 @@ static void efx_ef10_remove(struct efx_nic *efx)
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	int rc;
	int rc;


#ifdef CONFIG_SFC_SRIOV
	struct efx_ef10_nic_data *nic_data_pf;
	struct pci_dev *pci_dev_pf;
	struct efx_nic *efx_pf;
	struct ef10_vf *vf;

	if (efx->pci_dev->is_virtfn) {
		pci_dev_pf = efx->pci_dev->physfn;
		if (pci_dev_pf) {
			efx_pf = pci_get_drvdata(pci_dev_pf);
			nic_data_pf = efx_pf->nic_data;
			vf = nic_data_pf->vf + nic_data->vf_index;
			vf->efx = NULL;
		} else
			netif_info(efx, drv, efx->net_dev,
				   "Could not get the PF id from VF\n");
	}
#endif

	efx_ptp_remove(efx);
	efx_ptp_remove(efx);


	efx_mcdi_mon_remove(efx);
	efx_mcdi_mon_remove(efx);
@@ -561,6 +613,50 @@ static void efx_ef10_remove(struct efx_nic *efx)
	kfree(nic_data);
	kfree(nic_data);
}
}


static int efx_ef10_probe_pf(struct efx_nic *efx)
{
	return efx_ef10_probe(efx);
}

#ifdef CONFIG_SFC_SRIOV
static int efx_ef10_probe_vf(struct efx_nic *efx)
{
	int rc;

	rc = efx_ef10_probe(efx);
	if (rc)
		return rc;

	rc = efx_ef10_get_vf_index(efx);
	if (rc)
		goto fail;

	if (efx->pci_dev->is_virtfn) {
		if (efx->pci_dev->physfn) {
			struct efx_nic *efx_pf =
				pci_get_drvdata(efx->pci_dev->physfn);
			struct efx_ef10_nic_data *nic_data_p = efx_pf->nic_data;
			struct efx_ef10_nic_data *nic_data = efx->nic_data;

			nic_data_p->vf[nic_data->vf_index].efx = efx;
		} else
			netif_info(efx, drv, efx->net_dev,
				   "Could not get the PF id from VF\n");
	}

	return 0;

fail:
	efx_ef10_remove(efx);
	return rc;
}
#else
static int efx_ef10_probe_vf(struct efx_nic *efx __attribute__ ((unused)))
{
	return 0;
}
#endif

static int efx_ef10_alloc_vis(struct efx_nic *efx,
static int efx_ef10_alloc_vis(struct efx_nic *efx,
			      unsigned int min_vis, unsigned int max_vis)
			      unsigned int min_vis, unsigned int max_vis)
{
{
@@ -770,6 +866,14 @@ static void efx_ef10_reset_mc_allocations(struct efx_nic *efx)
	nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
	nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
}
}


static enum reset_type efx_ef10_map_reset_reason(enum reset_type reason)
{
	if (reason == RESET_TYPE_MC_FAILURE)
		return RESET_TYPE_DATAPATH;

	return efx_mcdi_map_reset_reason(reason);
}

static int efx_ef10_map_reset_flags(u32 *flags)
static int efx_ef10_map_reset_flags(u32 *flags)
{
{
	enum {
	enum {
@@ -1312,17 +1416,17 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
{
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_INIT_TXQ_IN_LEN(EFX_MAX_DMAQ_SIZE * 8 /
	MCDI_DECLARE_BUF(inbuf, MC_CMD_INIT_TXQ_IN_LEN(EFX_MAX_DMAQ_SIZE * 8 /
						       EFX_BUF_SIZE));
						       EFX_BUF_SIZE));
	MCDI_DECLARE_BUF(outbuf, MC_CMD_INIT_TXQ_OUT_LEN);
	bool csum_offload = tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD;
	bool csum_offload = tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD;
	size_t entries = tx_queue->txd.buf.len / EFX_BUF_SIZE;
	size_t entries = tx_queue->txd.buf.len / EFX_BUF_SIZE;
	struct efx_channel *channel = tx_queue->channel;
	struct efx_channel *channel = tx_queue->channel;
	struct efx_nic *efx = tx_queue->efx;
	struct efx_nic *efx = tx_queue->efx;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	size_t inlen, outlen;
	size_t inlen;
	dma_addr_t dma_addr;
	dma_addr_t dma_addr;
	efx_qword_t *txd;
	efx_qword_t *txd;
	int rc;
	int rc;
	int i;
	int i;
	BUILD_BUG_ON(MC_CMD_INIT_TXQ_OUT_LEN != 0);


	MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_SIZE, tx_queue->ptr_mask + 1);
	MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_SIZE, tx_queue->ptr_mask + 1);
	MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_TARGET_EVQ, channel->channel);
	MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_TARGET_EVQ, channel->channel);
@@ -1347,7 +1451,7 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
	inlen = MC_CMD_INIT_TXQ_IN_LEN(entries);
	inlen = MC_CMD_INIT_TXQ_IN_LEN(entries);


	rc = efx_mcdi_rpc(efx, MC_CMD_INIT_TXQ, inbuf, inlen,
	rc = efx_mcdi_rpc(efx, MC_CMD_INIT_TXQ, inbuf, inlen,
			  outbuf, sizeof(outbuf), &outlen);
			  NULL, 0, NULL);
	if (rc)
	if (rc)
		goto fail;
		goto fail;


@@ -1380,7 +1484,7 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
static void efx_ef10_tx_fini(struct efx_tx_queue *tx_queue)
static void efx_ef10_tx_fini(struct efx_tx_queue *tx_queue)
{
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_TXQ_IN_LEN);
	MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_TXQ_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_FINI_TXQ_OUT_LEN);
	MCDI_DECLARE_BUF_ERR(outbuf);
	struct efx_nic *efx = tx_queue->efx;
	struct efx_nic *efx = tx_queue->efx;
	size_t outlen;
	size_t outlen;
	int rc;
	int rc;
@@ -1687,15 +1791,15 @@ static void efx_ef10_rx_init(struct efx_rx_queue *rx_queue)
	MCDI_DECLARE_BUF(inbuf,
	MCDI_DECLARE_BUF(inbuf,
			 MC_CMD_INIT_RXQ_IN_LEN(EFX_MAX_DMAQ_SIZE * 8 /
			 MC_CMD_INIT_RXQ_IN_LEN(EFX_MAX_DMAQ_SIZE * 8 /
						EFX_BUF_SIZE));
						EFX_BUF_SIZE));
	MCDI_DECLARE_BUF(outbuf, MC_CMD_INIT_RXQ_OUT_LEN);
	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
	size_t entries = rx_queue->rxd.buf.len / EFX_BUF_SIZE;
	size_t entries = rx_queue->rxd.buf.len / EFX_BUF_SIZE;
	struct efx_nic *efx = rx_queue->efx;
	struct efx_nic *efx = rx_queue->efx;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	size_t inlen, outlen;
	size_t inlen;
	dma_addr_t dma_addr;
	dma_addr_t dma_addr;
	int rc;
	int rc;
	int i;
	int i;
	BUILD_BUG_ON(MC_CMD_INIT_RXQ_OUT_LEN != 0);


	rx_queue->scatter_n = 0;
	rx_queue->scatter_n = 0;
	rx_queue->scatter_len = 0;
	rx_queue->scatter_len = 0;
@@ -1724,7 +1828,7 @@ static void efx_ef10_rx_init(struct efx_rx_queue *rx_queue)
	inlen = MC_CMD_INIT_RXQ_IN_LEN(entries);
	inlen = MC_CMD_INIT_RXQ_IN_LEN(entries);


	rc = efx_mcdi_rpc(efx, MC_CMD_INIT_RXQ, inbuf, inlen,
	rc = efx_mcdi_rpc(efx, MC_CMD_INIT_RXQ, inbuf, inlen,
			  outbuf, sizeof(outbuf), &outlen);
			  NULL, 0, NULL);
	if (rc)
	if (rc)
		netdev_WARN(efx->net_dev, "failed to initialise RXQ %d\n",
		netdev_WARN(efx->net_dev, "failed to initialise RXQ %d\n",
			    efx_rx_queue_index(rx_queue));
			    efx_rx_queue_index(rx_queue));
@@ -1733,7 +1837,7 @@ static void efx_ef10_rx_init(struct efx_rx_queue *rx_queue)
static void efx_ef10_rx_fini(struct efx_rx_queue *rx_queue)
static void efx_ef10_rx_fini(struct efx_rx_queue *rx_queue)
{
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_RXQ_IN_LEN);
	MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_RXQ_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_FINI_RXQ_OUT_LEN);
	MCDI_DECLARE_BUF_ERR(outbuf);
	struct efx_nic *efx = rx_queue->efx;
	struct efx_nic *efx = rx_queue->efx;
	size_t outlen;
	size_t outlen;
	int rc;
	int rc;
@@ -1895,7 +1999,7 @@ static int efx_ef10_ev_init(struct efx_channel *channel)
static void efx_ef10_ev_fini(struct efx_channel *channel)
static void efx_ef10_ev_fini(struct efx_channel *channel)
{
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_EVQ_IN_LEN);
	MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_EVQ_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_FINI_EVQ_OUT_LEN);
	MCDI_DECLARE_BUF_ERR(outbuf);
	struct efx_nic *efx = channel->efx;
	struct efx_nic *efx = channel->efx;
	size_t outlen;
	size_t outlen;
	int rc;
	int rc;
@@ -3248,6 +3352,9 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx)
	return rc;
	return rc;
}
}


/* Caller must hold efx->filter_sem for read if race against
 * efx_ef10_filter_table_remove() is possible
 */
static void efx_ef10_filter_table_restore(struct efx_nic *efx)
static void efx_ef10_filter_table_restore(struct efx_nic *efx)
{
{
	struct efx_ef10_filter_table *table = efx->filter_state;
	struct efx_ef10_filter_table *table = efx->filter_state;
@@ -3257,9 +3364,14 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
	bool failed = false;
	bool failed = false;
	int rc;
	int rc;


	WARN_ON(!rwsem_is_locked(&efx->filter_sem));

	if (!nic_data->must_restore_filters)
	if (!nic_data->must_restore_filters)
		return;
		return;


	if (!table)
		return;

	spin_lock_bh(&efx->filter_lock);
	spin_lock_bh(&efx->filter_lock);


	for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) {
	for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) {
@@ -3295,6 +3407,7 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
		nic_data->must_restore_filters = false;
		nic_data->must_restore_filters = false;
}
}


/* Caller must hold efx->filter_sem for write */
static void efx_ef10_filter_table_remove(struct efx_nic *efx)
static void efx_ef10_filter_table_remove(struct efx_nic *efx)
{
{
	struct efx_ef10_filter_table *table = efx->filter_state;
	struct efx_ef10_filter_table *table = efx->filter_state;
@@ -3303,6 +3416,10 @@ static void efx_ef10_filter_table_remove(struct efx_nic *efx)
	unsigned int filter_idx;
	unsigned int filter_idx;
	int rc;
	int rc;


	efx->filter_state = NULL;
	if (!table)
		return;

	for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) {
	for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) {
		spec = efx_ef10_filter_entry_spec(table, filter_idx);
		spec = efx_ef10_filter_entry_spec(table, filter_idx);
		if (!spec)
		if (!spec)
@@ -3328,6 +3445,9 @@ static void efx_ef10_filter_table_remove(struct efx_nic *efx)
	kfree(table);
	kfree(table);
}
}


/* Caller must hold efx->filter_sem for read if race against
 * efx_ef10_filter_table_remove() is possible
 */
static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx)
static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx)
{
{
	struct efx_ef10_filter_table *table = efx->filter_state;
	struct efx_ef10_filter_table *table = efx->filter_state;
@@ -3342,6 +3462,9 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx)
	if (!efx_dev_registered(efx))
	if (!efx_dev_registered(efx))
		return;
		return;


	if (!table)
		return;

	/* Mark old filters that may need to be removed */
	/* Mark old filters that may need to be removed */
	spin_lock_bh(&efx->filter_lock);
	spin_lock_bh(&efx->filter_lock);
	n = table->dev_uc_count < 0 ? 1 : table->dev_uc_count;
	n = table->dev_uc_count < 0 ? 1 : table->dev_uc_count;
@@ -3473,6 +3596,78 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx)
	WARN_ON(remove_failed);
	WARN_ON(remove_failed);
}
}


static int efx_ef10_set_mac_address(struct efx_nic *efx)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	bool was_enabled = efx->port_enabled;
	int rc;

	efx_device_detach_sync(efx);
	efx_net_stop(efx->net_dev);
	down_write(&efx->filter_sem);
	efx_ef10_filter_table_remove(efx);

	ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR),
			efx->net_dev->dev_addr);
	MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
		       nic_data->vport_id);
	rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
			  sizeof(inbuf), NULL, 0, NULL);

	efx_ef10_filter_table_probe(efx);
	up_write(&efx->filter_sem);
	if (was_enabled)
		efx_net_open(efx->net_dev);
	netif_device_attach(efx->net_dev);

#if !defined(CONFIG_SFC_SRIOV)
	if (rc == -EPERM)
		netif_err(efx, drv, efx->net_dev,
			  "Cannot change MAC address; use sfboot to enable mac-spoofing"
			  " on this interface\n");
#else
	if (rc == -EPERM) {
		struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;

		/* Switch to PF and change MAC address on vport */
		if (efx->pci_dev->is_virtfn && pci_dev_pf) {
			struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);

			if (!efx_ef10_sriov_set_vf_mac(efx_pf,
						       nic_data->vf_index,
						       efx->net_dev->dev_addr))
				return 0;
		}
		netif_err(efx, drv, efx->net_dev,
			  "Cannot change MAC address; use sfboot to enable mac-spoofing"
			  " on this interface\n");
	} else if (efx->pci_dev->is_virtfn) {
		/* Successfully changed by VF (with MAC spoofing), so update the
		 * parent PF if possible.
		 */
		struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;

		if (pci_dev_pf) {
			struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
			struct efx_ef10_nic_data *nic_data = efx_pf->nic_data;
			unsigned int i;

			for (i = 0; i < efx_pf->vf_count; ++i) {
				struct ef10_vf *vf = nic_data->vf + i;

				if (vf->efx == efx) {
					ether_addr_copy(vf->mac,
							efx->net_dev->dev_addr);
					return 0;
				}
			}
		}
	}
#endif
	return rc;
}

static int efx_ef10_mac_reconfigure(struct efx_nic *efx)
static int efx_ef10_mac_reconfigure(struct efx_nic *efx)
{
{
	efx_ef10_filter_sync_rx_mode(efx);
	efx_ef10_filter_sync_rx_mode(efx);
@@ -3480,6 +3675,13 @@ static int efx_ef10_mac_reconfigure(struct efx_nic *efx)
	return efx_mcdi_set_mac(efx);
	return efx_mcdi_set_mac(efx);
}
}


static int efx_ef10_mac_reconfigure_vf(struct efx_nic *efx)
{
	efx_ef10_filter_sync_rx_mode(efx);

	return 0;
}

static int efx_ef10_start_bist(struct efx_nic *efx, u32 bist_type)
static int efx_ef10_start_bist(struct efx_nic *efx, u32 bist_type)
{
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN);
	MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN);
@@ -3818,7 +4020,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.dimension_resources = efx_ef10_dimension_resources,
	.dimension_resources = efx_ef10_dimension_resources,
	.init = efx_ef10_init_nic,
	.init = efx_ef10_init_nic,
	.fini = efx_port_dummy_op_void,
	.fini = efx_port_dummy_op_void,
	.map_reset_reason = efx_mcdi_map_reset_reason,
	.map_reset_reason = efx_ef10_map_reset_reason,
	.map_reset_flags = efx_ef10_map_reset_flags,
	.map_reset_flags = efx_ef10_map_reset_flags,
	.reset = efx_ef10_reset,
	.reset = efx_ef10_reset,
	.probe_port = efx_mcdi_port_probe,
	.probe_port = efx_mcdi_port_probe,
@@ -3833,7 +4035,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.stop_stats = efx_port_dummy_op_void,
	.stop_stats = efx_port_dummy_op_void,
	.set_id_led = efx_mcdi_set_id_led,
	.set_id_led = efx_mcdi_set_id_led,
	.push_irq_moderation = efx_ef10_push_irq_moderation,
	.push_irq_moderation = efx_ef10_push_irq_moderation,
	.reconfigure_mac = efx_ef10_mac_reconfigure,
	.reconfigure_mac = efx_ef10_mac_reconfigure_vf,
	.check_mac_fault = efx_mcdi_mac_check_fault,
	.check_mac_fault = efx_mcdi_mac_check_fault,
	.reconfigure_port = efx_mcdi_port_reconfigure,
	.reconfigure_port = efx_mcdi_port_reconfigure,
	.get_wol = efx_ef10_get_wol_vf,
	.get_wol = efx_ef10_get_wol_vf,
@@ -3890,6 +4092,9 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.vswitching_restore = efx_ef10_vswitching_restore_vf,
	.vswitching_restore = efx_ef10_vswitching_restore_vf,
	.vswitching_remove = efx_ef10_vswitching_remove_vf,
	.vswitching_remove = efx_ef10_vswitching_remove_vf,
#endif
#endif
	.get_mac_address = efx_ef10_get_mac_address_vf,
	.set_mac_address = efx_ef10_set_mac_address,

	.revision = EFX_REV_HUNT_A0,
	.revision = EFX_REV_HUNT_A0,
	.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
	.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
	.rx_prefix_size = ES_DZ_RX_PREFIX_SIZE,
	.rx_prefix_size = ES_DZ_RX_PREFIX_SIZE,
@@ -3916,7 +4121,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.dimension_resources = efx_ef10_dimension_resources,
	.dimension_resources = efx_ef10_dimension_resources,
	.init = efx_ef10_init_nic,
	.init = efx_ef10_init_nic,
	.fini = efx_port_dummy_op_void,
	.fini = efx_port_dummy_op_void,
	.map_reset_reason = efx_mcdi_map_reset_reason,
	.map_reset_reason = efx_ef10_map_reset_reason,
	.map_reset_flags = efx_ef10_map_reset_flags,
	.map_reset_flags = efx_ef10_map_reset_flags,
	.reset = efx_ef10_reset,
	.reset = efx_ef10_reset,
	.probe_port = efx_mcdi_port_probe,
	.probe_port = efx_mcdi_port_probe,
@@ -3995,7 +4200,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.sriov_configure = efx_ef10_sriov_configure,
	.sriov_configure = efx_ef10_sriov_configure,
	.sriov_init = efx_ef10_sriov_init,
	.sriov_init = efx_ef10_sriov_init,
	.sriov_fini = efx_ef10_sriov_fini,
	.sriov_fini = efx_ef10_sriov_fini,
	.sriov_mac_address_changed = efx_ef10_sriov_mac_address_changed,
	.sriov_wanted = efx_ef10_sriov_wanted,
	.sriov_wanted = efx_ef10_sriov_wanted,
	.sriov_reset = efx_ef10_sriov_reset,
	.sriov_reset = efx_ef10_sriov_reset,
	.sriov_flr = efx_ef10_sriov_flr,
	.sriov_flr = efx_ef10_sriov_flr,
@@ -4003,10 +4207,13 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan,
	.sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan,
	.sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk,
	.sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk,
	.sriov_get_vf_config = efx_ef10_sriov_get_vf_config,
	.sriov_get_vf_config = efx_ef10_sriov_get_vf_config,
	.sriov_set_vf_link_state = efx_ef10_sriov_set_vf_link_state,
	.vswitching_probe = efx_ef10_vswitching_probe_pf,
	.vswitching_probe = efx_ef10_vswitching_probe_pf,
	.vswitching_restore = efx_ef10_vswitching_restore_pf,
	.vswitching_restore = efx_ef10_vswitching_restore_pf,
	.vswitching_remove = efx_ef10_vswitching_remove_pf,
	.vswitching_remove = efx_ef10_vswitching_remove_pf,
#endif
#endif
	.get_mac_address = efx_ef10_get_mac_address_pf,
	.set_mac_address = efx_ef10_set_mac_address,


	.revision = EFX_REV_HUNT_A0,
	.revision = EFX_REV_HUNT_A0,
	.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
	.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
+314 −6
Original line number Original line Diff line number Diff line
@@ -57,15 +57,29 @@ static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
				  unsigned int vswitch_type)
				  unsigned int vswitch_type)
{
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_VSWITCH_ALLOC_IN_LEN);
	MCDI_DECLARE_BUF(inbuf, MC_CMD_VSWITCH_ALLOC_IN_LEN);
	int rc;


	MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
	MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
	MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_TYPE, vswitch_type);
	MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_TYPE, vswitch_type);
	MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_NUM_VLAN_TAGS, 0);
	MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_NUM_VLAN_TAGS, 2);
	MCDI_POPULATE_DWORD_1(inbuf, VSWITCH_ALLOC_IN_FLAGS,
	MCDI_POPULATE_DWORD_1(inbuf, VSWITCH_ALLOC_IN_FLAGS,
			      VSWITCH_ALLOC_IN_FLAG_AUTO_PORT, 0);
			      VSWITCH_ALLOC_IN_FLAG_AUTO_PORT, 0);


	return efx_mcdi_rpc(efx, MC_CMD_VSWITCH_ALLOC, inbuf, sizeof(inbuf),
	/* Quietly try to allocate 2 VLAN tags */
	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VSWITCH_ALLOC, inbuf, sizeof(inbuf),
				NULL, 0, NULL);
				NULL, 0, NULL);

	/* If 2 VLAN tags is too many, revert to trying with 1 VLAN tags */
	if (rc == -EPROTO) {
		MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_NUM_VLAN_TAGS, 1);
		rc = efx_mcdi_rpc(efx, MC_CMD_VSWITCH_ALLOC, inbuf,
				  sizeof(inbuf), NULL, 0, NULL);
	} else if (rc) {
		efx_mcdi_display_error(efx, MC_CMD_VSWITCH_ALLOC,
				       MC_CMD_VSWITCH_ALLOC_IN_LEN,
				       NULL, 0, rc);
	}
	return rc;
}
}


static int efx_ef10_vswitch_free(struct efx_nic *efx, unsigned int port_id)
static int efx_ef10_vswitch_free(struct efx_nic *efx, unsigned int port_id)
@@ -81,6 +95,7 @@ static int efx_ef10_vswitch_free(struct efx_nic *efx, unsigned int port_id)
static int efx_ef10_vport_alloc(struct efx_nic *efx,
static int efx_ef10_vport_alloc(struct efx_nic *efx,
				unsigned int port_id_in,
				unsigned int port_id_in,
				unsigned int vport_type,
				unsigned int vport_type,
				u16 vlan,
				unsigned int *port_id_out)
				unsigned int *port_id_out)
{
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ALLOC_IN_LEN);
	MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ALLOC_IN_LEN);
@@ -92,9 +107,13 @@ static int efx_ef10_vport_alloc(struct efx_nic *efx,


	MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_UPSTREAM_PORT_ID, port_id_in);
	MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_UPSTREAM_PORT_ID, port_id_in);
	MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_TYPE, vport_type);
	MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_TYPE, vport_type);
	MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_NUM_VLAN_TAGS, 0);
	MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_NUM_VLAN_TAGS,
		       (vlan != EFX_EF10_NO_VLAN));
	MCDI_POPULATE_DWORD_1(inbuf, VPORT_ALLOC_IN_FLAGS,
	MCDI_POPULATE_DWORD_1(inbuf, VPORT_ALLOC_IN_FLAGS,
			      VPORT_ALLOC_IN_FLAG_AUTO_PORT, 0);
			      VPORT_ALLOC_IN_FLAG_AUTO_PORT, 0);
	if (vlan != EFX_EF10_NO_VLAN)
		MCDI_POPULATE_DWORD_1(inbuf, VPORT_ALLOC_IN_VLAN_TAGS,
				      VPORT_ALLOC_IN_VLAN_TAG_0, vlan);


	rc = efx_mcdi_rpc(efx, MC_CMD_VPORT_ALLOC, inbuf, sizeof(inbuf),
	rc = efx_mcdi_rpc(efx, MC_CMD_VPORT_ALLOC, inbuf, sizeof(inbuf),
			  outbuf, sizeof(outbuf), &outlen);
			  outbuf, sizeof(outbuf), &outlen);
@@ -160,6 +179,8 @@ static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx)
			efx_ef10_vport_free(efx, vf->vport_id);
			efx_ef10_vport_free(efx, vf->vport_id);
			vf->vport_id = 0;
			vf->vport_id = 0;
		}
		}

		vf->efx = NULL;
	}
	}
}
}


@@ -184,7 +205,7 @@ static int efx_ef10_sriov_assign_vf_vport(struct efx_nic *efx,


	rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
	rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
				  MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
				  MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
				  &vf->vport_id);
				  vf->vlan, &vf->vport_id);
	if (rc)
	if (rc)
		return rc;
		return rc;


@@ -215,6 +236,8 @@ static int efx_ef10_sriov_alloc_vf_vswitching(struct efx_nic *efx)


	for (i = 0; i < efx->vf_count; i++) {
	for (i = 0; i < efx->vf_count; i++) {
		random_ether_addr(nic_data->vf[i].mac);
		random_ether_addr(nic_data->vf[i].mac);
		nic_data->vf[i].efx = NULL;
		nic_data->vf[i].vlan = EFX_EF10_NO_VLAN;


		rc = efx_ef10_sriov_assign_vf_vport(efx, i);
		rc = efx_ef10_sriov_assign_vf_vport(efx, i);
		if (rc)
		if (rc)
@@ -268,7 +291,7 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)


	rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
	rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
				  MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
				  MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
				  &nic_data->vport_id);
				  EFX_EF10_NO_VLAN, &nic_data->vport_id);
	if (rc)
	if (rc)
		goto fail2;
		goto fail2;


@@ -428,3 +451,288 @@ void efx_ef10_sriov_fini(struct efx_nic *efx)
	else
	else
		netif_dbg(efx, drv, efx->net_dev, "SRIOV disabled\n");
		netif_dbg(efx, drv, efx->net_dev, "SRIOV disabled\n");
}
}

static int efx_ef10_vport_del_vf_mac(struct efx_nic *efx, unsigned int port_id,
				     u8 *mac)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
	MCDI_DECLARE_BUF_ERR(outbuf);
	size_t outlen;
	int rc;

	MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
	ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);

	rc = efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);

	return rc;
}

int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, u8 *mac)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct ef10_vf *vf;
	int rc;

	if (!nic_data->vf)
		return -EOPNOTSUPP;

	if (vf_i >= efx->vf_count)
		return -EINVAL;
	vf = nic_data->vf + vf_i;

	if (vf->efx) {
		efx_device_detach_sync(vf->efx);
		efx_net_stop(vf->efx->net_dev);

		down_write(&vf->efx->filter_sem);
		vf->efx->type->filter_table_remove(vf->efx);

		rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED);
		if (rc) {
			up_write(&vf->efx->filter_sem);
			return rc;
		}
	}

	rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i);
	if (rc)
		return rc;

	if (!is_zero_ether_addr(vf->mac)) {
		rc = efx_ef10_vport_del_vf_mac(efx, vf->vport_id, vf->mac);
		if (rc)
			return rc;
	}

	if (!is_zero_ether_addr(mac)) {
		rc = efx_ef10_vport_add_mac(efx, vf->vport_id, mac);
		if (rc) {
			eth_zero_addr(vf->mac);
			goto fail;
		}
		if (vf->efx)
			ether_addr_copy(vf->efx->net_dev->dev_addr, mac);
	}

	ether_addr_copy(vf->mac, mac);

	rc = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i);
	if (rc)
		goto fail;

	if (vf->efx) {
		/* VF cannot use the vport_id that the PF created */
		rc = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED);
		if (rc) {
			up_write(&vf->efx->filter_sem);
			return rc;
		}
		vf->efx->type->filter_table_probe(vf->efx);
		up_write(&vf->efx->filter_sem);
		efx_net_open(vf->efx->net_dev);
		netif_device_attach(vf->efx->net_dev);
	}

	return 0;

fail:
	memset(vf->mac, 0, ETH_ALEN);
	return rc;
}

int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
			       u8 qos)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct ef10_vf *vf;
	u16 old_vlan, new_vlan;
	int rc = 0, rc2 = 0;

	if (vf_i >= efx->vf_count)
		return -EINVAL;
	if (qos != 0)
		return -EINVAL;

	vf = nic_data->vf + vf_i;

	new_vlan = (vlan == 0) ? EFX_EF10_NO_VLAN : vlan;
	if (new_vlan == vf->vlan)
		return 0;

	if (vf->efx) {
		efx_device_detach_sync(vf->efx);
		efx_net_stop(vf->efx->net_dev);

		down_write(&vf->efx->filter_sem);
		vf->efx->type->filter_table_remove(vf->efx);

		rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED);
		if (rc)
			goto restore_filters;
	}

	if (vf->vport_assigned) {
		rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i);
		if (rc) {
			netif_warn(efx, drv, efx->net_dev,
				   "Failed to change vlan on VF %d.\n", vf_i);
			netif_warn(efx, drv, efx->net_dev,
				   "This is likely because the VF is bound to a driver in a VM.\n");
			netif_warn(efx, drv, efx->net_dev,
				   "Please unload the driver in the VM.\n");
			goto restore_vadaptor;
		}
		vf->vport_assigned = 0;
	}

	if (!is_zero_ether_addr(vf->mac)) {
		rc = efx_ef10_vport_del_mac(efx, vf->vport_id, vf->mac);
		if (rc)
			goto restore_evb_port;
	}

	if (vf->vport_id) {
		rc = efx_ef10_vport_free(efx, vf->vport_id);
		if (rc)
			goto restore_mac;
		vf->vport_id = 0;
	}

	/* Do the actual vlan change */
	old_vlan = vf->vlan;
	vf->vlan = new_vlan;

	/* Restore everything in reverse order */
	rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
				  MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
				  vf->vlan, &vf->vport_id);
	if (rc)
		goto reset_nic;

restore_mac:
	if (!is_zero_ether_addr(vf->mac)) {
		rc2 = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac);
		if (rc2) {
			eth_zero_addr(vf->mac);
			goto reset_nic;
		}
	}

restore_evb_port:
	rc2 = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i);
	if (rc2)
		goto reset_nic;
	else
		vf->vport_assigned = 1;

restore_vadaptor:
	if (vf->efx) {
		rc2 = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED);
		if (rc2)
			goto reset_nic;
	}

restore_filters:
	if (vf->efx) {
		rc2 = vf->efx->type->filter_table_probe(vf->efx);
		if (rc2)
			goto reset_nic;

		up_write(&vf->efx->filter_sem);

		rc2 = efx_net_open(vf->efx->net_dev);
		if (rc2)
			goto reset_nic;

		netif_device_attach(vf->efx->net_dev);
	}
	return rc;

reset_nic:
	if (vf->efx) {
		up_write(&vf->efx->filter_sem);
		netif_err(efx, drv, efx->net_dev,
			  "Failed to restore VF - scheduling reset.\n");
		efx_schedule_reset(vf->efx, RESET_TYPE_DATAPATH);
	} else {
		netif_err(efx, drv, efx->net_dev,
			  "Failed to restore the VF and cannot reset the VF "
			  "- VF is not functional.\n");
		netif_err(efx, drv, efx->net_dev,
			  "Please reload the driver attached to the VF.\n");
	}

	return rc ? rc : rc2;
}

int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf_i,
				   bool spoofchk)
{
	return spoofchk ? -EOPNOTSUPP : 0;
}

int efx_ef10_sriov_set_vf_link_state(struct efx_nic *efx, int vf_i,
				     int link_state)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_STATE_MODE_IN_LEN);
	struct efx_ef10_nic_data *nic_data = efx->nic_data;

	BUILD_BUG_ON(IFLA_VF_LINK_STATE_AUTO !=
		     MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_AUTO);
	BUILD_BUG_ON(IFLA_VF_LINK_STATE_ENABLE !=
		     MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_UP);
	BUILD_BUG_ON(IFLA_VF_LINK_STATE_DISABLE !=
		     MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_DOWN);
	MCDI_POPULATE_DWORD_2(inbuf, LINK_STATE_MODE_IN_FUNCTION,
			      LINK_STATE_MODE_IN_FUNCTION_PF,
			      nic_data->pf_index,
			      LINK_STATE_MODE_IN_FUNCTION_VF, vf_i);
	MCDI_SET_DWORD(inbuf, LINK_STATE_MODE_IN_NEW_MODE, link_state);
	return efx_mcdi_rpc(efx, MC_CMD_LINK_STATE_MODE, inbuf, sizeof(inbuf),
			    NULL, 0, NULL); /* don't care what old mode was */
}

int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf_i,
				 struct ifla_vf_info *ivf)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_STATE_MODE_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_LINK_STATE_MODE_OUT_LEN);

	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct ef10_vf *vf;
	size_t outlen;
	int rc;

	if (vf_i >= efx->vf_count)
		return -EINVAL;

	if (!nic_data->vf)
		return -EOPNOTSUPP;

	vf = nic_data->vf + vf_i;

	ivf->vf = vf_i;
	ivf->min_tx_rate = 0;
	ivf->max_tx_rate = 0;
	ether_addr_copy(ivf->mac, vf->mac);
	ivf->vlan = (vf->vlan == EFX_EF10_NO_VLAN) ? 0 : vf->vlan;
	ivf->qos = 0;

	MCDI_POPULATE_DWORD_2(inbuf, LINK_STATE_MODE_IN_FUNCTION,
			      LINK_STATE_MODE_IN_FUNCTION_PF,
			      nic_data->pf_index,
			      LINK_STATE_MODE_IN_FUNCTION_VF, vf_i);
	MCDI_SET_DWORD(inbuf, LINK_STATE_MODE_IN_NEW_MODE,
		       MC_CMD_LINK_STATE_MODE_IN_DO_NOT_CHANGE);
	rc = efx_mcdi_rpc(efx, MC_CMD_LINK_STATE_MODE, inbuf, sizeof(inbuf),
			  outbuf, sizeof(outbuf), &outlen);
	if (rc)
		return rc;
	if (outlen < MC_CMD_LINK_STATE_MODE_OUT_LEN)
		return -EIO;
	ivf->linkstate = MCDI_DWORD(outbuf, LINK_STATE_MODE_OUT_OLD_MODE);

	return 0;
}
+15 −21

File changed.

Preview size limit exceeded, changes collapsed.

+49 −16

File changed.

Preview size limit exceeded, changes collapsed.

+5 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,9 @@
#define EFX_MEM_BAR 2
#define EFX_MEM_BAR 2
#define EFX_MEM_VF_BAR 0
#define EFX_MEM_VF_BAR 0


int efx_net_open(struct net_device *net_dev);
int efx_net_stop(struct net_device *net_dev);

/* TX */
/* TX */
int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
@@ -74,6 +77,8 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);


/* Filters */
/* Filters */


void efx_mac_reconfigure(struct efx_nic *efx);

/**
/**
 * efx_filter_insert_filter - add or replace a filter
 * efx_filter_insert_filter - add or replace a filter
 * @efx: NIC in which to insert the filter
 * @efx: NIC in which to insert the filter
Loading