Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 4 Mar 2016 13:11:14 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r296383 - in head/sys/dev/cxgbe: . common
Message-ID:  <201603041311.u24DBEog076885@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Fri Mar  4 13:11:13 2016
New Revision: 296383
URL: https://svnweb.freebsd.org/changeset/base/296383

Log:
  cxgbe(4): Very basic T6 awareness.  This is part of ongoing work to
  update to the latest internal shared code.
  
  - Add a chip_params structure to keep track of hardware constants for
    all generations of Terminators handled by cxgbe.
  - Update t4_hw_pci_read_cfg4 to work with T6.
  - Update the hardware debug sysctls (hidden within dev.<tNnex>.<n>.misc.*) to
    work with T6.  Most of the changes are in the decoders for the CIM
    logic analyzer and the MPS TCAM.
  - Acquire the regwin lock around indirect register accesses.
  
  Obtained from:	Chelsio Communications
  Sponsored by:	Chelsio Communications

Modified:
  head/sys/dev/cxgbe/adapter.h
  head/sys/dev/cxgbe/common/common.h
  head/sys/dev/cxgbe/common/t4_hw.c
  head/sys/dev/cxgbe/common/t4_hw.h
  head/sys/dev/cxgbe/t4_main.c
  head/sys/dev/cxgbe/t4_netmap.c
  head/sys/dev/cxgbe/t4_sge.c

