aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/cxgbe/adapter.h1
-rw-r--r--sys/dev/cxgbe/common/common.h8
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c85
-rw-r--r--sys/dev/cxgbe/common/t4_regs_values.h53
-rw-r--r--sys/dev/cxgbe/t4_main.c16
-rw-r--r--sys/dev/cxgbe/t4_sge.c7
-rw-r--r--sys/dev/cxgbe/tom/t4_connect.c40
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.c59
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.h2
9 files changed, 205 insertions, 66 deletions
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 434fb53d47ad..df0976a766be 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -562,7 +562,6 @@ struct adapter {
struct taskqueue *tq[NCHAN]; /* taskqueues that flush data out */
struct port_info *port[MAX_NPORTS];
uint8_t chan_map[NCHAN];
- uint32_t filter_mode;
#ifdef TCP_OFFLOAD
void *tom_softc; /* (struct tom_data *) */
diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h
index 53b214b263e6..22edff686fa9 100644
--- a/sys/dev/cxgbe/common/common.h
+++ b/sys/dev/cxgbe/common/common.h
@@ -219,6 +219,12 @@ struct tp_params {
unsigned int dack_re; /* DACK timer resolution */
unsigned int la_mask; /* what events are recorded by TP LA */
unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */
+ uint32_t vlan_pri_map;
+ uint32_t ingress_config;
+ int8_t vlan_shift;
+ int8_t vnic_shift;
+ int8_t port_shift;
+ int8_t protocol_shift;
};
struct vpd_params {
@@ -421,6 +427,8 @@ int t4_get_tp_version(struct adapter *adapter, u32 *vers);
int t4_check_fw_version(struct adapter *adapter);
int t4_init_hw(struct adapter *adapter, u32 fw_params);
int t4_prep_adapter(struct adapter *adapter);
+int t4_init_tp_params(struct adapter *adap);
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
int t4_port_init(struct port_info *p, int mbox, int pf, int vf);
int t4_reinit_adapter(struct adapter *adap);
void t4_fatal_err(struct adapter *adapter);
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index 76b17d9d30ca..50bfba709b5f 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -5521,6 +5521,91 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
return 0;
}
+/**
+ * t4_init_tp_params - initialize adap->params.tp
+ * @adap: the adapter
+ *
+ * Initialize various fields of the adapter's TP Parameters structure.
+ */
+int __devinit t4_init_tp_params(struct adapter *adap)
+{
+ int chan;
+ u32 v;
+
+ v = t4_read_reg(adap, A_TP_TIMER_RESOLUTION);
+ adap->params.tp.tre = G_TIMERRESOLUTION(v);
+ adap->params.tp.dack_re = G_DELAYEDACKRESOLUTION(v);
+
+ /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
+ for (chan = 0; chan < NCHAN; chan++)
+ adap->params.tp.tx_modq[chan] = chan;
+
+ /*
+ * Cache the adapter's Compressed Filter Mode and global Incress
+ * Configuration.
+ */
+ t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &adap->params.tp.vlan_pri_map, 1,
+ A_TP_VLAN_PRI_MAP);
+ t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &adap->params.tp.ingress_config, 1,
+ A_TP_INGRESS_CONFIG);
+
+ /*
+ * Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
+ * shift positions of several elements of the Compressed Filter Tuple
+ * for this adapter which we need frequently ...
+ */
+ adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
+ adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
+ adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
+ adap->params.tp.protocol_shift = t4_filter_field_shift(adap, F_PROTOCOL);
+
+ /*
+ * If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
+ * represents the presense of an Outer VLAN instead of a VNIC ID.
+ */
+ if ((adap->params.tp.ingress_config & F_VNIC) == 0)
+ adap->params.tp.vnic_shift = -1;
+
+ return 0;
+}
+
+/**
+ * t4_filter_field_shift - calculate filter field shift
+ * @adap: the adapter
+ * @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
+ *
+ * Return the shift position of a filter field within the Compressed
+ * Filter Tuple. The filter field is specified via its selection bit
+ * within TP_VLAN_PRI_MAL (filter mode). E.g. F_VLAN.
+ */
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
+{
+ unsigned int filter_mode = adap->params.tp.vlan_pri_map;
+ unsigned int sel;
+ int field_shift;
+
+ if ((filter_mode & filter_sel) == 0)
+ return -1;
+
+ for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
+ switch (filter_mode & sel) {
+ case F_FCOE: field_shift += W_FT_FCOE; break;
+ case F_PORT: field_shift += W_FT_PORT; break;
+ case F_VNIC_ID: field_shift += W_FT_VNIC_ID; break;
+ case F_VLAN: field_shift += W_FT_VLAN; break;
+ case F_TOS: field_shift += W_FT_TOS; break;
+ case F_PROTOCOL: field_shift += W_FT_PROTOCOL; break;
+ case F_ETHERTYPE: field_shift += W_FT_ETHERTYPE; break;
+ case F_MACMATCH: field_shift += W_FT_MACMATCH; break;
+ case F_MPSHITTYPE: field_shift += W_FT_MPSHITTYPE; break;
+ case F_FRAGMENTATION: field_shift += W_FT_FRAGMENTATION; break;
+ }
+ }
+ return field_shift;
+}
+
int __devinit t4_port_init(struct port_info *p, int mbox, int pf, int vf)
{
u8 addr[6];
diff --git a/sys/dev/cxgbe/common/t4_regs_values.h b/sys/dev/cxgbe/common/t4_regs_values.h
index aacda81a1065..40dabf1e9552 100644
--- a/sys/dev/cxgbe/common/t4_regs_values.h
+++ b/sys/dev/cxgbe/common/t4_regs_values.h
@@ -189,4 +189,57 @@
#define X_MBOWNER_FW 1
#define X_MBOWNER_PL 2
+/*
+ * PCI-E definitions.
+ * ==================
+ */
+
+#define X_WINDOW_SHIFT 10
+#define X_PCIEOFST_SHIFT 10
+
+/*
+ * TP definitions.
+ * ===============
+ */
+
+/*
+ * TP_VLAN_PRI_MAP controls which subset of fields will be present in the
+ * Compressed Filter Tuple for LE filters. Each bit set in TP_VLAN_PRI_MAP
+ * selects for a particular field being present. These fields, when present
+ * in the Compressed Filter Tuple, have the following widths in bits.
+ */
+#define W_FT_FCOE 1
+#define W_FT_PORT 3
+#define W_FT_VNIC_ID 17
+#define W_FT_VLAN 17
+#define W_FT_TOS 8
+#define W_FT_PROTOCOL 8
+#define W_FT_ETHERTYPE 16
+#define W_FT_MACMATCH 9
+#define W_FT_MPSHITTYPE 3
+#define W_FT_FRAGMENTATION 1
+
+/*
+ * Some of the Compressed Filter Tuple fields have internal structure. These
+ * bit shifts/masks describe those structures. All shifts are relative to the
+ * base position of the fields within the Compressed Filter Tuple
+ */
+#define S_FT_VLAN_VLD 16
+#define V_FT_VLAN_VLD(x) ((x) << S_FT_VLAN_VLD)
+#define F_FT_VLAN_VLD V_FT_VLAN_VLD(1U)
+
+#define S_FT_VNID_ID_VF 0
+#define M_FT_VNID_ID_VF 0x7fU
+#define V_FT_VNID_ID_VF(x) ((x) << S_FT_VNID_ID_VF)
+#define G_FT_VNID_ID_VF(x) (((x) >> S_FT_VNID_ID_VF) & M_FT_VNID_ID_VF)
+
+#define S_FT_VNID_ID_PF 7
+#define M_FT_VNID_ID_PF 0x7U
+#define V_FT_VNID_ID_PF(x) ((x) << S_FT_VNID_ID_PF)
+#define G_FT_VNID_ID_PF(x) (((x) >> S_FT_VNID_ID_PF) & M_FT_VNID_ID_PF)
+
+#define S_FT_VNID_ID_VLD 16
+#define V_FT_VNID_ID_VLD(x) ((x) << S_FT_VNID_ID_VLD)
+#define F_FT_VNID_ID_VLD(x) V_FT_VNID_ID_VLD(1U)
+
#endif /* __T4_REGS_VALUES_H__ */
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 1303299c154d..b0d0532daa6b 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -633,9 +633,6 @@ t4_attach(device_t dev)
if (rc != 0)
goto done; /* error message displayed already */
- for (i = 0; i < NCHAN; i++)
- sc->params.tp.tx_modq[i] = i;
-
rc = t4_create_dma_tag(sc);
if (rc != 0)
goto done; /* error message displayed already */
@@ -2089,6 +2086,7 @@ prep_firmware(struct adapter *sc)
G_FW_HDR_FW_VER_MINOR(sc->params.fw_vers),
G_FW_HDR_FW_VER_MICRO(sc->params.fw_vers),
G_FW_HDR_FW_VER_BUILD(sc->params.fw_vers));
+ t4_get_tp_version(sc, &sc->params.tp_vers);
/* Reset device */
if (need_fw_reset &&
@@ -6522,13 +6520,14 @@ get_filter_mode(struct adapter *sc, uint32_t *mode)
t4_read_indirect(sc, A_TP_PIO_ADDR, A_TP_PIO_DATA, &fconf, 1,
A_TP_VLAN_PRI_MAP);
- if (sc->filter_mode != fconf) {
+ if (sc->params.tp.vlan_pri_map != fconf) {
log(LOG_WARNING, "%s: cached filter mode out of sync %x %x.\n",
- device_get_nameunit(sc->dev), sc->filter_mode, fconf);
- sc->filter_mode = fconf;
+ device_get_nameunit(sc->dev), sc->params.tp.vlan_pri_map,
+ fconf);
+ sc->params.tp.vlan_pri_map = fconf;
}
- *mode = fconf_to_mode(sc->filter_mode);
+ *mode = fconf_to_mode(sc->params.tp.vlan_pri_map);
end_synchronized_op(sc, LOCK_HELD);
return (0);
@@ -6661,7 +6660,8 @@ set_filter(struct adapter *sc, struct t4_filter *t)
}
/* Validate against the global filter mode */
- if ((sc->filter_mode | fspec_to_fconf(&t->fs)) != sc->filter_mode) {
+ if ((sc->params.tp.vlan_pri_map | fspec_to_fconf(&t->fs)) !=
+ sc->params.tp.vlan_pri_map) {
rc = E2BIG;
goto done;
}
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 84fb44ec1415..5f40f5c497c5 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -474,16 +474,11 @@ t4_read_chip_settings(struct adapter *sc)
s->s_qpp = r & M_QUEUESPERPAGEPF0;
}
- r = t4_read_reg(sc, A_TP_TIMER_RESOLUTION);
- sc->params.tp.tre = G_TIMERRESOLUTION(r);
- sc->params.tp.dack_re = G_DELAYEDACKRESOLUTION(r);
+ t4_init_tp_params(sc);
t4_read_mtu_tbl(sc, sc->params.mtus, NULL);
t4_load_mtus(sc, sc->params.mtus, sc->params.a_wnd, sc->params.b_wnd);
- t4_read_indirect(sc, A_TP_PIO_ADDR, A_TP_PIO_DATA, &sc->filter_mode, 1,
- A_TP_VLAN_PRI_MAP);
-
return (rc);
}
diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c
index ac48d313a0ad..69dca96c66ae 100644
--- a/sys/dev/cxgbe/tom/t4_connect.c
+++ b/sys/dev/cxgbe/tom/t4_connect.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include "common/common.h"
#include "common/t4_msg.h"
#include "common/t4_regs.h"
+#include "common/t4_regs_values.h"
#include "tom/t4_tom_l2t.h"
#include "tom/t4_tom.h"
@@ -384,10 +385,18 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
if (toep->ce == NULL)
DONT_OFFLOAD_ACTIVE_OPEN(ENOENT);
- INIT_TP_WR(cpl, 0);
+ if (is_t4(sc)) {
+ INIT_TP_WR(cpl, 0);
+ cpl->params = select_ntuple(pi, toep->l2te);
+ } else {
+ struct cpl_t5_act_open_req6 *c5 = (void *)cpl;
+
+ INIT_TP_WR(c5, 0);
+ c5->rsvd = 0;
+ c5->params = select_ntuple(pi, toep->l2te);
+ }
OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
qid_atid));
-
cpl->local_port = inp->inp_lport;
cpl->local_ip_hi = *(uint64_t *)&inp->in6p_laddr.s6_addr[0];
cpl->local_ip_lo = *(uint64_t *)&inp->in6p_laddr.s6_addr[8];
@@ -397,20 +406,19 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale,
toep->rx_credits, toep->ulp_mode);
cpl->opt2 = calc_opt2a(so, toep);
+ } else {
+ struct cpl_act_open_req *cpl = wrtod(wr);
+
if (is_t4(sc)) {
- cpl->params = select_ntuple(pi, toep->l2te,
- sc->filter_mode);
+ INIT_TP_WR(cpl, 0);
+ cpl->params = select_ntuple(pi, toep->l2te);
} else {
- struct cpl_t5_act_open_req6 *c5 = (void *)cpl;
+ struct cpl_t5_act_open_req *c5 = (void *)cpl;
+ INIT_TP_WR(c5, 0);
c5->rsvd = 0;
- c5->params = select_ntuple(pi, toep->l2te,
- sc->filter_mode);
+ c5->params = select_ntuple(pi, toep->l2te);
}
- } else {
- struct cpl_act_open_req *cpl = wrtod(wr);
-
- INIT_TP_WR(cpl, 0);
OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
qid_atid));
inp_4tuple_get(inp, &cpl->local_ip, &cpl->local_port,
@@ -418,16 +426,6 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale,
toep->rx_credits, toep->ulp_mode);
cpl->opt2 = calc_opt2a(so, toep);
- if (is_t4(sc)) {
- cpl->params = select_ntuple(pi, toep->l2te,
- sc->filter_mode);
- } else {
- struct cpl_t5_act_open_req6 *c5 = (void *)cpl;
-
- c5->rsvd = 0;
- c5->params = select_ntuple(pi, toep->l2te,
- sc->filter_mode);
- }
}
CTR5(KTR_CXGBE, "%s: atid %u (%s), toep %p, inp %p", __func__,
diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index a254253e6cfb..8e7965a697c5 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include "common/common.h"
#include "common/t4_msg.h"
#include "common/t4_regs.h"
+#include "common/t4_regs_values.h"
#include "tom/t4_tom_l2t.h"
#include "tom/t4_tom.h"
@@ -513,38 +514,38 @@ calc_opt0(struct socket *so, struct port_info *pi, struct l2t_entry *e,
return htobe64(opt0);
}
-#define FILTER_SEL_WIDTH_P_FC (3 + 1)
-#define FILTER_SEL_WIDTH_VIN_P_FC (6 + 7 + FILTER_SEL_WIDTH_P_FC)
-#define FILTER_SEL_WIDTH_TAG_P_FC (3 + FILTER_SEL_WIDTH_VIN_P_FC)
-#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
-#define VLAN_NONE 0xfff
-#define FILTER_SEL_VLAN_NONE 0xffff
-
uint64_t
-select_ntuple(struct port_info *pi, struct l2t_entry *e, uint32_t filter_mode)
+select_ntuple(struct port_info *pi, struct l2t_entry *e)
{
+ struct adapter *sc = pi->adapter;
+ struct tp_params *tp = &sc->params.tp;
uint16_t viid = pi->viid;
- uint32_t ntuple = 0;
-
- if (filter_mode == HW_TPL_FR_MT_PR_IV_P_FC) {
- if (e->vlan == VLAN_NONE)
- ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
- else {
- ntuple |= e->vlan << FILTER_SEL_WIDTH_P_FC;
- ntuple |= 1 << FILTER_SEL_WIDTH_VLD_TAG_P_FC;
- }
- ntuple |= e->lport << S_PORT;
- ntuple |= IPPROTO_TCP << FILTER_SEL_WIDTH_VLD_TAG_P_FC;
- } else if (filter_mode == HW_TPL_FR_MT_PR_OV_P_FC) {
- ntuple |= G_FW_VIID_VIN(viid) << FILTER_SEL_WIDTH_P_FC;
- ntuple |= G_FW_VIID_PFN(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
- ntuple |= G_FW_VIID_VIVLD(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
- ntuple |= e->lport << S_PORT;
- ntuple |= IPPROTO_TCP << FILTER_SEL_WIDTH_VLD_TAG_P_FC;
- }
-
- if (is_t4(pi->adapter))
- return (htobe32(ntuple));
+ uint64_t ntuple = 0;
+
+ /*
+ * Initialize each of the fields which we care about which are present
+ * in the Compressed Filter Tuple.
+ */
+ if (tp->vlan_shift >= 0 && e->vlan != CPL_L2T_VLAN_NONE)
+ ntuple |= (uint64_t)(F_FT_VLAN_VLD | e->vlan) << tp->vlan_shift;
+
+ if (tp->port_shift >= 0)
+ ntuple |= (uint64_t)e->lport << tp->port_shift;
+
+ if (tp->protocol_shift >= 0)
+ ntuple |= (uint64_t)IPPROTO_TCP << tp->protocol_shift;
+
+ if (tp->vnic_shift >= 0) {
+ uint32_t vf = G_FW_VIID_VIN(viid);
+ uint32_t pf = G_FW_VIID_PFN(viid);
+ uint32_t vld = G_FW_VIID_VIVLD(viid);
+
+ ntuple |= (uint64_t)(V_FT_VNID_ID_VF(vf) | V_FT_VNID_ID_PF(pf) |
+ V_FT_VNID_ID_VLD(vld)) << tp->vnic_shift;
+ }
+
+ if (is_t4(sc))
+ return (htobe32((uint32_t)ntuple));
else
return (htobe64(V_FILTER_TUPLE(ntuple)));
}
diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h
index 4411a0642dbd..b86a76ce28f0 100644
--- a/sys/dev/cxgbe/tom/t4_tom.h
+++ b/sys/dev/cxgbe/tom/t4_tom.h
@@ -234,7 +234,7 @@ u_long select_rcv_wnd(struct socket *);
int select_rcv_wscale(void);
uint64_t calc_opt0(struct socket *, struct port_info *, struct l2t_entry *,
int, int, int, int);
-uint64_t select_ntuple(struct port_info *, struct l2t_entry *, uint32_t);
+uint64_t select_ntuple(struct port_info *, struct l2t_entry *);
void set_tcpddp_ulp_mode(struct toepcb *);
int negative_advice(int);
struct clip_entry *hold_lip(struct tom_data *, struct in6_addr *);