Commit 05ccd8d8 authored by Edward Cree's avatar Edward Cree Committed by Jakub Kicinski
Browse files

sfc: support offloading TC VLAN push/pop actions to the MAE

parent 494f642f
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -682,6 +682,10 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
	size_t outlen;
	int rc;

	MCDI_POPULATE_DWORD_2(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS,
			      MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, act->vlan_push,
			      MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop);

	MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
		       MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
	MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
@@ -694,6 +698,18 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
			       MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL);
	MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID,
		       MC_CMD_MAE_COUNTER_LIST_ALLOC_OUT_COUNTER_LIST_ID_NULL);
	if (act->vlan_push) {
		MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE,
				 act->vlan_tci[0]);
		MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE,
				 act->vlan_proto[0]);
	}
	if (act->vlan_push >= 2) {
		MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE,
				 act->vlan_tci[1]);
		MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
				 act->vlan_proto[1]);
	}
	MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
		       MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
	if (act->deliver)
+5 −0
Original line number Diff line number Diff line
@@ -233,6 +233,11 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
	((void)BUILD_BUG_ON_ZERO(_field ## _LEN != 2),  \
	le16_to_cpu(*(__force const __le16 *)MCDI_STRUCT_PTR(_buf, _field)))
/* Write a 16-bit field defined in the protocol as being big-endian. */
#define MCDI_SET_WORD_BE(_buf, _field, _value) do {			\
	BUILD_BUG_ON(MC_CMD_ ## _field ## _LEN != 2);			\
	BUILD_BUG_ON(MC_CMD_ ## _field ## _OFST & 1);			\
	*(__force __be16 *)MCDI_PTR(_buf, _field) = (_value);		\
	} while (0)
#define MCDI_STRUCT_SET_WORD_BE(_buf, _field, _value) do {		\
	BUILD_BUG_ON(_field ## _LEN != 2);				\
	BUILD_BUG_ON(_field ## _OFST & 1);				\
+42 −0
Original line number Diff line number Diff line
@@ -286,6 +286,8 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx,

/* For details of action order constraints refer to SF-123102-TC-1§12.6.1 */
enum efx_tc_action_order {
	EFX_TC_AO_VLAN_POP,
	EFX_TC_AO_VLAN_PUSH,
	EFX_TC_AO_COUNT,
	EFX_TC_AO_DELIVER
};
@@ -294,6 +296,20 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act,
					  enum efx_tc_action_order new)
{
	switch (new) {
	case EFX_TC_AO_VLAN_POP:
		if (act->vlan_pop >= 2)
			return false;
		/* If we've already pushed a VLAN, we can't then pop it;
		 * the hardware would instead try to pop an existing VLAN
		 * before pushing the new one.
		 */
		if (act->vlan_push)
			return false;
		fallthrough;
	case EFX_TC_AO_VLAN_PUSH:
		if (act->vlan_push >= 2)
			return false;
		fallthrough;
	case EFX_TC_AO_COUNT:
		if (act->count)
			return false;
@@ -393,6 +409,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx,

	flow_action_for_each(i, fa, &fr->action) {
		struct efx_tc_action_set save;
		u16 tci;

		if (!act) {
			/* more actions after a non-pipe action */
@@ -494,6 +511,31 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
			}
			*act = save;
			break;
		case FLOW_ACTION_VLAN_POP:
			if (act->vlan_push) {
				act->vlan_push--;
			} else if (efx_tc_flower_action_order_ok(act, EFX_TC_AO_VLAN_POP)) {
				act->vlan_pop++;
			} else {
				NL_SET_ERR_MSG_MOD(extack,
						   "More than two VLAN pops, or action order violated");
				rc = -EINVAL;
				goto release;
			}
			break;
		case FLOW_ACTION_VLAN_PUSH:
			if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_VLAN_PUSH)) {
				rc = -EINVAL;
				NL_SET_ERR_MSG_MOD(extack,
						   "More than two VLAN pushes, or action order violated");
				goto release;
			}
			tci = fa->vlan.vid & VLAN_VID_MASK;
			tci |= fa->vlan.prio << VLAN_PRIO_SHIFT;
			act->vlan_tci[act->vlan_push] = cpu_to_be16(tci);
			act->vlan_proto[act->vlan_push] = fa->vlan.proto;
			act->vlan_push++;
			break;
		default:
			NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u",
					       fa->id);
+4 −0
Original line number Diff line number Diff line
@@ -19,7 +19,11 @@
#define IS_ALL_ONES(v)	(!(typeof (v))~(v))

struct efx_tc_action_set {
	u16 vlan_push:2;
	u16 vlan_pop:2;
	u16 deliver:1;
	__be16 vlan_tci[2]; /* TCIs for vlan_push */
	__be16 vlan_proto[2]; /* Ethertypes for vlan_push */
	struct efx_tc_counter_index *count;
	u32 dest_mport;
	u32 fw_id; /* index of this entry in firmware actions table */