Add support to match all packets received on the underlying VF.
Use new firmware API to fetch the Virtual Interface Number (VIN)
allocated to each VF by the firmware. The VIN is required to
write filter rules to match all packets on VFs, whose identifier
is beyond max 7-bit value (i.e. 127) in VIID.
If firmware doesn't support fetching the VIN information, then
fallback to manually retrieving the VIN value from the 7-bit field
in the VIID, which only supports in range of 0..127. In this case,
packets belonging to VFs, whose identifier is beyond 127 can't be
matched.
Signed-off-by: Karra Satwik <kaara.satwik@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
u8 rss_mode; /* rss mode */
u16 rss_size; /* size of VI's RSS table slice */
u64 rss_hf; /* RSS Hash Function */
+
+ /* viid fields either returned by fw
+ * or decoded by parsing viid by driver.
+ */
+ u8 vin;
+ u8 vivld;
};
/* Enable or disable autonegotiation. If this is set to enable,
bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */
u8 fw_caps_support; /* 32-bit Port Capabilities */
u8 filter2_wr_support; /* FW support for FILTER2_WR */
+ u32 viid_smt_extn_support:1; /* FW returns vin and smt index */
u32 max_tx_coalesce_num; /* Max # of Tx packets that can be coalesced */
};
int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
unsigned int port, unsigned int pf, unsigned int vf,
unsigned int nmac, u8 *mac, unsigned int *rss_size,
- unsigned int portfunc, unsigned int idstype);
+ unsigned int portfunc, unsigned int idstype,
+ u8 *vivld, u8 *vin);
int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
- unsigned int *rss_size);
+ unsigned int *rss_size, u8 *vivild, u8 *vin);
int t4_free_vi(struct adapter *adap, unsigned int mbox,
unsigned int pf, unsigned int vf,
unsigned int viid);
int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
unsigned int port, unsigned int pf, unsigned int vf,
unsigned int nmac, u8 *mac, unsigned int *rss_size,
- unsigned int portfunc, unsigned int idstype)
+ unsigned int portfunc, unsigned int idstype,
+ u8 *vivld, u8 *vin)
{
int ret;
struct fw_vi_cmd c;
}
if (rss_size)
*rss_size = G_FW_VI_CMD_RSSSIZE(be16_to_cpu(c.norss_rsssize));
+ if (vivld)
+ *vivld = G_FW_VI_CMD_VFVLD(be32_to_cpu(c.alloc_to_len16));
+ if (vin)
+ *vin = G_FW_VI_CMD_VIN(be32_to_cpu(c.alloc_to_len16));
return G_FW_VI_CMD_VIID(cpu_to_be16(c.type_to_viid));
}
*/
int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
- unsigned int *rss_size)
+ unsigned int *rss_size, u8 *vivld, u8 *vin)
{
return t4_alloc_vi_func(adap, mbox, port, pf, vf, nmac, mac, rss_size,
- FW_VI_FUNC_ETH, 0);
+ FW_VI_FUNC_ETH, 0, vivld, vin);
}
/**
fw_port_cap32_t pcaps, acaps;
enum fw_port_type port_type;
struct fw_port_cmd cmd;
+ u8 vivld = 0, vin = 0;
int ret, i, j = 0;
int mdio_addr;
u32 action;
acaps = be32_to_cpu(cmd.u.info32.acaps32);
}
- ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size);
+ ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size,
+ &vivld, &vin);
if (ret < 0)
return ret;
pi->rss_size = rss_size;
t4_os_set_hw_addr(adap, i, addr);
+ /* If fw supports returning the VIN as part of FW_VI_CMD,
+ * save the returned values.
+ */
+ if (adap->params.viid_smt_extn_support) {
+ pi->vivld = vivld;
+ pi->vin = vin;
+ } else {
+ /* Retrieve the values from VIID */
+ pi->vivld = G_FW_VIID_VIVLD(pi->viid);
+ pi->vin = G_FW_VIID_VIN(pi->viid);
+ }
+
pi->port_type = port_type;
pi->mdio_addr = mdio_addr;
pi->mod_type = FW_PORT_MOD_TYPE_NA;
FW_PARAMS_PARAM_DEV_TPREV = 0x0C, /* tp version */
FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17,
FW_PARAMS_PARAM_DEV_FILTER2_WR = 0x1D,
+ FW_PARAMS_PARAM_DEV_OPAQUE_VIID_SMT_EXTN = 0x27,
};
/*
FW_VI_FUNC_ETH,
};
+/* Macros for VIID parsing:
+ * VIID - [10:8] PFN, [7] VI Valid, [6:0] VI number
+ */
+
+#define S_FW_VIID_VIVLD 7
+#define M_FW_VIID_VIVLD 0x1
+#define G_FW_VIID_VIVLD(x) (((x) >> S_FW_VIID_VIVLD) & M_FW_VIID_VIVLD)
+
+#define S_FW_VIID_VIN 0
+#define M_FW_VIID_VIN 0x7F
+#define G_FW_VIID_VIN(x) (((x) >> S_FW_VIID_VIN) & M_FW_VIID_VIN)
+
struct fw_vi_cmd {
__be32 op_to_vfn;
__be32 alloc_to_len16;
#define G_FW_VI_CMD_FREE(x) (((x) >> S_FW_VI_CMD_FREE) & M_FW_VI_CMD_FREE)
#define F_FW_VI_CMD_FREE V_FW_VI_CMD_FREE(1U)
+#define S_FW_VI_CMD_VFVLD 24
+#define M_FW_VI_CMD_VFVLD 0x1
+#define G_FW_VI_CMD_VFVLD(x) \
+ (((x) >> S_FW_VI_CMD_VFVLD) & M_FW_VI_CMD_VFVLD)
+
+#define S_FW_VI_CMD_VIN 16
+#define M_FW_VI_CMD_VIN 0xff
+#define G_FW_VI_CMD_VIN(x) \
+ (((x) >> S_FW_VI_CMD_VIN) & M_FW_VI_CMD_VIN)
+
#define S_FW_VI_CMD_TYPE 15
#define M_FW_VI_CMD_TYPE 0x1
#define V_FW_VI_CMD_TYPE(x) ((x) << S_FW_VI_CMD_TYPE)
if (tp->vnic_shift >= 0) {
if ((adap->params.tp.ingress_config & F_VNIC) &&
f->fs.mask.pfvf_vld)
- ntuple |= (u64)((f->fs.val.pfvf_vld << 16) |
- (f->fs.val.pf << 13)) << tp->vnic_shift;
+ ntuple |= (u64)(f->fs.val.pfvf_vld << 16 |
+ f->fs.val.pf << 13 | f->fs.val.vf) <<
+ tp->vnic_shift;
else if (!(adap->params.tp.ingress_config & F_VNIC) &&
f->fs.mask.ovlan_vld)
ntuple |= (u64)(f->fs.val.ovlan_vld << 16 |
* to hardware.
*/
if (iconf & F_VNIC) {
- f->fs.val.ovlan = fs->val.pf << 13;
- f->fs.mask.ovlan = fs->mask.pf << 13;
+ f->fs.val.ovlan = fs->val.pf << 13 | fs->val.vf;
+ f->fs.mask.ovlan = fs->mask.pf << 13 | fs->mask.vf;
f->fs.val.ovlan_vld = fs->val.pfvf_vld;
f->fs.mask.ovlan_vld = fs->mask.pfvf_vld;
}
#define PROTO_BITWIDTH 8
#define TOS_BITWIDTH 8
#define PF_BITWIDTH 3
-#define VF_BITWIDTH 8
+#define VF_BITWIDTH 13
#define IVLAN_BITWIDTH 16
#define OVLAN_BITWIDTH 16
ntuple_mask |= (u64)(fs->val.ovlan_vld << 16 |
fs->mask.ovlan) << tp->vnic_shift;
else if (fs->mask.pfvf_vld)
- ntuple_mask |= (u64)((fs->mask.pfvf_vld << 16) |
- (fs->mask.pf << 13)) <<
- tp->vnic_shift;
+ ntuple_mask |= (u64)(fs->mask.pfvf_vld << 16 |
+ fs->mask.pf << 13 |
+ fs->mask.vf) << tp->vnic_shift;
}
if (tp->tos_shift >= 0)
ntuple_mask |= (u64)fs->mask.tos << tp->tos_shift;
return 0;
}
+static int
+ch_rte_parsetype_vf(const void *dmask, const struct rte_flow_item *item,
+ struct ch_filter_specification *fs,
+ struct rte_flow_error *e)
+{
+ const struct rte_flow_item_vf *umask = item->mask;
+ const struct rte_flow_item_vf *val = item->spec;
+ const struct rte_flow_item_vf *mask;
+
+ /* If user has not given any mask, then use chelsio supported mask. */
+ mask = umask ? umask : (const struct rte_flow_item_vf *)dmask;
+
+ CXGBE_FILL_FS(1, 1, pfvf_vld);
+
+ if (!val)
+ return 0; /* Wildcard, match all Vf */
+
+ if (val->id > UCHAR_MAX)
+ return rte_flow_error_set(e, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "VF ID > MAX(255)");
+
+ CXGBE_FILL_FS(val->id, mask->id, vf);
+
+ return 0;
+}
+
static int
ch_rte_parsetype_udp(const void *dmask, const struct rte_flow_item *item,
struct ch_filter_specification *fs,
.fptr = ch_rte_parsetype_pf,
.dmask = NULL,
},
+
+ [RTE_FLOW_ITEM_TYPE_VF] = {
+ .fptr = ch_rte_parsetype_vf,
+ .dmask = &(const struct rte_flow_item_vf){
+ .id = 0xffffffff,
+ }
+ },
};
static int
adap->params.filter2_wr_support = (ret == 0 && val[0] != 0);
}
+ /* Check if FW supports returning vin.
+ * If this is not supported, driver will interpret
+ * these values from viid.
+ */
+ params[0] = CXGBE_FW_PARAM_DEV(OPAQUE_VIID_SMT_EXTN);
+ ret = t4_query_params(adap, adap->mbox, adap->pf, 0,
+ 1, params, val);
+ adap->params.viid_smt_extn_support = (ret == 0 && val[0] != 0);
+
/* query tid-related parameters */
params[0] = CXGBE_FW_PARAM_DEV(NTID);
ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,