- Read all TP parameters in one place.

- Read the filter mode, calculate various shifts, and use them
  properly during active open (in select_ntuple).

MFC after:	1 day
This commit is contained in:
Navdeep Parhar 2013-07-04 17:55:52 +00:00
parent 6f7e608220
commit c337fa30af
9 changed files with 205 additions and 66 deletions

View file

@ -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 *) */

View file

@ -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);

View file

@ -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];

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);
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);
}
} else {
struct cpl_act_open_req *cpl = wrtod(wr);
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_req *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_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__,

View file

@ -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;
uint64_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;
}
/*
* 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 (is_t4(pi->adapter))
return (htobe32(ntuple));
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)));
}

View file

@ -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 *);