Commit 9b1b31d5 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sfc-remove-nic_data-usage-in-common-code'



Edward Cree says:

====================
sfc: remove nic_data usage in common code

efx->nic_data should only be used from NIC-specific code (i.e. nic_type
 functions and things they call), in files like ef10[_sriov].c and
 siena.c.  This series refactors several nic_data usages from common
 code (mainly in mcdi_filters.c) into nic_type functions, in preparation
 for the upcoming ef100 driver which will use those functions but have
 its own struct layout for efx->nic_data distinct from ef10's.
After this series, one nic_data usage (in ptp.c) remains; it wasn't
 clear to me how to fix it, and ef100 devices don't yet have PTP support
 (so the initial ef100 driver will not call that code).
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a90f704a 9b46132c
Loading
Loading
Loading
Loading
+132 −82
Original line number Diff line number Diff line
@@ -553,7 +553,7 @@ static int efx_ef10_probe(struct efx_nic *efx)

	efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID;

	nic_data->vport_id = EVB_PORT_ID_ASSIGNED;
	efx->vport_id = EVB_PORT_ID_ASSIGNED;

	/* In case we're recovering from a crash (kexec), we want to
	 * cancel any outstanding request by the previous user of this
@@ -1281,13 +1281,13 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
		nic_data->must_check_datapath_caps = false;
	}

	if (nic_data->must_realloc_vis) {
	if (efx->must_realloc_vis) {
		/* We cannot let the number of VIs change now */
		rc = efx_ef10_alloc_vis(efx, nic_data->n_allocated_vis,
					nic_data->n_allocated_vis);
		if (rc)
			return rc;
		nic_data->must_realloc_vis = false;
		efx->must_realloc_vis = false;
	}

	if (nic_data->must_restore_piobufs && nic_data->n_piobufs) {
@@ -1326,16 +1326,15 @@ static void efx_ef10_table_reset_mc_allocations(struct efx_nic *efx)
#endif

	/* All our allocations have been reset */
	nic_data->must_realloc_vis = true;
	nic_data->must_restore_rss_contexts = true;
	nic_data->must_restore_filters = true;
	efx->must_realloc_vis = true;
	efx_mcdi_filter_table_reset_mc_allocations(efx);
	nic_data->must_restore_piobufs = true;
	efx_ef10_forget_old_piobufs(efx);
	efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID;

	/* Driver-created vswitches and vports must be re-created */
	nic_data->must_probe_vswitching = true;
	nic_data->vport_id = EVB_PORT_ID_ASSIGNED;
	efx->vport_id = EVB_PORT_ID_ASSIGNED;
#ifdef CONFIG_SFC_SRIOV
	if (nic_data->vf)
		for (i = 0; i < efx->vf_count; i++)
@@ -2389,6 +2388,86 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
	}
}

static int efx_ef10_probe_multicast_chaining(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	unsigned int enabled, implemented;
	bool want_workaround_26807;
	int rc;

	rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled);
	if (rc == -ENOSYS) {
		/* GET_WORKAROUNDS was implemented before this workaround,
		 * thus it must be unavailable in this firmware.
		 */
		nic_data->workaround_26807 = false;
		return 0;
	}
	if (rc)
		return rc;
	want_workaround_26807 =
		implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807;
	nic_data->workaround_26807 =
		!!(enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807);

	if (want_workaround_26807 && !nic_data->workaround_26807) {
		unsigned int flags;

		rc = efx_mcdi_set_workaround(efx,
					     MC_CMD_WORKAROUND_BUG26807,
					     true, &flags);
		if (!rc) {
			if (flags &
			    1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN) {
				netif_info(efx, drv, efx->net_dev,
					   "other functions on NIC have been reset\n");

				/* With MCFW v4.6.x and earlier, the
				 * boot count will have incremented,
				 * so re-read the warm_boot_count
				 * value now to ensure this function
				 * doesn't think it has changed next
				 * time it checks.
				 */
				rc = efx_ef10_get_warm_boot_count(efx);
				if (rc >= 0) {
					nic_data->warm_boot_count = rc;
					rc = 0;
				}
			}
			nic_data->workaround_26807 = true;
		} else if (rc == -EPERM) {
			rc = 0;
		}
	}
	return rc;
}

