aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/cxgbe/common/common.h9
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c190
-rw-r--r--sys/dev/cxgbe/firmware/t4fw_interface.h5
-rw-r--r--sys/dev/cxgbe/t4_filter.c196
-rw-r--r--sys/dev/cxgbe/t4_ioctl.h14
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.c2
6 files changed, 287 insertions, 129 deletions
diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h
index 9cc923eaf2f6..53be2fa2588a 100644
--- a/sys/dev/cxgbe/common/common.h
+++ b/sys/dev/cxgbe/common/common.h
@@ -256,11 +256,11 @@ struct tp_params {
unsigned int la_mask; /* what events are recorded by TP LA */
unsigned short tx_modq[MAX_NCHAN]; /* channel to modulation queue map */
- uint32_t vlan_pri_map;
- uint32_t ingress_config;
+ uint16_t filter_mode;
+ uint16_t filter_mask; /* Used by TOE and hashfilters */
+ int vnic_mode;
uint32_t max_rx_pdu;
uint32_t max_tx_pdu;
- uint64_t hash_filter_mask;
bool rx_pkt_encap;
int8_t fcoe_shift;
@@ -753,8 +753,7 @@ int t4_set_sched_ipg(struct adapter *adap, int sched, unsigned int ipg);
int t4_set_pace_tbl(struct adapter *adap, const unsigned int *pace_vals,
unsigned int start, unsigned int n);
void t4_get_chan_txrate(struct adapter *adap, u64 *nic_rate, u64 *ofld_rate);
-int t4_set_filter_mode(struct adapter *adap, unsigned int mode_map,
- bool sleep_ok);
+int t4_set_filter_cfg(struct adapter *adap, int mode, int mask, int vnic_mode);
void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid);
void t4_wol_magic_enable(struct adapter *adap, unsigned int port, const u8 *addr);
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index 36d8864de960..8b22f2e4f5ba 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -9633,19 +9633,74 @@ int t4_init_sge_params(struct adapter *adapter)
return 0;
}
+/* Convert the LE's hardware hash mask to a shorter filter mask. */
+static inline uint16_t
+hashmask_to_filtermask(uint64_t hashmask, uint16_t filter_mode)
+{
+ static const uint8_t width[] = {1, 3, 17, 17, 8, 8, 16, 9, 3, 1};
+ int i;
+ uint16_t filter_mask;
+ uint64_t mask; /* field mask */
+
+ filter_mask = 0;
+ for (i = S_FCOE; i <= S_FRAGMENTATION; i++) {
+ if ((filter_mode & (1 << i)) == 0)
+ continue;
+ mask = (1 << width[i]) - 1;
+ if ((hashmask & mask) == mask)
+ filter_mask |= 1 << i;
+ hashmask >>= width[i];
+ }
+
+ return (filter_mask);
+}
+
/*
* Read and cache the adapter's compressed filter mode and ingress config.
*/
-static void read_filter_mode_and_ingress_config(struct adapter *adap,
- bool sleep_ok)
+static void
+read_filter_mode_and_ingress_config(struct adapter *adap)
{
- uint32_t v;
+ int rc;
+ uint32_t v, param[2], val[2];
struct tp_params *tpp = &adap->params.tp;
+ uint64_t hash_mask;
+
+ param[0] = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FILTER) |
+ V_FW_PARAMS_PARAM_Y(FW_PARAM_DEV_FILTER_MODE_MASK);
+ param[1] = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FILTER) |
+ V_FW_PARAMS_PARAM_Y(FW_PARAM_DEV_FILTER_VNIC_MODE);
+ rc = -t4_query_params(adap, adap->mbox, adap->pf, 0, 2, param, val);
+ if (rc == 0) {
+ tpp->filter_mode = G_FW_PARAMS_PARAM_FILTER_MODE(val[0]);
+ tpp->filter_mask = G_FW_PARAMS_PARAM_FILTER_MASK(val[0]);
+ tpp->vnic_mode = val[1];
+ } else {
+ /*
+ * Old firmware. Read filter mode/mask and ingress config
+ * straight from the hardware.
+ */
+ t4_tp_pio_read(adap, &v, 1, A_TP_VLAN_PRI_MAP, true);
+ tpp->filter_mode = v & 0xffff;
+
+ hash_mask = 0;
+ if (chip_id(adap) > CHELSIO_T4) {
+ v = t4_read_reg(adap, LE_HASH_MASK_GEN_IPV4T5(3));
+ hash_mask = v;
+ v = t4_read_reg(adap, LE_HASH_MASK_GEN_IPV4T5(4));
+ hash_mask |= (u64)v << 32;
+ }
+ tpp->filter_mask = hashmask_to_filtermask(hash_mask,
+ tpp->filter_mode);
- t4_tp_pio_read(adap, &tpp->vlan_pri_map, 1, A_TP_VLAN_PRI_MAP,
- sleep_ok);
- t4_tp_pio_read(adap, &tpp->ingress_config, 1, A_TP_INGRESS_CONFIG,
- sleep_ok);
+ t4_tp_pio_read(adap, &v, 1, A_TP_INGRESS_CONFIG, true);
+ if (v & F_VNIC)
+ tpp->vnic_mode = FW_VNIC_MODE_PF_VF;
+ else
+ tpp->vnic_mode = FW_VNIC_MODE_OUTER_VLAN;
+ }
/*
* Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
@@ -9662,13 +9717,6 @@ static void read_filter_mode_and_ingress_config(struct adapter *adap,
tpp->macmatch_shift = t4_filter_field_shift(adap, F_MACMATCH);
tpp->matchtype_shift = t4_filter_field_shift(adap, F_MPSHITTYPE);
tpp->frag_shift = t4_filter_field_shift(adap, F_FRAGMENTATION);
-
- if (chip_id(adap) > CHELSIO_T4) {
- v = t4_read_reg(adap, LE_HASH_MASK_GEN_IPV4T5(3));
- adap->params.tp.hash_filter_mask = v;
- v = t4_read_reg(adap, LE_HASH_MASK_GEN_IPV4T5(4));
- adap->params.tp.hash_filter_mask |= (u64)v << 32;
- }
}
/**
@@ -9691,7 +9739,7 @@ int t4_init_tp_params(struct adapter *adap)
for (chan = 0; chan < MAX_NCHAN; chan++)
tpp->tx_modq[chan] = chan;
- read_filter_mode_and_ingress_config(adap, true);
+ read_filter_mode_and_ingress_config(adap);
if (chip_id(adap) > CHELSIO_T5) {
v = t4_read_reg(adap, A_TP_OUT_CONFIG);
@@ -9728,7 +9776,7 @@ int t4_init_tp_params(struct adapter *adap)
*/
int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
{
- unsigned int filter_mode = adap->params.tp.vlan_pri_map;
+ const unsigned int filter_mode = adap->params.tp.filter_mode;
unsigned int sel;
int field_shift;
@@ -10798,30 +10846,98 @@ out:
}
/**
- * t4_set_filter_mode - configure the optional components of filter tuples
+ * t4_set_filter_cfg - set up filter mode/mask and ingress config.
* @adap: the adapter
- * @mode_map: a bitmap selcting which optional filter components to enable
- * @sleep_ok: if true we may sleep while awaiting command completion
- *
- * Sets the filter mode by selecting the optional components to enable
- * in filter tuples. Returns 0 on success and a negative error if the
- * requested mode needs more bits than are available for optional
- * components.
- */
-int t4_set_filter_mode(struct adapter *adap, unsigned int mode_map,
- bool sleep_ok)
-{
- static u8 width[] = { 1, 3, 17, 17, 8, 8, 16, 9, 3, 1 };
+ * @mode: a bitmap selecting which optional filter components to enable
+ * @mask: a bitmap selecting which components to enable in filter mask
+ * @vnic_mode: the ingress config/vnic mode setting
+ *
+ * Sets the filter mode and mask by selecting the optional components to
+ * enable in filter tuples. Returns 0 on success and a negative error if
+ * the requested mode needs more bits than are available for optional
+ * components. The filter mask must be a subset of the filter mode.
+ */
+int t4_set_filter_cfg(struct adapter *adap, int mode, int mask, int vnic_mode)
+{
+ static const uint8_t width[] = {1, 3, 17, 17, 8, 8, 16, 9, 3, 1};
+ int i, nbits, rc;
+ uint32_t param, val;
+ uint16_t fmode, fmask;
+ const int maxbits = FILTER_OPT_LEN;
+
+ if (mode != -1 || mask != -1) {
+ if (mode != -1) {
+ fmode = mode;
+ nbits = 0;
+ for (i = S_FCOE; i <= S_FRAGMENTATION; i++) {
+ if (fmode & (1 << i))
+ nbits += width[i];
+ }
+ if (nbits > maxbits) {
+ CH_ERR(adap, "optional fields in the filter "
+ "mode (0x%x) add up to %d bits "
+ "(must be <= %db). Remove some fields and "
+ "try again.\n", fmode, nbits, maxbits);
+ return -E2BIG;
+ }
- int i, nbits = 0;
+ /*
+ * Hardware wants the bits to be maxed out. Keep
+ * setting them until there's no room for more.
+ */
+ for (i = S_FCOE; i <= S_FRAGMENTATION; i++) {
+ if (fmode & (1 << i))
+ continue;
+ if (nbits + width[i] <= maxbits) {
+ fmode |= 1 << i;
+ nbits += width[i];
+ if (nbits == maxbits)
+ break;
+ }
+ }
- for (i = S_FCOE; i <= S_FRAGMENTATION; i++)
- if (mode_map & (1 << i))
- nbits += width[i];
- if (nbits > FILTER_OPT_LEN)
- return -EINVAL;
- t4_tp_pio_write(adap, &mode_map, 1, A_TP_VLAN_PRI_MAP, sleep_ok);
- read_filter_mode_and_ingress_config(adap, sleep_ok);
+ fmask = fmode & adap->params.tp.filter_mask;
+ if (fmask != adap->params.tp.filter_mask) {
+ CH_WARN(adap,
+ "filter mask will be changed from 0x%x to "
+ "0x%x to comply with the filter mode (0x%x).\n",
+ adap->params.tp.filter_mask, fmask, fmode);
+ }
+ } else {
+ fmode = adap->params.tp.filter_mode;
+ fmask = mask;
+ if ((fmode | fmask) != fmode) {
+ CH_ERR(adap,
+ "filter mask (0x%x) must be a subset of "
+ "the filter mode (0x%x).\n", fmask, fmode);
+ return -EINVAL;
+ }
+ }
+
+ param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FILTER) |
+ V_FW_PARAMS_PARAM_Y(FW_PARAM_DEV_FILTER_MODE_MASK);
+ val = V_FW_PARAMS_PARAM_FILTER_MODE(fmode) |
+ V_FW_PARAMS_PARAM_FILTER_MASK(fmask);
+ rc = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, &param,
+ &val);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (vnic_mode != -1) {
+ param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FILTER) |
+ V_FW_PARAMS_PARAM_Y(FW_PARAM_DEV_FILTER_VNIC_MODE);
+ val = vnic_mode;
+ rc = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, &param,
+ &val);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Refresh. */
+ read_filter_mode_and_ingress_config(adap);
return 0;
}
diff --git a/sys/dev/cxgbe/firmware/t4fw_interface.h b/sys/dev/cxgbe/firmware/t4fw_interface.h
index dcec2cc122f2..30a2e1760052 100644
--- a/sys/dev/cxgbe/firmware/t4fw_interface.h
+++ b/sys/dev/cxgbe/firmware/t4fw_interface.h
@@ -4874,6 +4874,11 @@ enum fw_params_param_dev_diag {
enum fw_params_param_dev_filter{
FW_PARAM_DEV_FILTER_VNIC_MODE = 0x00,
FW_PARAM_DEV_FILTER_MODE_MASK = 0x01,
+
+ /* VNIC modes */
+ FW_VNIC_MODE_PF_VF = 0,
+ FW_VNIC_MODE_OUTER_VLAN = 1,
+ FW_VNIC_MODE_ENCAP_EN = 2,
};
enum fw_params_param_dev_ktls_hw {
diff --git a/sys/dev/cxgbe/t4_filter.c b/sys/dev/cxgbe/t4_filter.c
index 65a87f4c4163..1e0269fcd5c0 100644
--- a/sys/dev/cxgbe/t4_filter.c
+++ b/sys/dev/cxgbe/t4_filter.c
@@ -231,9 +231,8 @@ filter_eq(struct t4_filter_specification *fs1,
return (false);
/*
- * We know the masks are the same because all hashfilter masks have to
- * conform to the global tp->hash_filter_mask and the driver has
- * verified that already.
+ * We know the masks are the same because all hashfilters conform to the
+ * global tp->filter_mask and the driver has verified that already.
*/
if ((fs1->mask.pfvf_vld || fs1->mask.ovlan_vld) &&
@@ -325,7 +324,11 @@ remove_hftid(struct adapter *sc, struct filter_entry *f)
LIST_REMOVE(f, link_tid);
}
-static uint32_t
+/*
+ * Input: driver's 32b filter mode.
+ * Returns: hardware filter mode (bits to set in vlan_pri_map) for the input.
+ */
+static uint16_t
mode_to_fconf(uint32_t mode)
{
uint32_t fconf = 0;
@@ -363,13 +366,22 @@ mode_to_fconf(uint32_t mode)
return (fconf);
}
-static uint32_t
+/*
+ * Input: driver's 32b filter mode.
+ * Returns: hardware vnic mode (ingress config) matching the input.
+ */
+static int
mode_to_iconf(uint32_t mode)
{
+ if ((mode & T4_FILTER_VNIC) == 0)
+ return (-1); /* ingress config doesn't matter. */
if (mode & T4_FILTER_IC_VNIC)
- return (F_VNIC);
- return (0);
+ return (FW_VNIC_MODE_PF_VF);
+ else if (mode & T4_FILTER_IC_ENCAP)
+ return (FW_VNIC_MODE_ENCAP_EN);
+ else
+ return (FW_VNIC_MODE_OUTER_VLAN);
}
static int
@@ -401,16 +413,24 @@ check_fspec_against_fconf_iconf(struct adapter *sc,
fconf |= F_VLAN;
if (fs->val.ovlan_vld || fs->mask.ovlan_vld) {
- fconf |= F_VNIC_ID;
- if (tpp->ingress_config & F_VNIC)
+ if (tpp->vnic_mode != FW_VNIC_MODE_OUTER_VLAN)
return (EINVAL);
+ fconf |= F_VNIC_ID;
}
if (fs->val.pfvf_vld || fs->mask.pfvf_vld) {
+ if (tpp->vnic_mode != FW_VNIC_MODE_PF_VF)
+ return (EINVAL);
fconf |= F_VNIC_ID;
- if ((tpp->ingress_config & F_VNIC) == 0)
+ }
+
+#ifdef notyet
+ if (fs->val.encap_vld || fs->mask.encap_vld) {
+ if (tpp->vnic_mode != FW_VNIC_MODE_ENCAP_EN);
return (EINVAL);
+ fconf |= F_VNIC_ID;
}
+#endif
if (fs->val.iport || fs->mask.iport)
fconf |= F_PORT;
@@ -418,46 +438,70 @@ check_fspec_against_fconf_iconf(struct adapter *sc,
if (fs->val.fcoe || fs->mask.fcoe)
fconf |= F_FCOE;
- if ((tpp->vlan_pri_map | fconf) != tpp->vlan_pri_map)
+ if ((tpp->filter_mode | fconf) != tpp->filter_mode)
return (E2BIG);
return (0);
}
+/*
+ * Input: hardware filter configuration (filter mode/mask, ingress config).
+ * Input: driver's 32b filter mode matching the input.
+ */
+static uint32_t
+fconf_to_mode(uint16_t hwmode, int vnic_mode)
+{
+ uint32_t mode = T4_FILTER_IPv4 | T4_FILTER_IPv6 | T4_FILTER_IP_SADDR |
+ T4_FILTER_IP_DADDR | T4_FILTER_IP_SPORT | T4_FILTER_IP_DPORT;
+
+ if (hwmode & F_FRAGMENTATION)
+ mode |= T4_FILTER_IP_FRAGMENT;
+ if (hwmode & F_MPSHITTYPE)
+ mode |= T4_FILTER_MPS_HIT_TYPE;
+ if (hwmode & F_MACMATCH)
+ mode |= T4_FILTER_MAC_IDX;
+ if (hwmode & F_ETHERTYPE)
+ mode |= T4_FILTER_ETH_TYPE;
+ if (hwmode & F_PROTOCOL)
+ mode |= T4_FILTER_IP_PROTO;
+ if (hwmode & F_TOS)
+ mode |= T4_FILTER_IP_TOS;
+ if (hwmode & F_VLAN)
+ mode |= T4_FILTER_VLAN;
+ if (hwmode & F_VNIC_ID)
+ mode |= T4_FILTER_VNIC; /* real meaning depends on vnic_mode. */
+ if (hwmode & F_PORT)
+ mode |= T4_FILTER_PORT;
+ if (hwmode & F_FCOE)
+ mode |= T4_FILTER_FCoE;
+
+ switch (vnic_mode) {
+ case FW_VNIC_MODE_PF_VF:
+ mode |= T4_FILTER_IC_VNIC;
+ break;
+ case FW_VNIC_MODE_ENCAP_EN:
+ mode |= T4_FILTER_IC_ENCAP;
+ break;
+ case FW_VNIC_MODE_OUTER_VLAN:
+ default:
+ break;
+ }
+
+ return (mode);
+}
+
int
get_filter_mode(struct adapter *sc, uint32_t *mode)
{
struct tp_params *tp = &sc->params.tp;
- uint64_t mask;
+ uint16_t filter_mode;
- /* Non-zero incoming value in mode means "hashfilter mode". */
- mask = *mode ? tp->hash_filter_mask : UINT64_MAX;
+ /* Filter mask must comply with the global filter mode. */
+ MPASS((tp->filter_mode | tp->filter_mask) == tp->filter_mode);
- /* Always */
- *mode = T4_FILTER_IPv4 | T4_FILTER_IPv6 | T4_FILTER_IP_SADDR |
- T4_FILTER_IP_DADDR | T4_FILTER_IP_SPORT | T4_FILTER_IP_DPORT;
-
-#define CHECK_FIELD(fconf_bit, field_shift, field_mask, mode_bit) do { \
- if (tp->vlan_pri_map & (fconf_bit)) { \
- MPASS(tp->field_shift >= 0); \
- if ((mask >> tp->field_shift & field_mask) == field_mask) \
- *mode |= (mode_bit); \
- } \
-} while (0)
-
- CHECK_FIELD(F_FRAGMENTATION, frag_shift, M_FT_FRAGMENTATION, T4_FILTER_IP_FRAGMENT);
- CHECK_FIELD(F_MPSHITTYPE, matchtype_shift, M_FT_MPSHITTYPE, T4_FILTER_MPS_HIT_TYPE);
- CHECK_FIELD(F_MACMATCH, macmatch_shift, M_FT_MACMATCH, T4_FILTER_MAC_IDX);
- CHECK_FIELD(F_ETHERTYPE, ethertype_shift, M_FT_ETHERTYPE, T4_FILTER_ETH_TYPE);
- CHECK_FIELD(F_PROTOCOL, protocol_shift, M_FT_PROTOCOL, T4_FILTER_IP_PROTO);
- CHECK_FIELD(F_TOS, tos_shift, M_FT_TOS, T4_FILTER_IP_TOS);
- CHECK_FIELD(F_VLAN, vlan_shift, M_FT_VLAN, T4_FILTER_VLAN);
- CHECK_FIELD(F_VNIC_ID, vnic_shift, M_FT_VNIC_ID , T4_FILTER_VNIC);
- if (tp->ingress_config & F_VNIC)
- *mode |= T4_FILTER_IC_VNIC;
- CHECK_FIELD(F_PORT, port_shift, M_FT_PORT , T4_FILTER_PORT);
- CHECK_FIELD(F_FCOE, fcoe_shift, M_FT_FCOE , T4_FILTER_FCoE);
-#undef CHECK_FIELD
+ /* Non-zero incoming value in mode means "hashfilter mode". */
+ filter_mode = *mode ? tp->filter_mask : tp->filter_mode;
+ *mode = fconf_to_mode(filter_mode, tp->vnic_mode);
return (0);
}
@@ -465,33 +509,22 @@ get_filter_mode(struct adapter *sc, uint32_t *mode)
int
set_filter_mode(struct adapter *sc, uint32_t mode)
{
- struct tp_params *tpp = &sc->params.tp;
- uint32_t fconf, iconf;
- int rc;
+ struct tp_params *tp = &sc->params.tp;
+ int rc, iconf;
+ uint16_t fconf;
iconf = mode_to_iconf(mode);
- if ((iconf ^ tpp->ingress_config) & F_VNIC) {
- /*
- * For now we just complain if A_TP_INGRESS_CONFIG is not
- * already set to the correct value for the requested filter
- * mode. It's not clear if it's safe to write to this register
- * on the fly. (And we trust the cached value of the register).
- *
- * check_fspec_against_fconf_iconf and other code that looks at
- * tp->vlan_pri_map and tp->ingress_config needs to be reviewed
- * thorougly before allowing dynamic filter mode changes.
- */
- return (EBUSY);
- }
-
fconf = mode_to_fconf(mode);
+ if ((iconf == -1 || iconf == tp->vnic_mode) && fconf == tp->filter_mode)
+ return (0); /* Nothing to do */
- rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK,
- "t4setfm");
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setfm");
if (rc)
return (rc);
- if (sc->tids.ftids_in_use > 0 || sc->tids.hpftids_in_use > 0) {
+ if (sc->tids.ftids_in_use > 0 || /* TCAM filters active */
+ sc->tids.hpftids_in_use > 0 || /* hi-pri TCAM filters active */
+ sc->tids.tids_in_use > 0) { /* TOE or hashfilters active */
rc = EBUSY;
goto done;
}
@@ -503,9 +536,10 @@ set_filter_mode(struct adapter *sc, uint32_t mode)
}
#endif
- rc = -t4_set_filter_mode(sc, fconf, true);
+ /* Note that filter mask will get clipped to the new filter mode. */
+ rc = -t4_set_filter_cfg(sc, fconf, -1, iconf);
done:
- end_synchronized_op(sc, LOCK_HELD);
+ end_synchronized_op(sc, 0);
return (rc);
}
@@ -718,7 +752,7 @@ hashfilter_ntuple(struct adapter *sc, const struct t4_filter_specification *fs,
uint64_t *ftuple)
{
struct tp_params *tp = &sc->params.tp;
- uint64_t fmask;
+ uint16_t fmask;
*ftuple = fmask = 0;
@@ -727,63 +761,67 @@ hashfilter_ntuple(struct adapter *sc, const struct t4_filter_specification *fs,
* in the Compressed Filter Tuple.
*/
if (tp->vlan_shift >= 0 && fs->mask.vlan) {
- *ftuple |= (F_FT_VLAN_VLD | fs->val.vlan) << tp->vlan_shift;
- fmask |= M_FT_VLAN << tp->vlan_shift;
+ *ftuple |= (uint64_t)(F_FT_VLAN_VLD | fs->val.vlan) <<
+ tp->vlan_shift;
+ fmask |= F_VLAN;
}
if (tp->port_shift >= 0 && fs->mask.iport) {
*ftuple |= (uint64_t)fs->val.iport << tp->port_shift;
- fmask |= M_FT_PORT << tp->port_shift;
+ fmask |= F_PORT;
}
if (tp->protocol_shift >= 0 && fs->mask.proto) {
*ftuple |= (uint64_t)fs->val.proto << tp->protocol_shift;
- fmask |= M_FT_PROTOCOL << tp->protocol_shift;
+ fmask |= F_PROTOCOL;
}
if (tp->tos_shift >= 0 && fs->mask.tos) {
*ftuple |= (uint64_t)(fs->val.tos) << tp->tos_shift;
- fmask |= M_FT_TOS << tp->tos_shift;
+ fmask |= F_TOS;
}
if (tp->vnic_shift >= 0 && fs->mask.vnic) {
- /* F_VNIC in ingress config was already validated. */
- if (tp->ingress_config & F_VNIC)
+ /* vnic_mode was already validated. */
+ if (tp->vnic_mode == FW_VNIC_MODE_PF_VF)
MPASS(fs->mask.pfvf_vld);
- else
+ else if (tp->vnic_mode == FW_VNIC_MODE_OUTER_VLAN)
MPASS(fs->mask.ovlan_vld);
-
+#ifdef notyet
+ else if (tp->vnic_mode == FW_VNIC_MODE_ENCAP_EN)
+ MPASS(fs->mask.encap_vld);
+#endif
*ftuple |= ((1ULL << 16) | fs->val.vnic) << tp->vnic_shift;
- fmask |= M_FT_VNIC_ID << tp->vnic_shift;
+ fmask |= F_VNIC_ID;
}
if (tp->macmatch_shift >= 0 && fs->mask.macidx) {
*ftuple |= (uint64_t)(fs->val.macidx) << tp->macmatch_shift;
- fmask |= M_FT_MACMATCH << tp->macmatch_shift;
+ fmask |= F_MACMATCH;
}
if (tp->ethertype_shift >= 0 && fs->mask.ethtype) {
*ftuple |= (uint64_t)(fs->val.ethtype) << tp->ethertype_shift;
- fmask |= M_FT_ETHERTYPE << tp->ethertype_shift;
+ fmask |= F_ETHERTYPE;
}
if (tp->matchtype_shift >= 0 && fs->mask.matchtype) {
*ftuple |= (uint64_t)(fs->val.matchtype) << tp->matchtype_shift;
- fmask |= M_FT_MPSHITTYPE << tp->matchtype_shift;
+ fmask |= F_MPSHITTYPE;
}
if (tp->frag_shift >= 0 && fs->mask.frag) {
*ftuple |= (uint64_t)(fs->val.frag) << tp->frag_shift;
- fmask |= M_FT_FRAGMENTATION << tp->frag_shift;
+ fmask |= F_FRAGMENTATION;
}
if (tp->fcoe_shift >= 0 && fs->mask.fcoe) {
*ftuple |= (uint64_t)(fs->val.fcoe) << tp->fcoe_shift;
- fmask |= M_FT_FCOE << tp->fcoe_shift;
+ fmask |= F_FCOE;
}
- /* A hashfilter must conform to the filterMask. */
- if (fmask != tp->hash_filter_mask)
+ /* A hashfilter must conform to the hardware filter mask. */
+ if (fmask != tp->filter_mask)
return (EINVAL);
return (0);
diff --git a/sys/dev/cxgbe/t4_ioctl.h b/sys/dev/cxgbe/t4_ioctl.h
index 1daa4f5dfa27..4f0a71683ef0 100644
--- a/sys/dev/cxgbe/t4_ioctl.h
+++ b/sys/dev/cxgbe/t4_ioctl.h
@@ -110,7 +110,7 @@ struct t4_i2c_data {
#define T4_FILTER_IP_DPORT 0x20 /* Destination IP port */
#define T4_FILTER_FCoE 0x40 /* Fibre Channel over Ethernet packet */
#define T4_FILTER_PORT 0x80 /* Physical ingress port */
-#define T4_FILTER_VNIC 0x100 /* VNIC id or outer VLAN */
+#define T4_FILTER_VNIC 0x100 /* See the IC_* bits towards the end */
#define T4_FILTER_VLAN 0x200 /* VLAN ID */
#define T4_FILTER_IP_TOS 0x400 /* IPv4 TOS/IPv6 Traffic Class */
#define T4_FILTER_IP_PROTO 0x800 /* IP protocol */
@@ -118,12 +118,12 @@ struct t4_i2c_data {
#define T4_FILTER_MAC_IDX 0x2000 /* MPS MAC address match index */
#define T4_FILTER_MPS_HIT_TYPE 0x4000 /* MPS match type */
#define T4_FILTER_IP_FRAGMENT 0x8000 /* IP fragment */
-
-#define T4_FILTER_IC_VNIC 0x80000000 /* TP Ingress Config's F_VNIC
- bit. It indicates whether
- T4_FILTER_VNIC bit means VNIC
- id (PF/VF) or outer VLAN.
- 0 = oVLAN, 1 = VNIC */
+/*
+ * T4_FILTER_VNIC's real meaning depends on the ingress config.
+ */
+#define T4_FILTER_IC_OVLAN 0 /* outer VLAN */
+#define T4_FILTER_IC_VNIC 0x80000000 /* VNIC id (PF/VF) */
+#define T4_FILTER_IC_ENCAP 0x40000000
/* Filter action */
enum {
diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index 0f0b4d7ee5b3..df837cc50454 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -1066,7 +1066,7 @@ select_ntuple(struct vi_info *vi, struct l2t_entry *e)
if (tp->protocol_shift >= 0)
ntuple |= (uint64_t)IPPROTO_TCP << tp->protocol_shift;
- if (tp->vnic_shift >= 0 && tp->ingress_config & F_VNIC) {
+ if (tp->vnic_shift >= 0 && tp->vnic_mode == FW_VNIC_MODE_PF_VF) {
ntuple |= (uint64_t)(V_FT_VNID_ID_VF(vi->vin) |
V_FT_VNID_ID_PF(sc->pf) | V_FT_VNID_ID_VLD(vi->vfvld)) <<
tp->vnic_shift;