Modified: head/sys/dev/cxgbe/adapter.h
==============================================================================
--- head/sys/dev/cxgbe/adapter.h	Fri Mar  4 09:07:30 2016	(r296382)
+++ head/sys/dev/cxgbe/adapter.h	Fri Mar  4 13:11:13 2016	(r296383)
@@ -758,9 +758,9 @@ struct adapter {
 	struct sge sge;
 	int lro_timeout;
 
-	struct taskqueue *tq[NCHAN];	/* General purpose taskqueues */
+	struct taskqueue *tq[MAX_NCHAN];	/* General purpose taskqueues */
 	struct port_info *port[MAX_NPORTS];
-	uint8_t chan_map[NCHAN];
+	uint8_t chan_map[MAX_NCHAN];
 
 #ifdef TCP_OFFLOAD
 	void *tom_softc;	/* (struct tom_data *) */
@@ -791,6 +791,7 @@ struct adapter {
 	char cfg_file[32];
 	u_int cfcsum;
 	struct adapter_params params;
+	const struct chip_params *chip_params;
 	struct t4_virt_res vres;
 
 	uint16_t linkcaps;

Modified: head/sys/dev/cxgbe/common/common.h
==============================================================================
--- head/sys/dev/cxgbe/common/common.h	Fri Mar  4 09:07:30 2016	(r296382)
+++ head/sys/dev/cxgbe/common/common.h	Fri Mar  4 13:11:13 2016	(r296383)
@@ -188,25 +188,25 @@ struct tp_fcoe_stats {
 };
 
 struct tp_err_stats {
-	u32 mac_in_errs[4];
-	u32 hdr_in_errs[4];
-	u32 tcp_in_errs[4];
-	u32 tnl_cong_drops[4];
-	u32 ofld_chan_drops[4];
-	u32 tnl_tx_drops[4];
-	u32 ofld_vlan_drops[4];
-	u32 tcp6_in_errs[4];
+	u32 mac_in_errs[MAX_NCHAN];
+	u32 hdr_in_errs[MAX_NCHAN];
+	u32 tcp_in_errs[MAX_NCHAN];
+	u32 tnl_cong_drops[MAX_NCHAN];
+	u32 ofld_chan_drops[MAX_NCHAN];
+	u32 tnl_tx_drops[MAX_NCHAN];
+	u32 ofld_vlan_drops[MAX_NCHAN];
+	u32 tcp6_in_errs[MAX_NCHAN];
 	u32 ofld_no_neigh;
 	u32 ofld_cong_defer;
 };
 
 struct tp_proxy_stats {
-	u32 proxy[4];
+	u32 proxy[MAX_NCHAN];
 };
 
 struct tp_cpl_stats {
-	u32 req[4];
-	u32 rsp[4];
+	u32 req[MAX_NCHAN];
+	u32 rsp[MAX_NCHAN];
 };
 
 struct tp_rdma_stats {
@@ -219,7 +219,7 @@ struct tp_params {
 	unsigned int tre;            /* log2 of core clocks per TP tick */
 	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 */
+	unsigned short tx_modq[MAX_NCHAN];  /* channel to modulation queue map */
 	uint32_t vlan_pri_map;
 	uint32_t ingress_config;
 	int8_t vlan_shift;
@@ -253,6 +253,19 @@ struct devlog_params {
 	u32 size;			/* size of log */
 };
 
+/* Stores chip specific parameters */
+struct chip_params {
+	u8 nchan;
+	u8 pm_stats_cnt;
+	u8 cng_ch_bits_log;		/* congestion channel map bits width */
+	u8 nsched_cls;
+	u8 cim_num_obq;
+	u16 mps_rplc_size;
+	u16 vfcount;
+	u32 sge_fl_db;
+	u16 mps_tcam_size;
+};
+
 struct adapter_params {
 	struct tp_params  tp;
 	struct vpd_params vpd;
@@ -292,6 +305,7 @@ struct adapter_params {
 
 #define CHELSIO_T4		0x4
 #define CHELSIO_T5		0x5
+#define CHELSIO_T6		0x6
 
 struct trace_params {
 	u32 data[TRACE_LEN / 4];
@@ -366,6 +380,11 @@ static inline int is_t5(struct adapter *
 	return adap->params.chipid == CHELSIO_T5;
 }
 
+static inline int is_t6(struct adapter *adap)
+{
+	return adap->params.chipid == CHELSIO_T6;
+}
+
 static inline int is_fpga(struct adapter *adap)
 {
 	 return adap->params.fpga;

Modified: head/sys/dev/cxgbe/common/t4_hw.c
==============================================================================
--- head/sys/dev/cxgbe/common/t4_hw.c	Fri Mar  4 09:07:30 2016	(r296382)
+++ head/sys/dev/cxgbe/common/t4_hw.c	Fri Mar  4 13:11:13 2016	(r296383)
@@ -154,26 +154,49 @@ void t4_write_indirect(struct adapter *a
  * mechanism.  This guarantees that we get the real value even if we're
  * operating within a Virtual Machine and the Hypervisor is trapping our
  * Configuration Space accesses.
+ *
+ * N.B. This routine should only be used as a last resort: the firmware uses
+ *      the backdoor registers on a regular basis and we can end up
+ *      conflicting with it's uses!
  */
 u32 t4_hw_pci_read_cfg4(adapter_t *adap, int reg)
 {
-	t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ,
-		     F_ENABLE | F_LOCALCFG | V_FUNCTION(adap->pf) |
-		     V_REGISTER(reg));
-	return t4_read_reg(adap, A_PCIE_CFG_SPACE_DATA);
+	u32 req = V_FUNCTION(adap->pf) | V_REGISTER(reg);
+	u32 val;
+
+	if (chip_id(adap) <= CHELSIO_T5)
+		req |= F_ENABLE;
+	else
+		req |= F_T6_ENABLE;
+
+	if (is_t4(adap))
+		req |= F_LOCALCFG;
+
+	t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ, req);
+	val = t4_read_reg(adap, A_PCIE_CFG_SPACE_DATA);
+
+	/*
+	 * Reset F_ENABLE to 0 so reads of PCIE_CFG_SPACE_DATA won't cause a
+	 * Configuration Space read.  (None of the other fields matter when
+	 * F_ENABLE is 0 so a simple register write is easier than a
+	 * read-modify-write via t4_set_reg_field().)
+	 */
+	t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ, 0);
+
+	return val;
 }
 
 /*
- *	t4_report_fw_error - report firmware error
- *	@adap: the adapter
+ * t4_report_fw_error - report firmware error
+ * @adap: the adapter
  *
- *	The adapter firmware can indicate error conditions to the host.
- *	This routine prints out the reason for the firmware error (as
- *	reported by the firmware).
+ * The adapter firmware can indicate error conditions to the host.
+ * If the firmware has indicated an error, print out the reason for
+ * the firmware error.
  */
 static void t4_report_fw_error(struct adapter *adap)
 {
-	static const char *reason[] = {
+	static const char *const reason[] = {
 		"Crash",			/* PCIE_FW_EVAL_CRASH */
 		"During Device Preparation",	/* PCIE_FW_EVAL_PREP */
 		"During Device Configuration",	/* PCIE_FW_EVAL_CONF */
@@ -1512,7 +1535,6 @@ out:
 void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres)
 {
 	unsigned int i, v;
-	int cim_num_obq = is_t4(adap) ? CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
 
 	for (i = 0; i < CIM_NUM_IBQ; i++) {
 		t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_IBQSELECT |
@@ -1522,7 +1544,7 @@ void t4_read_cimq_cfg(struct adapter *ad
 		*size++ = G_CIMQSIZE(v) * 256; /* value is in 256-byte units */
 		*thres++ = G_QUEFULLTHRSH(v) * 8;   /* 8-byte unit */
 	}
-	for (i = 0; i < cim_num_obq; i++) {
+	for (i = 0; i < adap->chip_params->cim_num_obq; i++) {
 		t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
 			     V_QUENUMSELECT(i));
 		v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
@@ -1587,9 +1609,8 @@ int t4_read_cim_obq(struct adapter *adap
 {
 	int i, err;
 	unsigned int addr, v, nwords;
-	int cim_num_obq = is_t4(adap) ? CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
 
-	if (qid >= cim_num_obq || (n & 3))
+	if (qid >= adap->chip_params->cim_num_obq || (n & 3))
 		return -EINVAL;
 
 	t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
@@ -1743,7 +1764,15 @@ int t4_cim_read_la(struct adapter *adap,
 		ret = t4_cim_read(adap, A_UP_UP_DBG_LA_DATA, 1, &la_buf[i]);
 		if (ret)
 			break;
+		/* address can't exceed 0xfff (UpDbgLaRdPtr is of 12-bits) */
 		idx = (idx + 1) & M_UPDBGLARDPTR;
+		/*
+		 * Bits 0-3 of UpDbgLaRdPtr can be between 0000 to 1001 to
+		 * identify the 32-bit portion of the full 312-bit data
+		 */
+		if (is_t6(adap))
+			while ((idx & 0xf) > 9)
+				idx = (idx + 1) % M_UPDBGLARDPTR;
 	}
 restart:
 	if (cfg & F_UPDBGLAEN) {
@@ -3223,7 +3252,7 @@ void t4_tp_get_tcp_stats(struct adapter 
  */
 void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st)
 {
-	int nchan = NCHAN;
+	int nchan = adap->chip_params->nchan;
 
 	t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
 			st->mac_in_errs, nchan, A_TP_MIB_MAC_IN_ERR_0);
@@ -3255,8 +3284,10 @@ void t4_tp_get_err_stats(struct adapter 
  */
 void t4_tp_get_proxy_stats(struct adapter *adap, struct tp_proxy_stats *st)
 {
+	int nchan = adap->chip_params->nchan;
+
 	t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->proxy,
-			 4, A_TP_MIB_TNL_LPBK_0);
+			 nchan, A_TP_MIB_TNL_LPBK_0);
 }
 
 /**
@@ -3268,8 +3299,12 @@ void t4_tp_get_proxy_stats(struct adapte
  */
 void t4_tp_get_cpl_stats(struct adapter *adap, struct tp_cpl_stats *st)
 {
+	int nchan = adap->chip_params->nchan;
+
 	t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->req,
-			 8, A_TP_MIB_CPL_IN_REQ_0);
+			 nchan, A_TP_MIB_CPL_IN_REQ_0);
+	t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->rsp,
+			 nchan, A_TP_MIB_CPL_OUT_RSP_0);
 }
 
 /**
@@ -3672,14 +3707,18 @@ void t4_get_chan_txrate(struct adapter *
 	v = t4_read_reg(adap, A_TP_TX_TRATE);
 	nic_rate[0] = chan_rate(adap, G_TNLRATE0(v));
 	nic_rate[1] = chan_rate(adap, G_TNLRATE1(v));
-	nic_rate[2] = chan_rate(adap, G_TNLRATE2(v));
-	nic_rate[3] = chan_rate(adap, G_TNLRATE3(v));
+	if (adap->chip_params->nchan > 2) {
+		nic_rate[2] = chan_rate(adap, G_TNLRATE2(v));
+		nic_rate[3] = chan_rate(adap, G_TNLRATE3(v));
+	}
 
 	v = t4_read_reg(adap, A_TP_TX_ORATE);
 	ofld_rate[0] = chan_rate(adap, G_OFDRATE0(v));
 	ofld_rate[1] = chan_rate(adap, G_OFDRATE1(v));
-	ofld_rate[2] = chan_rate(adap, G_OFDRATE2(v));
-	ofld_rate[3] = chan_rate(adap, G_OFDRATE3(v));
+	if (adap->chip_params->nchan > 2) {
+		ofld_rate[2] = chan_rate(adap, G_OFDRATE2(v));
+		ofld_rate[3] = chan_rate(adap, G_OFDRATE3(v));
+	}
 }
 
 /**
@@ -3822,7 +3861,7 @@ void t4_pmtx_get_stats(struct adapter *a
 	int i;
 	u32 data[2];
 
-	for (i = 0; i < PM_NSTATS; i++) {
+	for (i = 0; i < adap->chip_params->pm_stats_cnt; i++) {
 		t4_write_reg(adap, A_PM_TX_STAT_CONFIG, i + 1);
 		cnt[i] = t4_read_reg(adap, A_PM_TX_STAT_COUNT);
 		if (is_t4(adap))
@@ -3849,7 +3888,7 @@ void t4_pmrx_get_stats(struct adapter *a
 	int i;
 	u32 data[2];
 
-	for (i = 0; i < PM_NSTATS; i++) {
+	for (i = 0; i < adap->chip_params->pm_stats_cnt; i++) {
 		t4_write_reg(adap, A_PM_RX_STAT_CONFIG, i + 1);
 		cnt[i] = t4_read_reg(adap, A_PM_RX_STAT_COUNT);
 		if (is_t4(adap))
@@ -3878,7 +3917,7 @@ static unsigned int get_mps_bg_map(struc
 
 	if (n == 0)
 		return idx == 0 ? 0xf : 0;
-	if (n == 1)
+	if (n == 1 && chip_id(adap) <= CHELSIO_T5)
 		return idx < 2 ? (3 << (2 * idx)) : 0;
 	return 1 << idx;
 }
@@ -5130,9 +5169,7 @@ int t4_alloc_mac_filt(struct adapter *ad
 	int offset, ret = 0;
 	struct fw_vi_mac_cmd c;
 	unsigned int nfilters = 0;
-	unsigned int max_naddr = is_t4(adap) ?
-				       NUM_MPS_CLS_SRAM_L_INSTANCES :
-				       NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
+	unsigned int max_naddr = adap->chip_params->mps_tcam_size;
 	unsigned int rem = naddr;
 
 	if (naddr > max_naddr)
@@ -5223,9 +5260,7 @@ int t4_change_mac(struct adapter *adap, 
 	int ret, mode;
 	struct fw_vi_mac_cmd c;
 	struct fw_vi_mac_exact *p = c.u.exact;
-	unsigned int max_mac_addr = is_t4(adap) ?
-				    NUM_MPS_CLS_SRAM_L_INSTANCES :
-				    NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
+	unsigned int max_mac_addr = adap->chip_params->mps_tcam_size;
 
 	if (idx < 0)                             /* new allocation */
 		idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC;
@@ -5581,6 +5616,54 @@ static void __devinit set_pcie_completio
 	}
 }
 
+static const struct chip_params *get_chip_params(int chipid)
+{
+	static const struct chip_params chip_params[] = {
+		{
+			/* T4 */
+			.nchan = NCHAN,
+			.pm_stats_cnt = PM_NSTATS,
+			.cng_ch_bits_log = 2,
+			.nsched_cls = 15,
+			.cim_num_obq = CIM_NUM_OBQ,
+			.mps_rplc_size = 128,
+			.vfcount = 128,
+			.sge_fl_db = F_DBPRIO,
+			.mps_tcam_size = NUM_MPS_CLS_SRAM_L_INSTANCES,
+		},
+		{
+			/* T5 */
+			.nchan = NCHAN,
+			.pm_stats_cnt = PM_NSTATS,
+			.cng_ch_bits_log = 2,
+			.nsched_cls = 16,
+			.cim_num_obq = CIM_NUM_OBQ_T5,
+			.mps_rplc_size = 128,
+			.vfcount = 128,
+			.sge_fl_db = F_DBPRIO | F_DBTYPE,
+			.mps_tcam_size = NUM_MPS_T5_CLS_SRAM_L_INSTANCES,
+		},
+		{
+			/* T6 */
+			.nchan = T6_NCHAN,
+			.pm_stats_cnt = T6_PM_NSTATS,
+			.cng_ch_bits_log = 3,
+			.nsched_cls = 16,
+			.cim_num_obq = CIM_NUM_OBQ_T5,
+			.mps_rplc_size = 256,
+			.vfcount = 256,
+			.sge_fl_db = 0,
+			.mps_tcam_size = NUM_MPS_T5_CLS_SRAM_L_INSTANCES,
+		},
+	};
+
+	chipid -= CHELSIO_T4;
+	if (chipid < 0 || chipid >= ARRAY_SIZE(chip_params))
+		return NULL;
+
+	return &chip_params[chipid];
+}
+
 /**
  *	t4_prep_adapter - prepare SW and HW for operation
  *	@adapter: the adapter
@@ -5611,6 +5694,11 @@ int __devinit t4_prep_adapter(struct ada
 			return -EINVAL;
 		}
 	}
+
+	adapter->chip_params = get_chip_params(chip_id(adapter));
+	if (adapter->chip_params == NULL)
+		return -EINVAL;
+
 	adapter->params.pci.vpd_cap_addr =
 	    t4_os_find_pci_capability(adapter, PCI_CAP_ID_VPD);
 
@@ -5624,7 +5712,7 @@ int __devinit t4_prep_adapter(struct ada
 
 	/* Cards with real ASICs have the chipid in the PCIe device id */
 	t4_os_pci_read_cfg2(adapter, PCI_DEVICE_ID, &device_id);
-	if (device_id >> 12 == adapter->params.chipid)
+	if (device_id >> 12 == chip_id(adapter))
 		adapter->params.cim_la_size = CIMLA_SIZE;
 	else {
 		/* FPGA */
@@ -5662,7 +5750,7 @@ int __devinit t4_init_tp_params(struct a
 	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++)
+	for (chan = 0; chan < MAX_NCHAN; chan++)
 		adap->params.tp.tx_modq[chan] = chan;
 
 	t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,

Modified: head/sys/dev/cxgbe/common/t4_hw.h
==============================================================================
--- head/sys/dev/cxgbe/common/t4_hw.h	Fri Mar  4 09:07:30 2016	(r296382)
+++ head/sys/dev/cxgbe/common/t4_hw.h	Fri Mar  4 13:11:13 2016	(r296383)
@@ -34,6 +34,8 @@
 
 enum {
 	NCHAN           = 4,     /* # of HW channels */
+	T6_NCHAN        = 2,
+	MAX_NCHAN       = 4,
 	MAX_MTU         = 9600,  /* max MAC MTU, excluding header + FCS */
 	EEPROMSIZE      = 17408, /* Serial EEPROM physical size */
 	EEPROMVSIZE     = 32768, /* Serial EEPROM virtual address space size */
@@ -44,6 +46,8 @@ enum {
 	NCCTRL_WIN      = 32,    /* # of congestion control windows */
 	NTX_SCHED       = 8,     /* # of HW Tx scheduling queues */
 	PM_NSTATS       = 5,     /* # of PM stats */
+	T6_PM_NSTATS    = 7,
+	MAX_PM_NSTATS   = 7,
 	MBOX_LEN        = 64,    /* mailbox size in bytes */
 	NTRACE          = 4,     /* # of tracing filters */
 	TRACE_LEN       = 112,   /* length of trace data and mask */

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c	Fri Mar  4 09:07:30 2016	(r296382)
+++ head/sys/dev/cxgbe/t4_main.c	Fri Mar  4 13:11:13 2016	(r296383)
@@ -453,6 +453,7 @@ static int sysctl_temperature(SYSCTL_HAN
 static int sysctl_cctrl(SYSCTL_HANDLER_ARGS);
 static int sysctl_cim_ibq_obq(SYSCTL_HANDLER_ARGS);
 static int sysctl_cim_la(SYSCTL_HANDLER_ARGS);
+static int sysctl_cim_la_t6(SYSCTL_HANDLER_ARGS);
 static int sysctl_cim_ma_la(SYSCTL_HANDLER_ARGS);
 static int sysctl_cim_pif_la(SYSCTL_HANDLER_ARGS);
 static int sysctl_cim_qcfg(SYSCTL_HANDLER_ARGS);
@@ -465,6 +466,7 @@ static int sysctl_lb_stats(SYSCTL_HANDLE
 static int sysctl_linkdnrc(SYSCTL_HANDLER_ARGS);
 static int sysctl_meminfo(SYSCTL_HANDLER_ARGS);
 static int sysctl_mps_tcam(SYSCTL_HANDLER_ARGS);
+static int sysctl_mps_tcam_t6(SYSCTL_HANDLER_ARGS);
 static int sysctl_path_mtus(SYSCTL_HANDLER_ARGS);
 static int sysctl_pm_stats(SYSCTL_HANDLER_ARGS);
 static int sysctl_rdma_stats(SYSCTL_HANDLER_ARGS);
@@ -4956,7 +4958,7 @@ cxgbe_refresh_stats(struct adapter *sc, 
 
 	tnl_cong_drops = 0;
 	t4_get_port_stats(sc, pi->tx_chan, &pi->stats);
-	for (i = 0; i < NCHAN; i++) {
+	for (i = 0; i < sc->chip_params->nchan; i++) {
 		if (pi->rx_chan_map & (1 << i)) {
 			mtx_lock(&sc->regwin_lock);
 			t4_read_indirect(sc, A_TP_MIB_INDEX, A_TP_MIB_DATA, &v,
@@ -5239,7 +5241,8 @@ t4_sysctls(struct adapter *sc)
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_la",
 	    CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
-	    sysctl_cim_la, "A", "CIM logic analyzer");
+	    chip_id(sc) <= CHELSIO_T5 ? sysctl_cim_la : sysctl_cim_la_t6,
+	    "A", "CIM logic analyzer");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ma_la",
 	    CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
@@ -5269,7 +5272,7 @@ t4_sysctls(struct adapter *sc)
 	    CTLTYPE_STRING | CTLFLAG_RD, sc, 5 + CIM_NUM_IBQ,
 	    sysctl_cim_ibq_obq, "A", "CIM OBQ 5 (NCSI)");
 
-	if (is_t5(sc)) {
+	if (chip_id(sc) > CHELSIO_T4) {
 		SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_sge0_rx",
 		    CTLTYPE_STRING | CTLFLAG_RD, sc, 6 + CIM_NUM_IBQ,
 		    sysctl_cim_ibq_obq, "A", "CIM OBQ 6 (SGE0-RX)");
@@ -5321,7 +5324,8 @@ t4_sysctls(struct adapter *sc)
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "mps_tcam",
 	    CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
-	    sysctl_mps_tcam, "A", "MPS TCAM entries");
+	    chip_id(sc) <= CHELSIO_T5 ? sysctl_mps_tcam : sysctl_mps_tcam_t6,
+	    "A", "MPS TCAM entries");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "path_mtus",
 	    CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
@@ -6034,7 +6038,7 @@ sysctl_cim_ibq_obq(SYSCTL_HANDLER_ARGS)
 	int rc, i, n, qid = arg2;
 	uint32_t *buf, *p;
 	char *qtype;
-	u_int cim_num_obq = is_t4(sc) ? CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
+	u_int cim_num_obq = sc->chip_params->cim_num_obq;
 
 	KASSERT(qid >= 0 && qid < CIM_NUM_IBQ + cim_num_obq,
 	    ("%s: bad qid %d\n", __func__, qid));
@@ -6091,6 +6095,8 @@ sysctl_cim_la(SYSCTL_HANDLER_ARGS)
 	uint32_t *buf, *p;
 	int rc;
 
+	MPASS(chip_id(sc) <= CHELSIO_T5);
+
 	rc = -t4_cim_read(sc, A_UP_UP_DBG_LA_CFG, 1, &cfg);
 	if (rc != 0)
 		return (rc);
@@ -6114,10 +6120,7 @@ sysctl_cim_la(SYSCTL_HANDLER_ARGS)
 	    cfg & F_UPDBGLACAPTPCONLY ? "" :
 	    "     LS0Stat  LS0Addr             LS0Data");
 
-	KASSERT((sc->params.cim_la_size & 7) == 0,
-	    ("%s: p will walk off the end of buf", __func__));
-
-	for (p = buf; p < &buf[sc->params.cim_la_size]; p += 8) {
+	for (p = buf; p <= &buf[sc->params.cim_la_size - 8]; p += 8) {
 		if (cfg & F_UPDBGLACAPTPCONLY) {
 			sbuf_printf(sb, "\n  %02x   %08x %08x", p[5] & 0xff,
 			    p[6], p[7]);
@@ -6145,6 +6148,69 @@ done:
 }
 
 static int
+sysctl_cim_la_t6(SYSCTL_HANDLER_ARGS)
+{
+	struct adapter *sc = arg1;
+	u_int cfg;
+	struct sbuf *sb;
+	uint32_t *buf, *p;
+	int rc;
+
+	MPASS(chip_id(sc) > CHELSIO_T5);
+
+	rc = -t4_cim_read(sc, A_UP_UP_DBG_LA_CFG, 1, &cfg);
+	if (rc != 0)
+		return (rc);
+
+	rc = sysctl_wire_old_buffer(req, 0);
+	if (rc != 0)
+		return (rc);
+
+	sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
+	if (sb == NULL)
+		return (ENOMEM);
+
+	buf = malloc(sc->params.cim_la_size * sizeof(uint32_t), M_CXGBE,
+	    M_ZERO | M_WAITOK);
+
+	rc = -t4_cim_read_la(sc, buf, NULL);
+	if (rc != 0)
+		goto done;
+
+	sbuf_printf(sb, "Status   Inst    Data      PC%s",
+	    cfg & F_UPDBGLACAPTPCONLY ? "" :
+	    "     LS0Stat  LS0Addr  LS0Data  LS1Stat  LS1Addr  LS1Data");
+
+	for (p = buf; p <= &buf[sc->params.cim_la_size - 10]; p += 10) {
+		if (cfg & F_UPDBGLACAPTPCONLY) {
+			sbuf_printf(sb, "\n  %02x   %08x %08x %08x",
+			    p[3] & 0xff, p[2], p[1], p[0]);
+			sbuf_printf(sb, "\n  %02x   %02x%06x %02x%06x %02x%06x",
+			    (p[6] >> 8) & 0xff, p[6] & 0xff, p[5] >> 8,
+			    p[5] & 0xff, p[4] >> 8, p[4] & 0xff, p[3] >> 8);
+			sbuf_printf(sb, "\n  %02x   %04x%04x %04x%04x %04x%04x",
+			    (p[9] >> 16) & 0xff, p[9] & 0xffff, p[8] >> 16,
+			    p[8] & 0xffff, p[7] >> 16, p[7] & 0xffff,
+			    p[6] >> 16);
+		} else {
+			sbuf_printf(sb, "\n  %02x   %04x%04x %04x%04x %04x%04x "
+			    "%08x %08x %08x %08x %08x %08x",
+			    (p[9] >> 16) & 0xff,
+			    p[9] & 0xffff, p[8] >> 16,
+			    p[8] & 0xffff, p[7] >> 16,
+			    p[7] & 0xffff, p[6] >> 16,
+			    p[2], p[1], p[0], p[5], p[4], p[3]);
+		}
+	}
+
+	rc = sbuf_finish(sb);
+	sbuf_delete(sb);
+done:
+	free(buf, M_CXGBE);
+	return (rc);
+}
+
+static int
 sysctl_cim_ma_la(SYSCTL_HANDLER_ARGS)
 {
 	struct adapter *sc = arg1;
@@ -6212,14 +6278,14 @@ sysctl_cim_pif_la(SYSCTL_HANDLER_ARGS)
 	p = buf;
 
 	sbuf_printf(sb, "Cntl ID DataBE   Addr                 Data");
-	for (i = 0; i < CIM_MALA_SIZE; i++, p += 6) {
+	for (i = 0; i < CIM_PIFLA_SIZE; i++, p += 6) {
 		sbuf_printf(sb, "\n %02x  %02x  %04x  %08x %08x%08x%08x%08x",
 		    (p[5] >> 22) & 0xff, (p[5] >> 16) & 0x3f, p[5] & 0xffff,
 		    p[4], p[3], p[2], p[1], p[0]);
 	}
 
 	sbuf_printf(sb, "\n\nCntl ID               Data");
-	for (i = 0; i < CIM_MALA_SIZE; i++, p += 6) {
+	for (i = 0; i < CIM_PIFLA_SIZE; i++, p += 6) {
 		sbuf_printf(sb, "\n %02x  %02x %08x%08x%08x%08x",
 		    (p[4] >> 6) & 0xff, p[4] & 0x3f, p[3], p[2], p[1], p[0]);
 	}
@@ -6243,12 +6309,11 @@ sysctl_cim_qcfg(SYSCTL_HANDLER_ARGS)
 	uint32_t stat[4 * (CIM_NUM_IBQ + CIM_NUM_OBQ_T5)], *p = stat;
 	u_int cim_num_obq, ibq_rdaddr, obq_rdaddr, nq;
 
+	cim_num_obq = sc->chip_params->cim_num_obq;
 	if (is_t4(sc)) {
-		cim_num_obq = CIM_NUM_OBQ;
 		ibq_rdaddr = A_UP_IBQ_0_RDADDR;
 		obq_rdaddr = A_UP_OBQ_0_REALADDR;
 	} else {
-		cim_num_obq = CIM_NUM_OBQ_T5;
 		ibq_rdaddr = A_UP_IBQ_0_SHADOW_RDADDR;
 		obq_rdaddr = A_UP_OBQ_0_SHADOW_REALADDR;
 	}
@@ -6305,14 +6370,24 @@ sysctl_cpl_stats(SYSCTL_HANDLER_ARGS)
 	if (sb == NULL)
 		return (ENOMEM);
 
+	mtx_lock(&sc->regwin_lock);
 	t4_tp_get_cpl_stats(sc, &stats);
+	mtx_unlock(&sc->regwin_lock);
 
-	sbuf_printf(sb, "                 channel 0  channel 1  channel 2  "
-	    "channel 3\n");
-	sbuf_printf(sb, "CPL requests:   %10u %10u %10u %10u\n",
-		   stats.req[0], stats.req[1], stats.req[2], stats.req[3]);
-	sbuf_printf(sb, "CPL responses:  %10u %10u %10u %10u",
-		   stats.rsp[0], stats.rsp[1], stats.rsp[2], stats.rsp[3]);
+	if (sc->chip_params->nchan > 2) {
+		sbuf_printf(sb, "                 channel 0  channel 1"
+		    "  channel 2  channel 3");
+		sbuf_printf(sb, "\nCPL requests:   %10u %10u %10u %10u",
+		    stats.req[0], stats.req[1], stats.req[2], stats.req[3]);
+		sbuf_printf(sb, "\nCPL responses:   %10u %10u %10u %10u",
+		    stats.rsp[0], stats.rsp[1], stats.rsp[2], stats.rsp[3]);
+	} else {
+		sbuf_printf(sb, "                 channel 0  channel 1");
+		sbuf_printf(sb, "\nCPL requests:   %10u %10u",
+		    stats.req[0], stats.req[1]);
+		sbuf_printf(sb, "\nCPL responses:   %10u %10u",
+		    stats.rsp[0], stats.rsp[1]);
+	}
 
 	rc = sbuf_finish(sb);
 	sbuf_delete(sb);
@@ -6476,7 +6551,8 @@ sysctl_fcoe_stats(SYSCTL_HANDLER_ARGS)
 	struct adapter *sc = arg1;
 	struct sbuf *sb;
 	int rc;
-	struct tp_fcoe_stats stats[4];
+	struct tp_fcoe_stats stats[MAX_NCHAN];
+	int i, nchan = sc->chip_params->nchan;
 
 	rc = sysctl_wire_old_buffer(req, 0);
 	if (rc != 0)
@@ -6486,22 +6562,30 @@ sysctl_fcoe_stats(SYSCTL_HANDLER_ARGS)
 	if (sb == NULL)
 		return (ENOMEM);
 
-	t4_get_fcoe_stats(sc, 0, &stats[0]);
-	t4_get_fcoe_stats(sc, 1, &stats[1]);
-	t4_get_fcoe_stats(sc, 2, &stats[2]);
-	t4_get_fcoe_stats(sc, 3, &stats[3]);
-
-	sbuf_printf(sb, "                   channel 0        channel 1        "
-	    "channel 2        channel 3\n");
-	sbuf_printf(sb, "octetsDDP:  %16ju %16ju %16ju %16ju\n",
-	    stats[0].octets_ddp, stats[1].octets_ddp, stats[2].octets_ddp,
-	    stats[3].octets_ddp);
-	sbuf_printf(sb, "framesDDP:  %16u %16u %16u %16u\n",
-	    stats[0].frames_ddp, stats[1].frames_ddp, stats[2].frames_ddp,
-	    stats[3].frames_ddp);
-	sbuf_printf(sb, "framesDrop: %16u %16u %16u %16u",
-	    stats[0].frames_drop, stats[1].frames_drop, stats[2].frames_drop,
-	    stats[3].frames_drop);
+	for (i = 0; i < nchan; i++)
+		t4_get_fcoe_stats(sc, i, &stats[i]);
+
+	if (nchan > 2) {
+		sbuf_printf(sb, "                   channel 0        channel 1"
+		    "        channel 2        channel 3");
+		sbuf_printf(sb, "\noctetsDDP:  %16ju %16ju %16ju %16ju",
+		    stats[0].octets_ddp, stats[1].octets_ddp,
+		    stats[2].octets_ddp, stats[3].octets_ddp);
+		sbuf_printf(sb, "\nframesDDP:  %16u %16u %16u %16u",
+		    stats[0].frames_ddp, stats[1].frames_ddp,
+		    stats[2].frames_ddp, stats[3].frames_ddp);
+		sbuf_printf(sb, "\nframesDrop: %16u %16u %16u %16u",
+		    stats[0].frames_drop, stats[1].frames_drop,
+		    stats[2].frames_drop, stats[3].frames_drop);
+	} else {
+		sbuf_printf(sb, "                   channel 0        channel 1");
+		sbuf_printf(sb, "\noctetsDDP:  %16ju %16ju",
+		    stats[0].octets_ddp, stats[1].octets_ddp);
+		sbuf_printf(sb, "\nframesDDP:  %16u %16u",
+		    stats[0].frames_ddp, stats[1].frames_ddp);
+		sbuf_printf(sb, "\nframesDrop: %16u %16u",
+		    stats[0].frames_drop, stats[1].frames_drop);
+	}
 
 	rc = sbuf_finish(sb);
 	sbuf_delete(sb);
@@ -6587,7 +6671,7 @@ sysctl_lb_stats(SYSCTL_HANDLER_ARGS)
 
 	memset(s, 0, sizeof(s));
 
-	for (i = 0; i < 4; i += 2) {
+	for (i = 0; i < sc->chip_params->nchan; i += 2) {
 		t4_get_lb_stats(sc, i, &s[0]);
 		t4_get_lb_stats(sc, i + 1, &s[1]);
 
@@ -6721,10 +6805,10 @@ sysctl_meminfo(SYSCTL_HANDLER_ARGS)
 		avail[i].base = G_EXT_MEM_BASE(hi) << 20;
 		avail[i].limit = avail[i].base +
 		    (G_EXT_MEM_SIZE(hi) << 20);
-		avail[i].idx = is_t4(sc) ? 2 : 3;	/* Call it MC for T4 */
+		avail[i].idx = is_t5(sc) ? 3 : 2;	/* Call it MC0 for T5 */
 		i++;
 	}
-	if (!is_t4(sc) && lo & F_EXT_MEM1_ENABLE) {
+	if (is_t5(sc) && lo & F_EXT_MEM1_ENABLE) {
 		hi = t4_read_reg(sc, A_MA_EXT_MEMORY1_BAR);
 		avail[i].base = G_EXT_MEM1_BASE(hi) << 20;
 		avail[i].limit = avail[i].base +
@@ -6760,9 +6844,14 @@ sysctl_meminfo(SYSCTL_HANDLER_ARGS)
 	md++;
 
 	if (t4_read_reg(sc, A_LE_DB_CONFIG) & F_HASHEN) {
-		hi = t4_read_reg(sc, A_LE_DB_TID_HASHBASE) / 4;
-		md->base = t4_read_reg(sc, A_LE_DB_HASH_TID_BASE);
-		md->limit = (sc->tids.ntids - hi) * 16 + md->base - 1;
+		if (chip_id(sc) <= CHELSIO_T5) {
+			hi = t4_read_reg(sc, A_LE_DB_TID_HASHBASE) / 4;
+			md->base = t4_read_reg(sc, A_LE_DB_HASH_TID_BASE);
+		} else {
+			hi = t4_read_reg(sc, A_LE_DB_HASH_TID_BASE);
+			md->base = t4_read_reg(sc, A_LE_DB_HASH_TBL_BASE_ADDR);
+		}
+		md->limit = 0;
 	} else {
 		md->base = 0;
 		md->idx = nitems(region);  /* hide it */
@@ -6785,18 +6874,30 @@ sysctl_meminfo(SYSCTL_HANDLER_ARGS)
 
 	md->base = 0;
 	md->idx = nitems(region);
-	if (!is_t4(sc) && t4_read_reg(sc, A_SGE_CONTROL2) & F_VFIFO_ENABLE) {
-		md->base = G_BASEADDR(t4_read_reg(sc, A_SGE_DBVFIFO_BADDR));
-		md->limit = md->base + (G_DBVFIFO_SIZE((t4_read_reg(sc,
-		    A_SGE_DBVFIFO_SIZE))) << 2) - 1;
+	if (!is_t4(sc)) {
+		uint32_t size = 0;
+		uint32_t sge_ctrl = t4_read_reg(sc, A_SGE_CONTROL2);
+		uint32_t fifo_size = t4_read_reg(sc, A_SGE_DBVFIFO_SIZE);
+
+		if (is_t5(sc)) {
+			if (sge_ctrl & F_VFIFO_ENABLE)
+				size = G_DBVFIFO_SIZE(fifo_size);
+		} else
+			size = G_T6_DBVFIFO_SIZE(fifo_size);
+
+		if (size) {
+			md->base = G_BASEADDR(t4_read_reg(sc,
+			    A_SGE_DBVFIFO_BADDR));
+			md->limit = md->base + (size << 2) - 1;
+		}
 	}
 	md++;
 
 	md->base = t4_read_reg(sc, A_ULP_RX_CTX_BASE);
-	md->limit = md->base + sc->tids.ntids - 1;
+	md->limit = 0;
 	md++;
 	md->base = t4_read_reg(sc, A_ULP_TX_ERR_TABLE_BASE);
-	md->limit = md->base + sc->tids.ntids - 1;
+	md->limit = 0;
 	md++;
 
 	md->base = sc->vres.ocq.start;
@@ -6855,29 +6956,37 @@ sysctl_meminfo(SYSCTL_HANDLER_ARGS)
 		   t4_read_reg(sc, A_TP_CMM_MM_MAX_PSTRUCT));
 
 	for (i = 0; i < 4; i++) {
-		lo = t4_read_reg(sc, A_MPS_RX_PG_RSV0 + i * 4);
-		if (is_t4(sc)) {
-			used = G_USED(lo);
-			alloc = G_ALLOC(lo);
-		} else {
+		if (chip_id(sc) > CHELSIO_T5)
+			lo = t4_read_reg(sc, A_MPS_RX_MAC_BG_PG_CNT0 + i * 4);
+		else
+			lo = t4_read_reg(sc, A_MPS_RX_PG_RSV0 + i * 4);
+		if (is_t5(sc)) {
 			used = G_T5_USED(lo);
 			alloc = G_T5_ALLOC(lo);
+		} else {
+			used = G_USED(lo);
+			alloc = G_ALLOC(lo);
 		}
+		/* For T6 these are MAC buffer groups */
 		sbuf_printf(sb, "\nPort %d using %u pages out of %u allocated",
-			   i, used, alloc);
+		    i, used, alloc);
 	}
-	for (i = 0; i < 4; i++) {
-		lo = t4_read_reg(sc, A_MPS_RX_PG_RSV4 + i * 4);
-		if (is_t4(sc)) {
-			used = G_USED(lo);
-			alloc = G_ALLOC(lo);
-		} else {
+	for (i = 0; i < sc->chip_params->nchan; i++) {
+		if (chip_id(sc) > CHELSIO_T5)
+			lo = t4_read_reg(sc, A_MPS_RX_LPBK_BG_PG_CNT0 + i * 4);
+		else
+			lo = t4_read_reg(sc, A_MPS_RX_PG_RSV4 + i * 4);
+		if (is_t5(sc)) {
 			used = G_T5_USED(lo);
 			alloc = G_T5_ALLOC(lo);
+		} else {
+			used = G_USED(lo);
+			alloc = G_ALLOC(lo);
 		}
+		/* For T6 these are MAC buffer groups */
 		sbuf_printf(sb,
-			   "\nLoopback %d using %u pages out of %u allocated",
-			   i, used, alloc);
+		    "\nLoopback %d using %u pages out of %u allocated",
+		    i, used, alloc);
 	}
 
 	rc = sbuf_finish(sb);
@@ -6899,7 +7008,9 @@ sysctl_mps_tcam(SYSCTL_HANDLER_ARGS)
 {
 	struct adapter *sc = arg1;
 	struct sbuf *sb;
-	int rc, i, n;
+	int rc, i;
+
+	MPASS(chip_id(sc) <= CHELSIO_T5);
 
 	rc = sysctl_wire_old_buffer(req, 0);
 	if (rc != 0)
@@ -6912,22 +7023,18 @@ sysctl_mps_tcam(SYSCTL_HANDLER_ARGS)
 	sbuf_printf(sb,
 	    "Idx  Ethernet address     Mask     Vld Ports PF"
 	    "  VF              Replication             P0 P1 P2 P3  ML");
-	n = is_t4(sc) ? NUM_MPS_CLS_SRAM_L_INSTANCES :
-	    NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
-	for (i = 0; i < n; i++) {
+	for (i = 0; i < sc->chip_params->mps_tcam_size; i++) {
 		uint64_t tcamx, tcamy, mask;
 		uint32_t cls_lo, cls_hi;
 		uint8_t addr[ETHER_ADDR_LEN];
 
 		tcamy = t4_read_reg64(sc, MPS_CLS_TCAM_Y_L(i));
 		tcamx = t4_read_reg64(sc, MPS_CLS_TCAM_X_L(i));
-		cls_lo = t4_read_reg(sc, MPS_CLS_SRAM_L(i));
-		cls_hi = t4_read_reg(sc, MPS_CLS_SRAM_H(i));
-
 		if (tcamx & tcamy)
 			continue;
-
 		tcamxy2valmask(tcamx, tcamy, addr, &mask);
+		cls_lo = t4_read_reg(sc, MPS_CLS_SRAM_L(i));
+		cls_hi = t4_read_reg(sc, MPS_CLS_SRAM_H(i));
 		sbuf_printf(sb, "\n%3u %02x:%02x:%02x:%02x:%02x:%02x %012jx"
 			   "  %c   %#x%4u%4d", i, addr[0], addr[1], addr[2],
 			   addr[3], addr[4], addr[5], (uintmax_t)mask,
@@ -6957,8 +7064,7 @@ sysctl_mps_tcam(SYSCTL_HANDLER_ARGS)
 			end_synchronized_op(sc, 0);
 
 			if (rc != 0) {
-				sbuf_printf(sb,
-				    " ------------ error %3u ------------", rc);
+				sbuf_printf(sb, "%36d", rc);
 				rc = 0;
 			} else {
 				sbuf_printf(sb, " %08x %08x %08x %08x",
@@ -6985,6 +7091,162 @@ sysctl_mps_tcam(SYSCTL_HANDLER_ARGS)
 }
 
 static int
+sysctl_mps_tcam_t6(SYSCTL_HANDLER_ARGS)
+{
+	struct adapter *sc = arg1;
+	struct sbuf *sb;
+	int rc, i;
+
+	MPASS(chip_id(sc) > CHELSIO_T5);
+
+	rc = sysctl_wire_old_buffer(req, 0);
+	if (rc != 0)
+		return (rc);
+
+	sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
+	if (sb == NULL)
+		return (ENOMEM);
+
+	sbuf_printf(sb, "Idx  Ethernet address     Mask       VNI   Mask"
+	    "   IVLAN Vld DIP_Hit   Lookup  Port Vld Ports PF  VF"
+	    "                           Replication"
+	    "                                    P0 P1 P2 P3  ML\n");
+
+	for (i = 0; i < sc->chip_params->mps_tcam_size; i++) {
+		uint8_t dip_hit, vlan_vld, lookup_type, port_num;
+		uint16_t ivlan;
+		uint64_t tcamx, tcamy, val, mask;
+		uint32_t cls_lo, cls_hi, ctl, data2, vnix, vniy;
+		uint8_t addr[ETHER_ADDR_LEN];
+
+		ctl = V_CTLREQID(1) | V_CTLCMDTYPE(0) | V_CTLXYBITSEL(0);
+		if (i < 256)
+			ctl |= V_CTLTCAMINDEX(i) | V_CTLTCAMSEL(0);
+		else
+			ctl |= V_CTLTCAMINDEX(i - 256) | V_CTLTCAMSEL(1);
+		t4_write_reg(sc, A_MPS_CLS_TCAM_DATA2_CTL, ctl);
+		val = t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA1_REQ_ID1);
+		tcamy = G_DMACH(val) << 32;
+		tcamy |= t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA0_REQ_ID1);
+		data2 = t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA2_REQ_ID1);
+		lookup_type = G_DATALKPTYPE(data2);
+		port_num = G_DATAPORTNUM(data2);
+		if (lookup_type && lookup_type != M_DATALKPTYPE) {
+			/* Inner header VNI */
+			vniy = ((data2 & F_DATAVIDH2) << 23) |
+				       (G_DATAVIDH1(data2) << 16) | G_VIDL(val);
+			dip_hit = data2 & F_DATADIPHIT;
+			vlan_vld = 0;
+		} else {
+			vniy = 0;
+			dip_hit = 0;
+			vlan_vld = data2 & F_DATAVIDH2;
+			ivlan = G_VIDL(val);
+		}
+
+		ctl |= V_CTLXYBITSEL(1);
+		t4_write_reg(sc, A_MPS_CLS_TCAM_DATA2_CTL, ctl);
+		val = t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA1_REQ_ID1);
+		tcamx = G_DMACH(val) << 32;
+		tcamx |= t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA0_REQ_ID1);
+		data2 = t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA2_REQ_ID1);
+		if (lookup_type && lookup_type != M_DATALKPTYPE) {
+			/* Inner header VNI mask */
+			vnix = ((data2 & F_DATAVIDH2) << 23) |
+			       (G_DATAVIDH1(data2) << 16) | G_VIDL(val);
+		} else
+			vnix = 0;
+
+		if (tcamx & tcamy)
+			continue;
+		tcamxy2valmask(tcamx, tcamy, addr, &mask);
+
+		cls_lo = t4_read_reg(sc, MPS_CLS_SRAM_L(i));
+		cls_hi = t4_read_reg(sc, MPS_CLS_SRAM_H(i));
+
+		if (lookup_type && lookup_type != M_DATALKPTYPE) {
+			sbuf_printf(sb, "\n%3u %02x:%02x:%02x:%02x:%02x:%02x "
+			    "%012jx %06x %06x    -    -   %3c"
+			    "      'I'  %4x   %3c   %#x%4u%4d", i, addr[0],
+			    addr[1], addr[2], addr[3], addr[4], addr[5],
+			    (uintmax_t)mask, vniy, vnix, dip_hit ? 'Y' : 'N',
+			    port_num, cls_lo & F_T6_SRAM_VLD ? 'Y' : 'N',
+			    G_PORTMAP(cls_hi), G_T6_PF(cls_lo),
+			    cls_lo & F_T6_VF_VALID ? G_T6_VF(cls_lo) : -1);
+		} else {
+			sbuf_printf(sb, "\n%3u %02x:%02x:%02x:%02x:%02x:%02x "
+			    "%012jx    -       -   ", i, addr[0], addr[1],
+			    addr[2], addr[3], addr[4], addr[5],
+			    (uintmax_t)mask);
+
+			if (vlan_vld)
+				sbuf_printf(sb, "%4u   Y     ", ivlan);
+			else
+				sbuf_printf(sb, "  -    N     ");
+
+			sbuf_printf(sb, "-      %3c  %4x   %3c   %#x%4u%4d",
+			    lookup_type ? 'I' : 'O', port_num,
+			    cls_lo & F_T6_SRAM_VLD ? 'Y' : 'N',
+			    G_PORTMAP(cls_hi), G_T6_PF(cls_lo),
+			    cls_lo & F_T6_VF_VALID ? G_T6_VF(cls_lo) : -1);
+		}
+
+
+		if (cls_lo & F_T6_REPLICATE) {
+			struct fw_ldst_cmd ldst_cmd;
+
+			memset(&ldst_cmd, 0, sizeof(ldst_cmd));
+			ldst_cmd.op_to_addrspace =
+			    htobe32(V_FW_CMD_OP(FW_LDST_CMD) |
+				F_FW_CMD_REQUEST | F_FW_CMD_READ |
+				V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MPS));
+			ldst_cmd.cycles_to_len16 = htobe32(FW_LEN16(ldst_cmd));
+			ldst_cmd.u.mps.rplc.fid_idx =
+			    htobe16(V_FW_LDST_CMD_FID(FW_LDST_MPS_RPLC) |
+				V_FW_LDST_CMD_IDX(i));
+
+			rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK,
+			    "t6mps");
+			if (rc)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201603041311.u24DBEog076885>