static int efx_ef10_filter_table_probe(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	int rc = efx_ef10_probe_multicast_chaining(efx);
	struct efx_mcdi_filter_vlan *vlan;

	if (rc)
		return rc;
	rc = efx_mcdi_filter_table_probe(efx, nic_data->workaround_26807);

	if (rc)
		return rc;

	list_for_each_entry(vlan, &nic_data->vlan_list, list) {
		rc = efx_mcdi_filter_add_vlan(efx, vlan->vid);
		if (rc)
			goto fail_add_vlan;
	}
	return 0;

fail_add_vlan:
	efx_mcdi_filter_table_remove(efx);
	return rc;
}

/* This creates an entry in the RX descriptor queue */
static inline void
efx_ef10_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
@@ -2464,75 +2543,14 @@ static int efx_ef10_ev_init(struct efx_channel *channel)
{
	struct efx_nic *efx = channel->efx;
	struct efx_ef10_nic_data *nic_data;
	unsigned int enabled, implemented;
	bool use_v2, cut_thru;
	int rc;

	nic_data = efx->nic_data;
	use_v2 = nic_data->datapath_caps2 &
			    1 << MC_CMD_GET_CAPABILITIES_V2_OUT_INIT_EVQ_V2_LBN;
	cut_thru = !(nic_data->datapath_caps &
			      1 << MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_LBN);
	rc = efx_mcdi_ev_init(channel, cut_thru, use_v2);

	/* IRQ return is ignored */
	if (channel->channel || rc)
		return rc;

	/* Successfully created event queue on channel 0 */
	rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled);
	if (rc == -ENOSYS) {
		/* GET_WORKAROUNDS was implemented before this workaround,
		 * thus it must be unavailable in this firmware.
		 */
		nic_data->workaround_26807 = false;
		rc = 0;
	} else if (rc) {
		goto fail;
	} else {
		nic_data->workaround_26807 =
			!!(enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807);

		if (implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807 &&
		    !nic_data->workaround_26807) {
			unsigned int flags;

			rc = efx_mcdi_set_workaround(efx,
						     MC_CMD_WORKAROUND_BUG26807,
						     true, &flags);

			if (!rc) {
				if (flags &
				    1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN) {
					netif_info(efx, drv, efx->net_dev,
						   "other functions on NIC have been reset\n");

					/* With MCFW v4.6.x and earlier, the
					 * boot count will have incremented,
					 * so re-read the warm_boot_count
					 * value now to ensure this function
					 * doesn't think it has changed next
					 * time it checks.
					 */
					rc = efx_ef10_get_warm_boot_count(efx);
					if (rc >= 0) {
						nic_data->warm_boot_count = rc;
						rc = 0;
					}
				}
				nic_data->workaround_26807 = true;
			} else if (rc == -EPERM) {
				rc = 0;
			}
		}
	}

	if (!rc)
		return 0;

fail:
	efx_mcdi_ev_fini(channel);
	return rc;
	return efx_mcdi_ev_init(channel, cut_thru, use_v2);
}

static void efx_ef10_handle_rx_wrong_queue(struct efx_rx_queue *rx_queue,
@@ -3100,16 +3118,15 @@ void efx_ef10_handle_drain_event(struct efx_nic *efx)

static int efx_ef10_fini_dmaq(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_channel *channel;
	struct efx_tx_queue *tx_queue;
	struct efx_rx_queue *rx_queue;
	struct efx_channel *channel;
	int pending;

	/* If the MC has just rebooted, the TX/RX queues will have already been
	 * torn down, but efx->active_queues needs to be set to zero.
	 */
	if (nic_data->must_realloc_vis) {
	if (efx->must_realloc_vis) {
		atomic_set(&efx->active_queues, 0);
		return 0;
	}
@@ -3158,22 +3175,22 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
	efx_mcdi_filter_table_remove(efx);
	up_write(&efx->filter_sem);

	rc = efx_ef10_vadaptor_free(efx, nic_data->vport_id);
	rc = efx_ef10_vadaptor_free(efx, efx->vport_id);
	if (rc)
		goto restore_filters;

	ether_addr_copy(mac_old, nic_data->vport_mac);
	rc = efx_ef10_vport_del_mac(efx, nic_data->vport_id,
	rc = efx_ef10_vport_del_mac(efx, efx->vport_id,
				    nic_data->vport_mac);
	if (rc)
		goto restore_vadaptor;

	rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id,
	rc = efx_ef10_vport_add_mac(efx, efx->vport_id,
				    efx->net_dev->dev_addr);
	if (!rc) {
		ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr);
	} else {
		rc2 = efx_ef10_vport_add_mac(efx, nic_data->vport_id, mac_old);
		rc2 = efx_ef10_vport_add_mac(efx, efx->vport_id, mac_old);
		if (rc2) {
			/* Failed to add original MAC, so clear vport_mac */
			eth_zero_addr(nic_data->vport_mac);
@@ -3182,12 +3199,12 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
	}

restore_vadaptor:
	rc2 = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
	rc2 = efx_ef10_vadaptor_alloc(efx, efx->vport_id);
	if (rc2)
		goto reset_nic;
restore_filters:
	down_write(&efx->filter_sem);
	rc2 = efx_mcdi_filter_table_probe(efx);
	rc2 = efx_ef10_filter_table_probe(efx);
	up_write(&efx->filter_sem);
	if (rc2)
		goto reset_nic;
@@ -3225,11 +3242,11 @@ static int efx_ef10_set_mac_address(struct efx_nic *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);
		       efx->vport_id);
	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
				sizeof(inbuf), NULL, 0, NULL);

	efx_mcdi_filter_table_probe(efx);
	efx_ef10_filter_table_probe(efx);
	up_write(&efx->filter_sem);
	mutex_unlock(&efx->mac_lock);

@@ -3961,6 +3978,35 @@ out_unlock:
	return rc;
}

/* EF10 may have multiple datapath firmware variants within a
 * single version.  Report which variants are running.
 */
static size_t efx_ef10_print_additional_fwver(struct efx_nic *efx, char *buf,
					      size_t len)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;

	return scnprintf(buf, len, " rx%x tx%x",
			 nic_data->rx_dpcpu_fw_id,
			 nic_data->tx_dpcpu_fw_id);
}

static unsigned int ef10_check_caps(const struct efx_nic *efx,
				    u8 flag,
				    u32 offset)
{
	const struct efx_ef10_nic_data *nic_data = efx->nic_data;

	switch (offset) {
	case(MC_CMD_GET_CAPABILITIES_V4_OUT_FLAGS1_OFST):
		return nic_data->datapath_caps & BIT_ULL(flag);
	case(MC_CMD_GET_CAPABILITIES_V4_OUT_FLAGS2_OFST):
		return nic_data->datapath_caps2 & BIT_ULL(flag);
	default:
		return 0;
	}
}

#define EF10_OFFLOAD_FEATURES		\
	(NETIF_F_IP_CSUM |		\
	 NETIF_F_HW_VLAN_CTAG_FILTER |	\
@@ -4027,7 +4073,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.ev_process = efx_ef10_ev_process,
	.ev_read_ack = efx_ef10_ev_read_ack,
	.ev_test_generate = efx_ef10_ev_test_generate,
	.filter_table_probe = efx_mcdi_filter_table_probe,
	.filter_table_probe = efx_ef10_filter_table_probe,
	.filter_table_restore = efx_mcdi_filter_table_restore,
	.filter_table_remove = efx_mcdi_filter_table_remove,
	.filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
@@ -4073,6 +4119,8 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
			    1 << HWTSTAMP_FILTER_ALL,
	.rx_hash_key_size = 40,
	.check_caps = ef10_check_caps,
	.print_additional_fwver = efx_ef10_print_additional_fwver,
};

const struct efx_nic_type efx_hunt_a0_nic_type = {
@@ -4139,7 +4187,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.ev_process = efx_ef10_ev_process,
	.ev_read_ack = efx_ef10_ev_read_ack,
	.ev_test_generate = efx_ef10_ev_test_generate,
	.filter_table_probe = efx_mcdi_filter_table_probe,
	.filter_table_probe = efx_ef10_filter_table_probe,
	.filter_table_restore = efx_mcdi_filter_table_restore,
	.filter_table_remove = efx_mcdi_filter_table_remove,
	.filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
@@ -4208,4 +4256,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
			    1 << HWTSTAMP_FILTER_ALL,
	.rx_hash_key_size = 40,
	.check_caps = ef10_check_caps,
	.print_additional_fwver = efx_ef10_print_additional_fwver,
};
+13 −14
Original line number Diff line number Diff line
@@ -232,15 +232,14 @@ fail:

static int efx_ef10_vadaptor_alloc_set_features(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	u32 port_flags;
	int rc;

	rc = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
	rc = efx_ef10_vadaptor_alloc(efx, efx->vport_id);
	if (rc)
		goto fail_vadaptor_alloc;

	rc = efx_ef10_vadaptor_query(efx, nic_data->vport_id,
	rc = efx_ef10_vadaptor_query(efx, efx->vport_id,
				     &port_flags, NULL, NULL);
	if (rc)
		goto fail_vadaptor_query;
@@ -281,11 +280,11 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)

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

	rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id, net_dev->dev_addr);
	rc = efx_ef10_vport_add_mac(efx, efx->vport_id, net_dev->dev_addr);
	if (rc)
		goto fail3;
	ether_addr_copy(nic_data->vport_mac, net_dev->dev_addr);
@@ -296,11 +295,11 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)

	return 0;
fail4:
	efx_ef10_vport_del_mac(efx, nic_data->vport_id, nic_data->vport_mac);
	efx_ef10_vport_del_mac(efx, efx->vport_id, nic_data->vport_mac);
	eth_zero_addr(nic_data->vport_mac);
fail3:
	efx_ef10_vport_free(efx, nic_data->vport_id);
	nic_data->vport_id = EVB_PORT_ID_ASSIGNED;
	efx_ef10_vport_free(efx, efx->vport_id);
	efx->vport_id = EVB_PORT_ID_ASSIGNED;
fail2:
	efx_ef10_vswitch_free(efx, EVB_PORT_ID_ASSIGNED);
fail1:
@@ -355,22 +354,22 @@ void efx_ef10_vswitching_remove_pf(struct efx_nic *efx)

	efx_ef10_sriov_free_vf_vswitching(efx);

	efx_ef10_vadaptor_free(efx, nic_data->vport_id);
	efx_ef10_vadaptor_free(efx, efx->vport_id);

	if (nic_data->vport_id == EVB_PORT_ID_ASSIGNED)
	if (efx->vport_id == EVB_PORT_ID_ASSIGNED)
		return; /* No vswitch was ever created */

	if (!is_zero_ether_addr(nic_data->vport_mac)) {
		efx_ef10_vport_del_mac(efx, nic_data->vport_id,
		efx_ef10_vport_del_mac(efx, efx->vport_id,
				       efx->net_dev->dev_addr);
		eth_zero_addr(nic_data->vport_mac);
	}
	efx_ef10_vport_free(efx, nic_data->vport_id);
	nic_data->vport_id = EVB_PORT_ID_ASSIGNED;
	efx_ef10_vport_free(efx, efx->vport_id);
	efx->vport_id = EVB_PORT_ID_ASSIGNED;

	/* Only free the vswitch if no VFs are assigned */
	if (!pci_vfs_assigned(efx->pci_dev))
		efx_ef10_vswitch_free(efx, nic_data->vport_id);
		efx_ef10_vswitch_free(efx, efx->vport_id);
}

void efx_ef10_vswitching_remove_vf(struct efx_nic *efx)
+9 −16
Original line number Diff line number Diff line
@@ -1425,15 +1425,9 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
			   le16_to_cpu(ver_words[2]),
			   le16_to_cpu(ver_words[3]));

	/* EF10 may have multiple datapath firmware variants within a
	 * single version.  Report which variants are running.
	 */
	if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
		struct efx_ef10_nic_data *nic_data = efx->nic_data;

		offset += scnprintf(buf + offset, len - offset, " rx%x tx%x",
				    nic_data->rx_dpcpu_fw_id,
				    nic_data->tx_dpcpu_fw_id);
	if (efx->type->print_additional_fwver)
		offset += efx->type->print_additional_fwver(efx, buf + offset,
							    len - offset);

	/* It's theoretically possible for the string to exceed 31
	 * characters, though in practice the first three version
@@ -1441,7 +1435,6 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
	 */
	if (WARN_ON(offset >= len))
		buf[0] = 0;
	}

	return;

+12 −0
Original line number Diff line number Diff line
@@ -326,6 +326,18 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define MCDI_EVENT_FIELD(_ev, _field)			\
	EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)

#define MCDI_CAPABILITY(field)						\
	MC_CMD_GET_CAPABILITIES_V4_OUT_ ## field ## _LBN

#define MCDI_CAPABILITY_OFST(field) \
	MC_CMD_GET_CAPABILITIES_V4_OUT_ ## field ## _OFST

/* field is FLAGS1 or FLAGS2 */
#define efx_has_cap(efx, flag, field) \
	efx->type->check_caps(efx, \
			      MCDI_CAPABILITY(flag), \
			      MCDI_CAPABILITY_OFST(field))

void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
			   u16 *fw_subtype_list, u32 *capabilities);
+34 −45
Original line number Diff line number Diff line
@@ -186,7 +186,6 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx,
				      struct efx_rss_context *ctx,
				      bool replacing)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	u32 flags = spec->flags;

	memset(inbuf, 0, MC_CMD_FILTER_OP_EXT_IN_LEN);
@@ -211,7 +210,7 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx,
		efx_mcdi_filter_push_prep_set_match_fields(efx, spec, inbuf);
	}

	MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, nic_data->vport_id);
	MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, efx->vport_id);
	MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_DEST,
		       spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP ?
		       MC_CMD_FILTER_OP_IN_RX_DEST_DROP :
@@ -332,7 +331,6 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx,
					 bool replace_equal)
{
	DECLARE_BITMAP(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT);
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_mcdi_filter_table *table;
	struct efx_filter_spec *saved_spec;
	struct efx_rss_context *ctx = NULL;
@@ -461,7 +459,7 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx,
	rc = efx_mcdi_filter_push(efx, spec, &table->entry[ins_index].handle,
				  ctx, replacing);

	if (rc == -EINVAL && nic_data->must_realloc_vis)
	if (rc == -EINVAL && efx->must_realloc_vis)
		/* The MC rebooted under us, causing it to reject our filter
		 * insertion as pointing to an invalid VI (spec->dmaq_id).
		 */
@@ -813,7 +811,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx,
				      enum efx_encap_type encap_type,
				      bool multicast, bool rollback)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_mcdi_filter_table *table = efx->filter_state;
	enum efx_filter_flags filter_flags;
	struct efx_filter_spec spec;
	u8 baddr[ETH_ALEN];
@@ -830,8 +828,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx,
		efx_filter_set_uc_def(&spec);

	if (encap_type) {
		if (nic_data->datapath_caps &
		    (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN))
		if (efx_has_cap(efx, VXLAN_NVGRE, FLAGS1))
			efx_filter_set_encap_type(&spec, encap_type);
		else
			/*
@@ -899,7 +896,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx,

		EFX_WARN_ON_PARANOID(*id != EFX_EF10_FILTER_ID_INVALID);
		*id = efx_mcdi_filter_get_unsafe_id(rc);
		if (!nic_data->workaround_26807 && !encap_type) {
		if (!table->mc_chaining && !encap_type) {
			/* Also need an Ethernet broadcast filter */
			efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
					   filter_flags, 0);
@@ -965,7 +962,6 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx,
					      struct efx_mcdi_filter_vlan *vlan)
{
	struct efx_mcdi_filter_table *table = efx->filter_state;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;

	/*
	 * Do not install unspecified VID if VLAN filtering is enabled.
@@ -1012,11 +1008,10 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx,
	 * If changing promiscuous state with cascaded multicast filters, remove
	 * old filters first, so that packets are dropped rather than duplicated
	 */
	if (nic_data->workaround_26807 &&
	    table->mc_promisc_last != table->mc_promisc)
	if (table->mc_chaining && table->mc_promisc_last != table->mc_promisc)
		efx_mcdi_filter_remove_old(efx);
	if (table->mc_promisc) {
		if (nic_data->workaround_26807) {
		if (table->mc_chaining) {
			/*
			 * If we failed to insert promiscuous filters, rollback
			 * and fall back to individual multicast filters
@@ -1051,7 +1046,7 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx,
		 */
		if (efx_mcdi_filter_insert_addr_list(efx, vlan, true, true)) {
			/* Changing promisc state, so remove old filters */
			if (nic_data->workaround_26807)
			if (table->mc_chaining)
				efx_mcdi_filter_remove_old(efx);
			if (efx_mcdi_filter_insert_def(efx, vlan,
						       EFX_ENCAP_TYPE_NONE,
@@ -1288,12 +1283,10 @@ efx_mcdi_filter_table_probe_matches(struct efx_nic *efx,
	return 0;
}

int efx_mcdi_filter_table_probe(struct efx_nic *efx)
int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct net_device *net_dev = efx->net_dev;
	struct efx_mcdi_filter_table *table;
	struct efx_mcdi_filter_vlan *vlan;
	int rc;

	if (!efx_rwsem_assert_write_locked(&efx->filter_sem))
@@ -1306,12 +1299,12 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx)
	if (!table)
		return -ENOMEM;

	table->mc_chaining = multicast_chaining;
	table->rx_match_count = 0;
	rc = efx_mcdi_filter_table_probe_matches(efx, table, false);
	if (rc)
		goto fail;
	if (nic_data->datapath_caps &
		   (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN))
	if (efx_has_cap(efx, VXLAN_NVGRE, FLAGS1))
		rc = efx_mcdi_filter_table_probe_matches(efx, table, true);
	if (rc)
		goto fail;
@@ -1342,22 +1335,22 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx)

	efx->filter_state = table;

	list_for_each_entry(vlan, &nic_data->vlan_list, list) {
		rc = efx_mcdi_filter_add_vlan(efx, vlan->vid);
		if (rc)
			goto fail_add_vlan;
	}

	return 0;

fail_add_vlan:
	efx_mcdi_filter_cleanup_vlans(efx);
	efx->filter_state = NULL;
fail:
	kfree(table);
	return rc;
}

void efx_mcdi_filter_table_reset_mc_allocations(struct efx_nic *efx)
{
	struct efx_mcdi_filter_table *table = efx->filter_state;

	if (table) {
		table->must_restore_filters = true;
		table->must_restore_rss_contexts = true;
	}
}

/*
 * Caller must hold efx->filter_sem for read if race against
 * efx_mcdi_filter_table_remove() is possible
@@ -1365,7 +1358,6 @@ fail:
void efx_mcdi_filter_table_restore(struct efx_nic *efx)
{
	struct efx_mcdi_filter_table *table = efx->filter_state;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	unsigned int invalid_filters = 0, failed = 0;
	struct efx_mcdi_filter_vlan *vlan;
	struct efx_filter_spec *spec;
@@ -1377,7 +1369,7 @@ void efx_mcdi_filter_table_restore(struct efx_nic *efx)

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

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

	if (!table)
@@ -1456,7 +1448,7 @@ not_restored:
		netif_err(efx, hw, efx->net_dev,
			  "unable to restore %u filters\n", failed);
	else
		nic_data->must_restore_filters = false;
		table->must_restore_filters = false;
}

void efx_mcdi_filter_table_remove(struct efx_nic *efx)
@@ -1921,7 +1913,6 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN);
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	size_t outlen;
	int rc;
	u32 alloc_type = exclusive ?
@@ -1939,12 +1930,11 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive
		return 0;
	}

	if (nic_data->datapath_caps &
	    1 << MC_CMD_GET_CAPABILITIES_OUT_RX_RSS_LIMITED_LBN)
	if (efx_has_cap(efx, RX_RSS_LIMITED, FLAGS1))
		return -EOPNOTSUPP;

	MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID,
		       nic_data->vport_id);
		       efx->vport_id);
	MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_TYPE, alloc_type);
	MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, rss_spread);

@@ -1961,8 +1951,7 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive
	if (context_size)
		*context_size = rss_spread;

	if (nic_data->datapath_caps &
	    1 << MC_CMD_GET_CAPABILITIES_OUT_ADDITIONAL_RSS_MODES_LBN)
	if (efx_has_cap(efx, ADDITIONAL_RSS_MODES, FLAGS1))
		efx_mcdi_set_rss_context_flags(efx, ctx);

	return 0;
@@ -2030,14 +2019,14 @@ void efx_mcdi_rx_free_indir_table(struct efx_nic *efx)
static int efx_mcdi_filter_rx_push_shared_rss_config(struct efx_nic *efx,
					      unsigned *context_size)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_mcdi_filter_table *table = efx->filter_state;
	int rc = efx_mcdi_filter_alloc_rss_context(efx, false, &efx->rss_context,
					    context_size);

	if (rc != 0)
		return rc;

	nic_data->rx_rss_context_exclusive = false;
	table->rx_rss_context_exclusive = false;
	efx_set_default_rx_indir_table(efx, &efx->rss_context);
	return 0;
}
@@ -2046,12 +2035,12 @@ static int efx_mcdi_filter_rx_push_exclusive_rss_config(struct efx_nic *efx,
						 const u32 *rx_indir_table,
						 const u8 *key)
{
	struct efx_mcdi_filter_table *table = efx->filter_state;
	u32 old_rx_rss_context = efx->rss_context.context_id;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	int rc;

	if (efx->rss_context.context_id == EFX_MCDI_RSS_CONTEXT_INVALID ||
	    !nic_data->rx_rss_context_exclusive) {
	    !table->rx_rss_context_exclusive) {
		rc = efx_mcdi_filter_alloc_rss_context(efx, true, &efx->rss_context,
						NULL);
		if (rc == -EOPNOTSUPP)
@@ -2068,7 +2057,7 @@ static int efx_mcdi_filter_rx_push_exclusive_rss_config(struct efx_nic *efx,
	if (efx->rss_context.context_id != old_rx_rss_context &&
	    old_rx_rss_context != EFX_MCDI_RSS_CONTEXT_INVALID)
		WARN_ON(efx_mcdi_filter_free_rss_context(efx, old_rx_rss_context) != 0);
	nic_data->rx_rss_context_exclusive = true;
	table->rx_rss_context_exclusive = true;
	if (rx_indir_table != efx->rss_context.rx_indir_table)
		memcpy(efx->rss_context.rx_indir_table, rx_indir_table,
		       sizeof(efx->rss_context.rx_indir_table));
@@ -2182,13 +2171,13 @@ int efx_mcdi_rx_pull_rss_config(struct efx_nic *efx)

void efx_mcdi_rx_restore_rss_contexts(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	struct efx_mcdi_filter_table *table = efx->filter_state;
	struct efx_rss_context *ctx;
	int rc;

	WARN_ON(!mutex_is_locked(&efx->rss_lock));

	if (!nic_data->must_restore_rss_contexts)
	if (!table->must_restore_rss_contexts)
		return;

	list_for_each_entry(ctx, &efx->rss_context.list, list) {
@@ -2204,7 +2193,7 @@ void efx_mcdi_rx_restore_rss_contexts(struct efx_nic *efx)
				   "; RSS filters may fail to be applied\n",
				   ctx->user_id, rc);
	}
	nic_data->must_restore_rss_contexts = false;
	table->must_restore_rss_contexts = false;
}

int efx_mcdi_pf_rx_push_rss_config(struct efx_nic *efx, bool user,
Loading