cxgbe(4): Add support for Chelsio's Terminator 5 (aka T5) ASIC. This
includes support for the NIC and TOE features of the 40G, 10G, and 1G/100M cards based on the T5. The ASIC is mostly backward compatible with the Terminator 4 so cxgbe(4) has been updated instead of writing a brand new driver. T5 cards will show up as cxl (short for cxlgb) ports attached to the t5nex bus driver. Sponsored by: Chelsio
This commit is contained in:
parent
fc36a232b9
commit
3c60e22da7
@ -50,9 +50,6 @@
|
||||
#include "offload.h"
|
||||
#include "firmware/t4fw_interface.h"
|
||||
|
||||
#define T4_CFGNAME "t4fw_cfg"
|
||||
#define T4_FWNAME "t4fw"
|
||||
|
||||
MALLOC_DECLARE(M_CXGBE);
|
||||
#define CXGBE_UNIMPLEMENTED(s) \
|
||||
panic("%s (%s, line %d) not implemented yet.", s, __FILE__, __LINE__)
|
||||
@ -144,12 +141,6 @@ enum {
|
||||
TX_WR_FLITS = SGE_MAX_WR_LEN / 8
|
||||
};
|
||||
|
||||
#ifdef T4_PKT_TIMESTAMP
|
||||
#define RX_COPY_THRESHOLD (MINCLSIZE - 8)
|
||||
#else
|
||||
#define RX_COPY_THRESHOLD MINCLSIZE
|
||||
#endif
|
||||
|
||||
enum {
|
||||
/* adapter intr_type */
|
||||
INTR_INTX = (1 << 0),
|
||||
@ -327,6 +318,9 @@ enum {
|
||||
EQ_STALLED = (1 << 6), /* out of hw descriptors or dmamaps */
|
||||
};
|
||||
|
||||
/* Listed in order of preference. Update t4_sysctls too if you change these */
|
||||
enum {DOORBELL_UDB, DOORBELL_WRWC, DOORBELL_UDBWC, DOORBELL_KDB};
|
||||
|
||||
/*
|
||||
* Egress Queue: driver is producer, T4 is consumer.
|
||||
*
|
||||
@ -344,6 +338,9 @@ struct sge_eq {
|
||||
struct tx_desc *desc; /* KVA of descriptor ring */
|
||||
bus_addr_t ba; /* bus address of descriptor ring */
|
||||
struct sge_qstat *spg; /* status page, for convenience */
|
||||
int doorbells;
|
||||
volatile uint32_t *udb; /* KVA of doorbell (lies within BAR2) */
|
||||
u_int udb_qid; /* relative qid within the doorbell page */
|
||||
uint16_t cap; /* max # of desc, for convenience */
|
||||
uint16_t avail; /* available descriptors, for convenience */
|
||||
uint16_t qsize; /* size (# of entries) of the queue */
|
||||
@ -496,6 +493,7 @@ struct sge {
|
||||
int timer_val[SGE_NTIMERS];
|
||||
int counter_val[SGE_NCOUNTERS];
|
||||
int fl_starve_threshold;
|
||||
int s_qpp;
|
||||
|
||||
int nrxq; /* total # of Ethernet rx queues */
|
||||
int ntxq; /* total # of Ethernet tx tx queues */
|
||||
@ -541,6 +539,9 @@ struct adapter {
|
||||
bus_space_handle_t bh;
|
||||
bus_space_tag_t bt;
|
||||
bus_size_t mmio_len;
|
||||
int udbs_rid;
|
||||
struct resource *udbs_res;
|
||||
volatile uint8_t *udbs_base;
|
||||
|
||||
unsigned int pf;
|
||||
unsigned int mbox;
|
||||
@ -570,6 +571,7 @@ struct adapter {
|
||||
struct l2t_data *l2t; /* L2 table */
|
||||
struct tid_info tids;
|
||||
|
||||
int doorbells;
|
||||
int open_device_map;
|
||||
#ifdef TCP_OFFLOAD
|
||||
int offload_map;
|
||||
@ -748,13 +750,15 @@ t4_os_set_hw_addr(struct adapter *sc, int idx, uint8_t hw_addr[])
|
||||
bcopy(hw_addr, sc->port[idx]->hw_addr, ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
static inline bool is_10G_port(const struct port_info *pi)
|
||||
static inline bool
|
||||
is_10G_port(const struct port_info *pi)
|
||||
{
|
||||
|
||||
return ((pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G) != 0);
|
||||
}
|
||||
|
||||
static inline int tx_resume_threshold(struct sge_eq *eq)
|
||||
static inline int
|
||||
tx_resume_threshold(struct sge_eq *eq)
|
||||
{
|
||||
|
||||
return (eq->qsize / 4);
|
||||
@ -778,7 +782,9 @@ void end_synchronized_op(struct adapter *, int);
|
||||
|
||||
/* t4_sge.c */
|
||||
void t4_sge_modload(void);
|
||||
int t4_sge_init(struct adapter *);
|
||||
void t4_init_sge_cpl_handlers(struct adapter *);
|
||||
void t4_tweak_chip_settings(struct adapter *);
|
||||
int t4_read_chip_settings(struct adapter *);
|
||||
int t4_create_dma_tag(struct adapter *);
|
||||
int t4_destroy_dma_tag(struct adapter *);
|
||||
int t4_setup_adapter_queues(struct adapter *);
|
||||
|
@ -42,15 +42,19 @@ enum {
|
||||
MACADDR_LEN = 12, /* MAC Address length */
|
||||
};
|
||||
|
||||
enum { MEM_EDC0, MEM_EDC1, MEM_MC };
|
||||
enum { MEM_EDC0, MEM_EDC1, MEM_MC, MEM_MC0 = MEM_MC, MEM_MC1 };
|
||||
|
||||
enum {
|
||||
MEMWIN0_APERTURE = 2048,
|
||||
MEMWIN0_BASE = 0x1b800,
|
||||
MEMWIN1_APERTURE = 32768,
|
||||
MEMWIN1_BASE = 0x28000,
|
||||
MEMWIN2_APERTURE = 65536,
|
||||
MEMWIN2_BASE = 0x30000,
|
||||
|
||||
MEMWIN2_APERTURE_T4 = 65536,
|
||||
MEMWIN2_BASE_T4 = 0x30000,
|
||||
|
||||
MEMWIN2_APERTURE_T5 = 128 * 1024,
|
||||
MEMWIN2_BASE_T5 = 0x60000,
|
||||
};
|
||||
|
||||
enum dev_master { MASTER_CANT, MASTER_MAY, MASTER_MUST };
|
||||
@ -63,15 +67,20 @@ enum {
|
||||
PAUSE_AUTONEG = 1 << 2
|
||||
};
|
||||
|
||||
#define FW_VERSION_MAJOR 1
|
||||
#define FW_VERSION_MINOR 8
|
||||
#define FW_VERSION_MICRO 4
|
||||
#define FW_VERSION_BUILD 0
|
||||
#define FW_VERSION_MAJOR_T4 1
|
||||
#define FW_VERSION_MINOR_T4 8
|
||||
#define FW_VERSION_MICRO_T4 4
|
||||
#define FW_VERSION_BUILD_T4 0
|
||||
|
||||
#define FW_VERSION (V_FW_HDR_FW_VER_MAJOR(FW_VERSION_MAJOR) | \
|
||||
V_FW_HDR_FW_VER_MINOR(FW_VERSION_MINOR) | \
|
||||
V_FW_HDR_FW_VER_MICRO(FW_VERSION_MICRO) | \
|
||||
V_FW_HDR_FW_VER_BUILD(FW_VERSION_BUILD))
|
||||
#define FW_VERSION_MAJOR_T5 0
|
||||
#define FW_VERSION_MINOR_T5 5
|
||||
#define FW_VERSION_MICRO_T5 18
|
||||
#define FW_VERSION_BUILD_T5 0
|
||||
|
||||
struct memwin {
|
||||
uint32_t base;
|
||||
uint32_t aperture;
|
||||
};
|
||||
|
||||
struct port_stats {
|
||||
u64 tx_octets; /* total # of octets in good frames */
|
||||
@ -267,18 +276,20 @@ struct adapter_params {
|
||||
|
||||
unsigned int cim_la_size;
|
||||
|
||||
/* Used as int in sysctls, do not reduce size */
|
||||
unsigned int nports; /* # of ethernet ports */
|
||||
unsigned int portvec;
|
||||
unsigned int rev; /* chip revision */
|
||||
unsigned int offload;
|
||||
uint8_t nports; /* # of ethernet ports */
|
||||
uint8_t portvec;
|
||||
unsigned int chipid:4; /* chip ID. T4 = 4, T5 = 5, ... */
|
||||
unsigned int rev:4; /* chip revision */
|
||||
unsigned int fpga:1; /* this is an FPGA */
|
||||
unsigned int offload:1; /* hw is TOE capable, fw has divvied up card
|
||||
resources for TOE operation. */
|
||||
unsigned int bypass:1; /* this is a bypass card */
|
||||
|
||||
unsigned int ofldq_wr_cred;
|
||||
};
|
||||
|
||||
enum { /* chip revisions */
|
||||
T4_REV_A = 0,
|
||||
};
|
||||
#define CHELSIO_T4 0x4
|
||||
#define CHELSIO_T5 0x5
|
||||
|
||||
struct trace_params {
|
||||
u32 data[TRACE_LEN / 4];
|
||||
@ -316,6 +327,31 @@ static inline int is_offload(const struct adapter *adap)
|
||||
return adap->params.offload;
|
||||
}
|
||||
|
||||
static inline int chip_id(struct adapter *adap)
|
||||
{
|
||||
return adap->params.chipid;
|
||||
}
|
||||
|
||||
static inline int chip_rev(struct adapter *adap)
|
||||
{
|
||||
return adap->params.rev;
|
||||
}
|
||||
|
||||
static inline int is_t4(struct adapter *adap)
|
||||
{
|
||||
return adap->params.chipid == CHELSIO_T4;
|
||||
}
|
||||
|
||||
static inline int is_t5(struct adapter *adap)
|
||||
{
|
||||
return adap->params.chipid == CHELSIO_T5;
|
||||
}
|
||||
|
||||
static inline int is_fpga(struct adapter *adap)
|
||||
{
|
||||
return adap->params.fpga;
|
||||
}
|
||||
|
||||
static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
|
||||
{
|
||||
return adap->params.vpd.cclk / 1000;
|
||||
@ -437,7 +473,8 @@ int t4_cim_read_la(struct adapter *adap, u32 *la_buf, unsigned int *wrptr);
|
||||
void t4_cim_read_pif_la(struct adapter *adap, u32 *pif_req, u32 *pif_rsp,
|
||||
unsigned int *pif_req_wrptr, unsigned int *pif_rsp_wrptr);
|
||||
void t4_cim_read_ma_la(struct adapter *adap, u32 *ma_req, u32 *ma_rsp);
|
||||
int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *parity);
|
||||
int t4_mc_read(struct adapter *adap, int idx, u32 addr,
|
||||
__be32 *data, u64 *parity);
|
||||
int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *parity);
|
||||
int t4_mem_read(struct adapter *adap, int mtype, u32 addr, u32 size,
|
||||
__be32 *data);
|
||||
|
@ -312,6 +312,7 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
|
||||
/**
|
||||
* t4_mc_read - read from MC through backdoor accesses
|
||||
* @adap: the adapter
|
||||
* @idx: which MC to access
|
||||
* @addr: address of first byte requested
|
||||
* @data: 64 bytes of data containing the requested address
|
||||
* @ecc: where to store the corresponding 64-bit ECC word
|
||||
@ -320,22 +321,40 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
|
||||
* that covers the requested address @addr. If @parity is not %NULL it
|
||||
* is assigned the 64-bit ECC word for the read data.
|
||||
*/
|
||||
int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *ecc)
|
||||
int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
|
||||
{
|
||||
int i;
|
||||
u32 mc_bist_cmd_reg, mc_bist_cmd_addr_reg, mc_bist_cmd_len_reg;
|
||||
u32 mc_bist_status_rdata_reg, mc_bist_data_pattern_reg;
|
||||
|
||||
if (t4_read_reg(adap, A_MC_BIST_CMD) & F_START_BIST)
|
||||
if (is_t4(adap)) {
|
||||
mc_bist_cmd_reg = A_MC_BIST_CMD;
|
||||
mc_bist_cmd_addr_reg = A_MC_BIST_CMD_ADDR;
|
||||
mc_bist_cmd_len_reg = A_MC_BIST_CMD_LEN;
|
||||
mc_bist_status_rdata_reg = A_MC_BIST_STATUS_RDATA;
|
||||
mc_bist_data_pattern_reg = A_MC_BIST_DATA_PATTERN;
|
||||
} else {
|
||||
mc_bist_cmd_reg = MC_REG(A_MC_P_BIST_CMD, idx);
|
||||
mc_bist_cmd_addr_reg = MC_REG(A_MC_P_BIST_CMD_ADDR, idx);
|
||||
mc_bist_cmd_len_reg = MC_REG(A_MC_P_BIST_CMD_LEN, idx);
|
||||
mc_bist_status_rdata_reg = MC_REG(A_MC_P_BIST_STATUS_RDATA,
|
||||
idx);
|
||||
mc_bist_data_pattern_reg = MC_REG(A_MC_P_BIST_DATA_PATTERN,
|
||||
idx);
|
||||
}
|
||||
|
||||
if (t4_read_reg(adap, mc_bist_cmd_reg) & F_START_BIST)
|
||||
return -EBUSY;
|
||||
t4_write_reg(adap, A_MC_BIST_CMD_ADDR, addr & ~0x3fU);
|
||||
t4_write_reg(adap, A_MC_BIST_CMD_LEN, 64);
|
||||
t4_write_reg(adap, A_MC_BIST_DATA_PATTERN, 0xc);
|
||||
t4_write_reg(adap, A_MC_BIST_CMD, V_BIST_OPCODE(1) | F_START_BIST |
|
||||
V_BIST_CMD_GAP(1));
|
||||
i = t4_wait_op_done(adap, A_MC_BIST_CMD, F_START_BIST, 0, 10, 1);
|
||||
t4_write_reg(adap, mc_bist_cmd_addr_reg, addr & ~0x3fU);
|
||||
t4_write_reg(adap, mc_bist_cmd_len_reg, 64);
|
||||
t4_write_reg(adap, mc_bist_data_pattern_reg, 0xc);
|
||||
t4_write_reg(adap, mc_bist_cmd_reg, V_BIST_OPCODE(1) |
|
||||
F_START_BIST | V_BIST_CMD_GAP(1));
|
||||
i = t4_wait_op_done(adap, mc_bist_cmd_reg, F_START_BIST, 0, 10, 1);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
#define MC_DATA(i) MC_BIST_STATUS_REG(A_MC_BIST_STATUS_RDATA, i)
|
||||
#define MC_DATA(i) MC_BIST_STATUS_REG(mc_bist_status_rdata_reg, i)
|
||||
|
||||
for (i = 15; i >= 0; i--)
|
||||
*data++ = ntohl(t4_read_reg(adap, MC_DATA(i)));
|
||||
@ -360,20 +379,47 @@ int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *ecc)
|
||||
int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
|
||||
{
|
||||
int i;
|
||||
u32 edc_bist_cmd_reg, edc_bist_cmd_addr_reg, edc_bist_cmd_len_reg;
|
||||
u32 edc_bist_cmd_data_pattern, edc_bist_status_rdata_reg;
|
||||
|
||||
idx *= EDC_STRIDE;
|
||||
if (t4_read_reg(adap, A_EDC_BIST_CMD + idx) & F_START_BIST)
|
||||
if (is_t4(adap)) {
|
||||
edc_bist_cmd_reg = EDC_REG(A_EDC_BIST_CMD, idx);
|
||||
edc_bist_cmd_addr_reg = EDC_REG(A_EDC_BIST_CMD_ADDR, idx);
|
||||
edc_bist_cmd_len_reg = EDC_REG(A_EDC_BIST_CMD_LEN, idx);
|
||||
edc_bist_cmd_data_pattern = EDC_REG(A_EDC_BIST_DATA_PATTERN,
|
||||
idx);
|
||||
edc_bist_status_rdata_reg = EDC_REG(A_EDC_BIST_STATUS_RDATA,
|
||||
idx);
|
||||
} else {
|
||||
/*
|
||||
* These macro are missing in t4_regs.h file.
|
||||
* Added temporarily for testing.
|
||||
*/
|
||||
#define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
|
||||
#define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
|
||||
edc_bist_cmd_reg = EDC_REG_T5(A_EDC_H_BIST_CMD, idx);
|
||||
edc_bist_cmd_addr_reg = EDC_REG_T5(A_EDC_H_BIST_CMD_ADDR, idx);
|
||||
edc_bist_cmd_len_reg = EDC_REG_T5(A_EDC_H_BIST_CMD_LEN, idx);
|
||||
edc_bist_cmd_data_pattern = EDC_REG_T5(A_EDC_H_BIST_DATA_PATTERN,
|
||||
idx);
|
||||
edc_bist_status_rdata_reg = EDC_REG_T5(A_EDC_H_BIST_STATUS_RDATA,
|
||||
idx);
|
||||
#undef EDC_REG_T5
|
||||
#undef EDC_STRIDE_T5
|
||||
}
|
||||
|
||||
if (t4_read_reg(adap, edc_bist_cmd_reg) & F_START_BIST)
|
||||
return -EBUSY;
|
||||
t4_write_reg(adap, A_EDC_BIST_CMD_ADDR + idx, addr & ~0x3fU);
|
||||
t4_write_reg(adap, A_EDC_BIST_CMD_LEN + idx, 64);
|
||||
t4_write_reg(adap, A_EDC_BIST_DATA_PATTERN + idx, 0xc);
|
||||
t4_write_reg(adap, A_EDC_BIST_CMD + idx,
|
||||
t4_write_reg(adap, edc_bist_cmd_addr_reg, addr & ~0x3fU);
|
||||
t4_write_reg(adap, edc_bist_cmd_len_reg, 64);
|
||||
t4_write_reg(adap, edc_bist_cmd_data_pattern, 0xc);
|
||||
t4_write_reg(adap, edc_bist_cmd_reg,
|
||||
V_BIST_OPCODE(1) | V_BIST_CMD_GAP(1) | F_START_BIST);
|
||||
i = t4_wait_op_done(adap, A_EDC_BIST_CMD + idx, F_START_BIST, 0, 10, 1);
|
||||
i = t4_wait_op_done(adap, edc_bist_cmd_reg, F_START_BIST, 0, 10, 1);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
#define EDC_DATA(i) (EDC_BIST_STATUS_REG(A_EDC_BIST_STATUS_RDATA, i) + idx)
|
||||
#define EDC_DATA(i) EDC_BIST_STATUS_REG(edc_bist_status_rdata_reg, i)
|
||||
|
||||
for (i = 15; i >= 0; i--)
|
||||
*data++ = ntohl(t4_read_reg(adap, EDC_DATA(i)));
|
||||
@ -425,8 +471,8 @@ int t4_mem_read(struct adapter *adap, int mtype, u32 addr, u32 len,
|
||||
/*
|
||||
* Read the chip's memory block and bail if there's an error.
|
||||
*/
|
||||
if (mtype == MEM_MC)
|
||||
ret = t4_mc_read(adap, pos, data, NULL);
|
||||
if ((mtype == MEM_MC) || (mtype == MEM_MC1))
|
||||
ret = t4_mc_read(adap, mtype - MEM_MC, pos, data, NULL);
|
||||
else
|
||||
ret = t4_edc_read(adap, mtype, pos, data, NULL);
|
||||
if (ret)
|
||||
@ -464,7 +510,7 @@ struct t4_vpd_hdr {
|
||||
#define EEPROM_STAT_ADDR 0x7bfc
|
||||
#define VPD_BASE 0x400
|
||||
#define VPD_BASE_OLD 0
|
||||
#define VPD_LEN 512
|
||||
#define VPD_LEN 1024
|
||||
#define VPD_INFO_FLD_HDR_SIZE 3
|
||||
|
||||
/**
|
||||
@ -914,6 +960,7 @@ int t4_get_tp_version(struct adapter *adapter, u32 *vers)
|
||||
int t4_check_fw_version(struct adapter *adapter)
|
||||
{
|
||||
int ret, major, minor, micro;
|
||||
int exp_major, exp_minor, exp_micro;
|
||||
|
||||
ret = t4_get_fw_version(adapter, &adapter->params.fw_vers);
|
||||
if (!ret)
|
||||
@ -925,13 +972,30 @@ int t4_check_fw_version(struct adapter *adapter)
|
||||
minor = G_FW_HDR_FW_VER_MINOR(adapter->params.fw_vers);
|
||||
micro = G_FW_HDR_FW_VER_MICRO(adapter->params.fw_vers);
|
||||
|
||||
if (major != FW_VERSION_MAJOR) { /* major mismatch - fail */
|
||||
CH_ERR(adapter, "card FW has major version %u, driver wants "
|
||||
"%u\n", major, FW_VERSION_MAJOR);
|
||||
switch (chip_id(adapter)) {
|
||||
case CHELSIO_T4:
|
||||
exp_major = FW_VERSION_MAJOR_T4;
|
||||
exp_minor = FW_VERSION_MINOR_T4;
|
||||
exp_micro = FW_VERSION_MICRO_T4;
|
||||
break;
|
||||
case CHELSIO_T5:
|
||||
exp_major = FW_VERSION_MAJOR_T5;
|
||||
exp_minor = FW_VERSION_MINOR_T5;
|
||||
exp_micro = FW_VERSION_MICRO_T5;
|
||||
break;
|
||||
default:
|
||||
CH_ERR(adapter, "Unsupported chip type, %x\n",
|
||||
chip_id(adapter));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (minor == FW_VERSION_MINOR && micro == FW_VERSION_MICRO)
|
||||
if (major != exp_major) { /* major mismatch - fail */
|
||||
CH_ERR(adapter, "card FW has major version %u, driver wants "
|
||||
"%u\n", major, exp_major);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (minor == exp_minor && micro == exp_micro)
|
||||
return 0; /* perfect match */
|
||||
|
||||
/* Minor/micro version mismatch. Report it but often it's OK. */
|
||||
@ -1407,6 +1471,7 @@ int t4_load_boot(struct adapter *adap, u8 *boot_data,
|
||||
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 |
|
||||
@ -1416,7 +1481,7 @@ void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres)
|
||||
*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 < 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);
|
||||
@ -1452,8 +1517,12 @@ int t4_read_cim_ibq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
|
||||
for (i = 0; i < n; i++, addr++) {
|
||||
t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, V_IBQDBGADDR(addr) |
|
||||
F_IBQDBGEN);
|
||||
/*
|
||||
* It might take 3-10ms before the IBQ debug read access is
|
||||
* allowed. Wait for 1 Sec with a delay of 1 usec.
|
||||
*/
|
||||
err = t4_wait_op_done(adap, A_CIM_IBQ_DBG_CFG, F_IBQDBGBUSY, 0,
|
||||
2, 1);
|
||||
1000000, 1);
|
||||
if (err)
|
||||
return err;
|
||||
*data++ = t4_read_reg(adap, A_CIM_IBQ_DBG_DATA);
|
||||
@ -1477,8 +1546,9 @@ int t4_read_cim_obq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
|
||||
{
|
||||
int i, err;
|
||||
unsigned int addr, v, nwords;
|
||||
int cim_num_obq = is_t4(adap) ? CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
|
||||
|
||||
if (qid > 5 || (n & 3))
|
||||
if (qid >= cim_num_obq || (n & 3))
|
||||
return -EINVAL;
|
||||
|
||||
t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
|
||||
@ -1933,6 +2003,47 @@ static void pcie_intr_handler(struct adapter *adapter)
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static struct intr_info t5_pcie_intr_info[] = {
|
||||
{ F_MSTGRPPERR, "Master Response Read Queue parity error",
|
||||
-1, 1 },
|
||||
{ F_MSTTIMEOUTPERR, "Master Timeout FIFO parity error", -1, 1 },
|
||||
{ F_MSIXSTIPERR, "MSI-X STI SRAM parity error", -1, 1 },
|
||||
{ F_MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
|
||||
{ F_MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
|
||||
{ F_MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
|
||||
{ F_MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
|
||||
{ F_PIOCPLGRPPERR, "PCI PIO completion Group FIFO parity error",
|
||||
-1, 1 },
|
||||
{ F_PIOREQGRPPERR, "PCI PIO request Group FIFO parity error",
|
||||
-1, 1 },
|
||||
{ F_TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
|
||||
{ F_MSTTAGQPERR, "PCI master tag queue parity error", -1, 1 },
|
||||
{ F_CREQPERR, "PCI CMD channel request parity error", -1, 1 },
|
||||
{ F_CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
|
||||
{ F_DREQWRPERR, "PCI DMA channel write request parity error",
|
||||
-1, 1 },
|
||||
{ F_DREQPERR, "PCI DMA channel request parity error", -1, 1 },
|
||||
{ F_DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
|
||||
{ F_HREQWRPERR, "PCI HMA channel count parity error", -1, 1 },
|
||||
{ F_HREQPERR, "PCI HMA channel request parity error", -1, 1 },
|
||||
{ F_HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
|
||||
{ F_CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
|
||||
{ F_FIDPERR, "PCI FID parity error", -1, 1 },
|
||||
{ F_VFIDPERR, "PCI INTx clear parity error", -1, 1 },
|
||||
{ F_MAGRPPERR, "PCI MA group FIFO parity error", -1, 1 },
|
||||
{ F_PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
|
||||
{ F_IPRXHDRGRPPERR, "PCI IP Rx header group parity error",
|
||||
-1, 1 },
|
||||
{ F_IPRXDATAGRPPERR, "PCI IP Rx data group parity error",
|
||||
-1, 1 },
|
||||
{ F_RPLPERR, "PCI IP replay buffer parity error", -1, 1 },
|
||||
{ F_IPSOTPERR, "PCI IP SOT buffer parity error", -1, 1 },
|
||||
{ F_TRGT1GRPPERR, "PCI TRGT1 group FIFOs parity error", -1, 1 },
|
||||
{ F_READRSPERR, "Outbound read error", -1,
|
||||
0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
int fat;
|
||||
|
||||
fat = t4_handle_intr_status(adapter,
|
||||
@ -1941,7 +2052,9 @@ static void pcie_intr_handler(struct adapter *adapter)
|
||||
t4_handle_intr_status(adapter,
|
||||
A_PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
|
||||
pcie_port_intr_info) +
|
||||
t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE, pcie_intr_info);
|
||||
t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
|
||||
is_t4(adapter) ?
|
||||
pcie_intr_info : t5_pcie_intr_info);
|
||||
if (fat)
|
||||
t4_fatal_err(adapter);
|
||||
}
|
||||
@ -2368,9 +2481,15 @@ static void ncsi_intr_handler(struct adapter *adap)
|
||||
*/
|
||||
static void xgmac_intr_handler(struct adapter *adap, int port)
|
||||
{
|
||||
u32 v = t4_read_reg(adap, PORT_REG(port, A_XGMAC_PORT_INT_CAUSE));
|
||||
u32 v, int_cause_reg;
|
||||
|
||||
v &= F_TXFIFO_PRTY_ERR | F_RXFIFO_PRTY_ERR;
|
||||
if (is_t4(adap))
|
||||
int_cause_reg = PORT_REG(port, A_XGMAC_PORT_INT_CAUSE);
|
||||
else
|
||||
int_cause_reg = T5_PORT_REG(port, A_MAC_PORT_INT_CAUSE);
|
||||
|
||||
v = t4_read_reg(adap, int_cause_reg);
|
||||
v &= (F_TXFIFO_PRTY_ERR | F_RXFIFO_PRTY_ERR);
|
||||
if (!v)
|
||||
return;
|
||||
|
||||
@ -2378,7 +2497,7 @@ static void xgmac_intr_handler(struct adapter *adap, int port)
|
||||
CH_ALERT(adap, "XGMAC %d Tx FIFO parity error\n", port);
|
||||
if (v & F_RXFIFO_PRTY_ERR)
|
||||
CH_ALERT(adap, "XGMAC %d Rx FIFO parity error\n", port);
|
||||
t4_write_reg(adap, PORT_REG(port, A_XGMAC_PORT_INT_CAUSE), v);
|
||||
t4_write_reg(adap, int_cause_reg, v);
|
||||
t4_fatal_err(adap);
|
||||
}
|
||||
|
||||
@ -3531,7 +3650,10 @@ int t4_set_trace_filter(struct adapter *adap, const struct trace_params *tp, int
|
||||
V_TFMINPKTSIZE(tp->min_len));
|
||||
t4_write_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + ofst,
|
||||
V_TFOFFSET(tp->skip_ofst) | V_TFLENGTH(tp->skip_len) |
|
||||
V_TFPORT(tp->port) | F_TFEN | V_TFINVERTMATCH(tp->invert));
|
||||
is_t4(adap) ?
|
||||
V_TFPORT(tp->port) | F_TFEN | V_TFINVERTMATCH(tp->invert) :
|
||||
V_T5_TFPORT(tp->port) | F_T5_TFEN |
|
||||
V_T5_TFINVERTMATCH(tp->invert));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3555,13 +3677,18 @@ void t4_get_trace_filter(struct adapter *adap, struct trace_params *tp, int idx,
|
||||
ctla = t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + ofst);
|
||||
ctlb = t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_B + ofst);
|
||||
|
||||
*enabled = !!(ctla & F_TFEN);
|
||||
if (is_t4(adap)) {
|
||||
*enabled = !!(ctla & F_TFEN);
|
||||
tp->port = G_TFPORT(ctla);
|
||||
} else {
|
||||
*enabled = !!(ctla & F_T5_TFEN);
|
||||
tp->port = G_T5_TFPORT(ctla);
|
||||
}
|
||||
tp->snap_len = G_TFCAPTUREMAX(ctlb);
|
||||
tp->min_len = G_TFMINPKTSIZE(ctlb);
|
||||
tp->skip_ofst = G_TFOFFSET(ctla);
|
||||
tp->skip_len = G_TFLENGTH(ctla);
|
||||
tp->invert = !!(ctla & F_TFINVERTMATCH);
|
||||
tp->port = G_TFPORT(ctla);
|
||||
|
||||
ofst = (A_MPS_TRC_FILTER1_MATCH - A_MPS_TRC_FILTER0_MATCH) * idx;
|
||||
data_reg = A_MPS_TRC_FILTER0_MATCH + ofst;
|
||||
@ -3584,11 +3711,19 @@ void t4_get_trace_filter(struct adapter *adap, struct trace_params *tp, int idx,
|
||||
void t4_pmtx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
|
||||
{
|
||||
int i;
|
||||
u32 data[2];
|
||||
|
||||
for (i = 0; i < PM_NSTATS; i++) {
|
||||
t4_write_reg(adap, A_PM_TX_STAT_CONFIG, i + 1);
|
||||
cnt[i] = t4_read_reg(adap, A_PM_TX_STAT_COUNT);
|
||||
cycles[i] = t4_read_reg64(adap, A_PM_TX_STAT_LSB);
|
||||
if (is_t4(adap))
|
||||
cycles[i] = t4_read_reg64(adap, A_PM_TX_STAT_LSB);
|
||||
else {
|
||||
t4_read_indirect(adap, A_PM_TX_DBG_CTRL,
|
||||
A_PM_TX_DBG_DATA, data, 2,
|
||||
A_PM_TX_DBG_STAT_MSB);
|
||||
cycles[i] = (((u64)data[0] << 32) | data[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3603,11 +3738,19 @@ void t4_pmtx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
|
||||
void t4_pmrx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
|
||||
{
|
||||
int i;
|
||||
u32 data[2];
|
||||
|
||||
for (i = 0; i < PM_NSTATS; i++) {
|
||||
t4_write_reg(adap, A_PM_RX_STAT_CONFIG, i + 1);
|
||||
cnt[i] = t4_read_reg(adap, A_PM_RX_STAT_COUNT);
|
||||
cycles[i] = t4_read_reg64(adap, A_PM_RX_STAT_LSB);
|
||||
if (is_t4(adap))
|
||||
cycles[i] = t4_read_reg64(adap, A_PM_RX_STAT_LSB);
|
||||
else {
|
||||
t4_read_indirect(adap, A_PM_RX_DBG_CTRL,
|
||||
A_PM_RX_DBG_DATA, data, 2,
|
||||
A_PM_RX_DBG_STAT_MSB);
|
||||
cycles[i] = (((u64)data[0] << 32) | data[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3666,7 +3809,9 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
|
||||
u32 bgmap = get_mps_bg_map(adap, idx);
|
||||
|
||||
#define GET_STAT(name) \
|
||||
t4_read_reg64(adap, PORT_REG(idx, A_MPS_PORT_STAT_##name##_L))
|
||||
t4_read_reg64(adap, \
|
||||
(is_t4(adap) ? PORT_REG(idx, A_MPS_PORT_STAT_##name##_L) : \
|
||||
T5_PORT_REG(idx, A_MPS_PORT_STAT_##name##_L)))
|
||||
#define GET_STAT_COM(name) t4_read_reg64(adap, A_MPS_STAT_##name##_L)
|
||||
|
||||
p->tx_pause = GET_STAT(TX_PORT_PAUSE);
|
||||
@ -3745,13 +3890,19 @@ void t4_clr_port_stats(struct adapter *adap, int idx)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 bgmap = get_mps_bg_map(adap, idx);
|
||||
u32 port_base_addr;
|
||||
|
||||
if (is_t4(adap))
|
||||
port_base_addr = PORT_BASE(idx);
|
||||
else
|
||||
port_base_addr = T5_PORT_BASE(idx);
|
||||
|
||||
for (i = A_MPS_PORT_STAT_TX_PORT_BYTES_L;
|
||||
i <= A_MPS_PORT_STAT_TX_PORT_PPP7_H; i += 8)
|
||||
t4_write_reg(adap, PORT_REG(idx, i), 0);
|
||||
i <= A_MPS_PORT_STAT_TX_PORT_PPP7_H; i += 8)
|
||||
t4_write_reg(adap, port_base_addr + i, 0);
|
||||
for (i = A_MPS_PORT_STAT_RX_PORT_BYTES_L;
|
||||
i <= A_MPS_PORT_STAT_RX_PORT_LESS_64B_H; i += 8)
|
||||
t4_write_reg(adap, PORT_REG(idx, i), 0);
|
||||
i <= A_MPS_PORT_STAT_RX_PORT_LESS_64B_H; i += 8)
|
||||
t4_write_reg(adap, port_base_addr + i, 0);
|
||||
for (i = 0; i < 4; i++)
|
||||
if (bgmap & (1 << i)) {
|
||||
t4_write_reg(adap,
|
||||
@ -3774,7 +3925,10 @@ void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
|
||||
u32 bgmap = get_mps_bg_map(adap, idx);
|
||||
|
||||
#define GET_STAT(name) \
|
||||
t4_read_reg64(adap, PORT_REG(idx, A_MPS_PORT_STAT_LB_PORT_##name##_L))
|
||||
t4_read_reg64(adap, \
|
||||
(is_t4(adap) ? \
|
||||
PORT_REG(idx, A_MPS_PORT_STAT_LB_PORT_##name##_L) : \
|
||||
T5_PORT_REG(idx, A_MPS_PORT_STAT_LB_PORT_##name##_L)))
|
||||
#define GET_STAT_COM(name) t4_read_reg64(adap, A_MPS_STAT_##name##_L)
|
||||
|
||||
p->octets = GET_STAT(BYTES);
|
||||
@ -3791,8 +3945,7 @@ void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
|
||||
p->frames_512_1023 = GET_STAT(512B_1023B);
|
||||
p->frames_1024_1518 = GET_STAT(1024B_1518B);
|
||||
p->frames_1519_max = GET_STAT(1519B_MAX);
|
||||
p->drop = t4_read_reg(adap, PORT_REG(idx,
|
||||
A_MPS_PORT_STAT_LB_PORT_DROP_FRAMES));
|
||||
p->drop = GET_STAT(DROP_FRAMES);
|
||||
|
||||
p->ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_DROP_FRAME) : 0;
|
||||
p->ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_DROP_FRAME) : 0;
|
||||
@ -3818,14 +3971,26 @@ void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
|
||||
void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
|
||||
const u8 *addr)
|
||||
{
|
||||
u32 mag_id_reg_l, mag_id_reg_h, port_cfg_reg;
|
||||
|
||||
if (is_t4(adap)) {
|
||||
mag_id_reg_l = PORT_REG(port, A_XGMAC_PORT_MAGIC_MACID_LO);
|
||||
mag_id_reg_h = PORT_REG(port, A_XGMAC_PORT_MAGIC_MACID_HI);
|
||||
port_cfg_reg = PORT_REG(port, A_XGMAC_PORT_CFG2);
|
||||
} else {
|
||||
mag_id_reg_l = T5_PORT_REG(port, A_MAC_PORT_MAGIC_MACID_LO);
|
||||
mag_id_reg_h = T5_PORT_REG(port, A_MAC_PORT_MAGIC_MACID_HI);
|
||||
port_cfg_reg = T5_PORT_REG(port, A_MAC_PORT_CFG2);
|
||||
}
|
||||
|
||||
if (addr) {
|
||||
t4_write_reg(adap, PORT_REG(port, A_XGMAC_PORT_MAGIC_MACID_LO),
|
||||
t4_write_reg(adap, mag_id_reg_l,
|
||||
(addr[2] << 24) | (addr[3] << 16) |
|
||||
(addr[4] << 8) | addr[5]);
|
||||
t4_write_reg(adap, PORT_REG(port, A_XGMAC_PORT_MAGIC_MACID_HI),
|
||||
t4_write_reg(adap, mag_id_reg_h,
|
||||
(addr[0] << 8) | addr[1]);
|
||||
}
|
||||
t4_set_reg_field(adap, PORT_REG(port, A_XGMAC_PORT_CFG2), F_MAGICEN,
|
||||
t4_set_reg_field(adap, port_cfg_reg, F_MAGICEN,
|
||||
V_MAGICEN(addr != NULL));
|
||||
}
|
||||
|
||||
@ -3848,16 +4013,23 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
|
||||
u64 mask0, u64 mask1, unsigned int crc, bool enable)
|
||||
{
|
||||
int i;
|
||||
u32 port_cfg_reg;
|
||||
|
||||
if (is_t4(adap))
|
||||
port_cfg_reg = PORT_REG(port, A_XGMAC_PORT_CFG2);
|
||||
else
|
||||
port_cfg_reg = T5_PORT_REG(port, A_MAC_PORT_CFG2);
|
||||
|
||||
if (!enable) {
|
||||
t4_set_reg_field(adap, PORT_REG(port, A_XGMAC_PORT_CFG2),
|
||||
F_PATEN, 0);
|
||||
t4_set_reg_field(adap, port_cfg_reg, F_PATEN, 0);
|
||||
return 0;
|
||||
}
|
||||
if (map > 0xff)
|
||||
return -EINVAL;
|
||||
|
||||
#define EPIO_REG(name) PORT_REG(port, A_XGMAC_PORT_EPIO_##name)
|
||||
#define EPIO_REG(name) \
|
||||
(is_t4(adap) ? PORT_REG(port, A_XGMAC_PORT_EPIO_##name) : \
|
||||
T5_PORT_REG(port, A_MAC_PORT_EPIO_##name))
|
||||
|
||||
t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32);
|
||||
t4_write_reg(adap, EPIO_REG(DATA2), mask1);
|
||||
@ -3883,7 +4055,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
|
||||
}
|
||||
#undef EPIO_REG
|
||||
|
||||
t4_set_reg_field(adap, PORT_REG(port, A_XGMAC_PORT_CFG2), 0, F_PATEN);
|
||||
t4_set_reg_field(adap, port_cfg_reg, 0, F_PATEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4763,9 +4935,12 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
|
||||
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 rem = naddr;
|
||||
|
||||
if (naddr > NUM_MPS_CLS_SRAM_L_INSTANCES)
|
||||
if (naddr > max_naddr)
|
||||
return -EINVAL;
|
||||
|
||||
for (offset = 0; offset < naddr ; /**/) {
|
||||
@ -4806,10 +4981,10 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
|
||||
u16 index = G_FW_VI_MAC_CMD_IDX(ntohs(p->valid_to_idx));
|
||||
|
||||
if (idx)
|
||||
idx[offset+i] = (index >= NUM_MPS_CLS_SRAM_L_INSTANCES
|
||||
idx[offset+i] = (index >= max_naddr
|
||||
? 0xffff
|
||||
: index);
|
||||
if (index < NUM_MPS_CLS_SRAM_L_INSTANCES)
|
||||
if (index < max_naddr)
|
||||
nfilters++;
|
||||
else if (hash)
|
||||
*hash |= (1ULL << hash_mac_addr(addr[offset+i]));
|
||||
@ -4853,6 +5028,9 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
|
||||
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;
|
||||
|
||||
if (idx < 0) /* new allocation */
|
||||
idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC;
|
||||
@ -4867,10 +5045,10 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
|
||||
V_FW_VI_MAC_CMD_IDX(idx));
|
||||
memcpy(p->macaddr, addr, sizeof(p->macaddr));
|
||||
|
||||
ret = t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), &c);
|
||||
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
|
||||
if (ret == 0) {
|
||||
ret = G_FW_VI_MAC_CMD_IDX(ntohs(p->valid_to_idx));
|
||||
if (ret >= NUM_MPS_CLS_SRAM_L_INSTANCES)
|
||||
if (ret >= max_mac_addr)
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
return ret;
|
||||
@ -5188,21 +5366,6 @@ static void __devinit init_link_config(struct link_config *lc,
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit wait_dev_ready(struct adapter *adap)
|
||||
{
|
||||
u32 whoami;
|
||||
|
||||
whoami = t4_read_reg(adap, A_PL_WHOAMI);
|
||||
|
||||
if (whoami != 0xffffffff && whoami != X_CIM_PF_NOACCESS)
|
||||
return 0;
|
||||
|
||||
msleep(500);
|
||||
whoami = t4_read_reg(adap, A_PL_WHOAMI);
|
||||
return (whoami != 0xffffffff && whoami != X_CIM_PF_NOACCESS
|
||||
? 0 : -EIO);
|
||||
}
|
||||
|
||||
static int __devinit get_flash_params(struct adapter *adapter)
|
||||
{
|
||||
int ret;
|
||||
@ -5255,21 +5418,26 @@ static void __devinit set_pcie_completion_timeout(struct adapter *adapter,
|
||||
int __devinit t4_prep_adapter(struct adapter *adapter)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wait_dev_ready(adapter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
uint16_t device_id;
|
||||
uint32_t pl_rev;
|
||||
|
||||
get_pci_mode(adapter, &adapter->params.pci);
|
||||
|
||||
adapter->params.rev = t4_read_reg(adapter, A_PL_REV);
|
||||
/* T4A1 chip is no longer supported */
|
||||
if (adapter->params.rev == 1) {
|
||||
CH_ALERT(adapter, "T4 rev 1 chip is no longer supported\n");
|
||||
return -EINVAL;
|
||||
pl_rev = t4_read_reg(adapter, A_PL_REV);
|
||||
adapter->params.chipid = G_CHIPID(pl_rev);
|
||||
adapter->params.rev = G_REV(pl_rev);
|
||||
if (adapter->params.chipid == 0) {
|
||||
/* T4 did not have chipid in PL_REV (T5 onwards do) */
|
||||
adapter->params.chipid = CHELSIO_T4;
|
||||
|
||||
/* T4A1 chip is not supported */
|
||||
if (adapter->params.rev == 1) {
|
||||
CH_ALERT(adapter, "T4 rev 1 chip is not supported.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
adapter->params.pci.vpd_cap_addr =
|
||||
t4_os_find_pci_capability(adapter, PCI_CAP_ID_VPD);
|
||||
t4_os_find_pci_capability(adapter, PCI_CAP_ID_VPD);
|
||||
|
||||
ret = get_flash_params(adapter);
|
||||
if (ret < 0)
|
||||
@ -5279,12 +5447,14 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (t4_read_reg(adapter, A_PCIE_REVISION) != 0) {
|
||||
/* FPGA */
|
||||
adapter->params.cim_la_size = 2 * CIMLA_SIZE;
|
||||
} else {
|
||||
/* ASIC */
|
||||
/* 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)
|
||||
adapter->params.cim_la_size = CIMLA_SIZE;
|
||||
else {
|
||||
/* FPGA */
|
||||
adapter->params.fpga = 1;
|
||||
adapter->params.cim_la_size = 2 * CIMLA_SIZE;
|
||||
}
|
||||
|
||||
init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
|
||||
|
@ -33,27 +33,32 @@
|
||||
#include "osdep.h"
|
||||
|
||||
enum {
|
||||
NCHAN = 4, /* # of HW channels */
|
||||
MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */
|
||||
EEPROMSIZE = 17408, /* Serial EEPROM physical size */
|
||||
EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */
|
||||
EEPROMPFSIZE = 1024, /* EEPROM writable area size for PFn, n>0 */
|
||||
RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */
|
||||
TCB_SIZE = 128, /* TCB size */
|
||||
NMTUS = 16, /* size of MTU table */
|
||||
NCCTRL_WIN = 32, /* # of congestion control windows */
|
||||
NTX_SCHED = 8, /* # of HW Tx scheduling queues */
|
||||
PM_NSTATS = 5, /* # of PM stats */
|
||||
MBOX_LEN = 64, /* mailbox size in bytes */
|
||||
TRACE_LEN = 112, /* length of trace data and mask */
|
||||
FILTER_OPT_LEN = 36, /* filter tuple width for optional components */
|
||||
NWOL_PAT = 8, /* # of WoL patterns */
|
||||
WOL_PAT_LEN = 128, /* length of WoL patterns */
|
||||
NCHAN = 4, /* # of HW channels */
|
||||
MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */
|
||||
EEPROMSIZE = 17408, /* Serial EEPROM physical size */
|
||||
EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */
|
||||
EEPROMPFSIZE = 1024, /* EEPROM writable area size for PFn, n>0 */
|
||||
RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */
|
||||
TCB_SIZE = 128, /* TCB size */
|
||||
NMTUS = 16, /* size of MTU table */
|
||||
NCCTRL_WIN = 32, /* # of congestion control windows */
|
||||
NTX_SCHED = 8, /* # of HW Tx scheduling queues */
|
||||
PM_NSTATS = 5, /* # of PM stats */
|
||||
MBOX_LEN = 64, /* mailbox size in bytes */
|
||||
TRACE_LEN = 112, /* length of trace data and mask */
|
||||
FILTER_OPT_LEN = 36, /* filter tuple width of optional components */
|
||||
NWOL_PAT = 8, /* # of WoL patterns */
|
||||
WOL_PAT_LEN = 128, /* length of WoL patterns */
|
||||
UDBS_SEG_SIZE = 128, /* Segment size of BAR2 doorbells */
|
||||
UDBS_SEG_SHIFT = 7, /* log2(UDBS_SEG_SIZE) */
|
||||
UDBS_DB_OFFSET = 8, /* offset of the 4B doorbell in a segment */
|
||||
UDBS_WR_OFFSET = 64, /* offset of the work request in a segment */
|
||||
};
|
||||
|
||||
enum {
|
||||
CIM_NUM_IBQ = 6, /* # of CIM IBQs */
|
||||
CIM_NUM_OBQ = 6, /* # of CIM OBQs */
|
||||
CIM_NUM_OBQ_T5 = 8, /* # of CIM OBQs for T5 adapter */
|
||||
CIMLA_SIZE = 2048, /* # of 32-bit words in CIM LA */
|
||||
CIM_PIFLA_SIZE = 64, /* # of 192-bit words in CIM PIF LA */
|
||||
CIM_MALA_SIZE = 64, /* # of 160-bit words in CIM MA LA */
|
||||
@ -80,6 +85,7 @@ enum {
|
||||
SGE_CTXT_SIZE = 24, /* size of SGE context */
|
||||
SGE_NTIMERS = 6, /* # of interrupt holdoff timer values */
|
||||
SGE_NCOUNTERS = 4, /* # of interrupt packet counter values */
|
||||
SGE_MAX_IQ_SIZE = 65520,
|
||||
};
|
||||
|
||||
struct sge_qstat { /* data written to SGE queue status entries */
|
||||
@ -221,7 +227,7 @@ enum {
|
||||
* Location of firmware image in FLASH.
|
||||
*/
|
||||
FLASH_FW_START_SEC = 8,
|
||||
FLASH_FW_NSECS = 8,
|
||||
FLASH_FW_NSECS = 16,
|
||||
FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC),
|
||||
FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS),
|
||||
|
||||
|
@ -104,6 +104,7 @@ enum {
|
||||
CPL_RX_ISCSI_DDP = 0x49,
|
||||
CPL_RX_FCOE_DIF = 0x4A,
|
||||
CPL_RX_DATA_DIF = 0x4B,
|
||||
CPL_ERR_NOTIFY = 0x4D,
|
||||
|
||||
CPL_RDMA_READ_REQ = 0x60,
|
||||
CPL_RX_ISCSI_DIF = 0x60,
|
||||
@ -125,6 +126,7 @@ enum {
|
||||
CPL_RDMA_IMM_DATA_SE = 0xAD,
|
||||
|
||||
CPL_TRACE_PKT = 0xB0,
|
||||
CPL_TRACE_PKT_T5 = 0x48,
|
||||
CPL_RX2TX_DATA = 0xB1,
|
||||
CPL_ISCSI_DATA = 0xB2,
|
||||
CPL_FCOE_DATA = 0xB3,
|
||||
@ -478,6 +480,11 @@ struct work_request_hdr {
|
||||
#define V_CONN_POLICY(x) ((x) << S_CONN_POLICY)
|
||||
#define G_CONN_POLICY(x) (((x) >> S_CONN_POLICY) & M_CONN_POLICY)
|
||||
|
||||
#define S_FILT_INFO 28
|
||||
#define M_FILT_INFO 0xfffffffffULL
|
||||
#define V_FILT_INFO(x) ((x) << S_FILT_INFO)
|
||||
#define G_FILT_INFO(x) (((x) >> S_FILT_INFO) & M_FILT_INFO)
|
||||
|
||||
/* option 2 fields */
|
||||
#define S_RSS_QUEUE 0
|
||||
#define M_RSS_QUEUE 0x3FF
|
||||
@ -552,6 +559,10 @@ struct work_request_hdr {
|
||||
#define V_SACK_EN(x) ((x) << S_SACK_EN)
|
||||
#define F_SACK_EN V_SACK_EN(1U)
|
||||
|
||||
#define S_T5_OPT_2_VALID 31
|
||||
#define V_T5_OPT_2_VALID(x) ((x) << S_T5_OPT_2_VALID)
|
||||
#define F_T5_OPT_2_VALID V_T5_OPT_2_VALID(1U)
|
||||
|
||||
struct cpl_pass_open_req {
|
||||
WR_HDR;
|
||||
union opcode_tid ot;
|
||||
@ -679,6 +690,10 @@ struct cpl_act_open_req {
|
||||
__be32 opt2;
|
||||
};
|
||||
|
||||
#define S_FILTER_TUPLE 24
|
||||
#define M_FILTER_TUPLE 0xFFFFFFFFFF
|
||||
#define V_FILTER_TUPLE(x) ((x) << S_FILTER_TUPLE)
|
||||
#define G_FILTER_TUPLE(x) (((x) >> S_FILTER_TUPLE) & M_FILTER_TUPLE)
|
||||
struct cpl_t5_act_open_req {
|
||||
WR_HDR;
|
||||
union opcode_tid ot;
|
||||
@ -1053,6 +1068,12 @@ struct cpl_tx_pkt {
|
||||
#define V_TXPKT_OVLAN_IDX(x) ((x) << S_TXPKT_OVLAN_IDX)
|
||||
#define G_TXPKT_OVLAN_IDX(x) (((x) >> S_TXPKT_OVLAN_IDX) & M_TXPKT_OVLAN_IDX)
|
||||
|
||||
#define S_TXPKT_T5_OVLAN_IDX 12
|
||||
#define M_TXPKT_T5_OVLAN_IDX 0x7
|
||||
#define V_TXPKT_T5_OVLAN_IDX(x) ((x) << S_TXPKT_T5_OVLAN_IDX)
|
||||
#define G_TXPKT_T5_OVLAN_IDX(x) (((x) >> S_TXPKT_T5_OVLAN_IDX) & \
|
||||
M_TXPKT_T5_OVLAN_IDX)
|
||||
|
||||
#define S_TXPKT_INTF 16
|
||||
#define M_TXPKT_INTF 0xF
|
||||
#define V_TXPKT_INTF(x) ((x) << S_TXPKT_INTF)
|
||||
@ -1062,10 +1083,18 @@ struct cpl_tx_pkt {
|
||||
#define V_TXPKT_SPECIAL_STAT(x) ((x) << S_TXPKT_SPECIAL_STAT)
|
||||
#define F_TXPKT_SPECIAL_STAT V_TXPKT_SPECIAL_STAT(1U)
|
||||
|
||||
#define S_TXPKT_T5_FCS_DIS 21
|
||||
#define V_TXPKT_T5_FCS_DIS(x) ((x) << S_TXPKT_T5_FCS_DIS)
|
||||
#define F_TXPKT_T5_FCS_DIS V_TXPKT_T5_FCS_DIS(1U)
|
||||
|
||||
#define S_TXPKT_INS_OVLAN 21
|
||||
#define V_TXPKT_INS_OVLAN(x) ((x) << S_TXPKT_INS_OVLAN)
|
||||
#define F_TXPKT_INS_OVLAN V_TXPKT_INS_OVLAN(1U)
|
||||
|
||||
#define S_TXPKT_T5_INS_OVLAN 15
|
||||
#define V_TXPKT_T5_INS_OVLAN(x) ((x) << S_TXPKT_T5_INS_OVLAN)
|
||||
#define F_TXPKT_T5_INS_OVLAN V_TXPKT_T5_INS_OVLAN(1U)
|
||||
|
||||
#define S_TXPKT_STAT_DIS 22
|
||||
#define V_TXPKT_STAT_DIS(x) ((x) << S_TXPKT_STAT_DIS)
|
||||
#define F_TXPKT_STAT_DIS V_TXPKT_STAT_DIS(1U)
|
||||
@ -1208,6 +1237,11 @@ struct cpl_tx_pkt_ufo {
|
||||
#define V_LSO_OPCODE(x) ((x) << S_LSO_OPCODE)
|
||||
#define G_LSO_OPCODE(x) (((x) >> S_LSO_OPCODE) & M_LSO_OPCODE)
|
||||
|
||||
#define S_LSO_T5_XFER_SIZE 0
|
||||
#define M_LSO_T5_XFER_SIZE 0xFFFFFFF
|
||||
#define V_LSO_T5_XFER_SIZE(x) ((x) << S_LSO_T5_XFER_SIZE)
|
||||
#define G_LSO_T5_XFER_SIZE(x) (((x) >> S_LSO_T5_XFER_SIZE) & M_LSO_T5_XFER_SIZE)
|
||||
|
||||
/* cpl_tx_pkt_lso_core.mss fields */
|
||||
#define S_LSO_MSS 0
|
||||
#define M_LSO_MSS 0x3FFF
|
||||
@ -1906,14 +1940,24 @@ struct cpl_l2t_write_req {
|
||||
#define G_L2T_W_INFO(x) (((x) >> S_L2T_W_INFO) & M_L2T_W_INFO)
|
||||
|
||||
#define S_L2T_W_PORT 8
|
||||
#define M_L2T_W_PORT 0xF
|
||||
#define M_L2T_W_PORT 0x3
|
||||
#define V_L2T_W_PORT(x) ((x) << S_L2T_W_PORT)
|
||||
#define G_L2T_W_PORT(x) (((x) >> S_L2T_W_PORT) & M_L2T_W_PORT)
|
||||
|
||||
#define S_L2T_W_LPBK 10
|
||||
#define V_L2T_W_LPBK(x) ((x) << S_L2T_W_LPBK)
|
||||
#define F_L2T_W_PKBK V_L2T_W_LPBK(1U)
|
||||
|
||||
#define S_L2T_W_ARPMISS 11
|
||||
#define V_L2T_W_ARPMISS(x) ((x) << S_L2T_W_ARPMISS)
|
||||
#define F_L2T_W_ARPMISS V_L2T_W_ARPMISS(1U)
|
||||
|
||||
#define S_L2T_W_NOREPLY 15
|
||||
#define V_L2T_W_NOREPLY(x) ((x) << S_L2T_W_NOREPLY)
|
||||
#define F_L2T_W_NOREPLY V_L2T_W_NOREPLY(1U)
|
||||
|
||||
#define CPL_L2T_VLAN_NONE 0xfff
|
||||
|
||||
struct cpl_l2t_write_rpl {
|
||||
RSS_HDR
|
||||
union opcode_tid ot;
|
||||
@ -2394,6 +2438,14 @@ struct ulp_mem_io {
|
||||
#define V_ULP_MEMIO_ORDER(x) ((x) << S_ULP_MEMIO_ORDER)
|
||||
#define F_ULP_MEMIO_ORDER V_ULP_MEMIO_ORDER(1U)
|
||||
|
||||
#define S_T5_ULP_MEMIO_IMM 23
|
||||
#define V_T5_ULP_MEMIO_IMM(x) ((x) << S_T5_ULP_MEMIO_IMM)
|
||||
#define F_T5_ULP_MEMIO_IMM V_T5_ULP_MEMIO_IMM(1U)
|
||||
|
||||
#define S_T5_ULP_MEMIO_ORDER 22
|
||||
#define V_T5_ULP_MEMIO_ORDER(x) ((x) << S_T5_ULP_MEMIO_ORDER)
|
||||
#define F_T5_ULP_MEMIO_ORDER V_T5_ULP_MEMIO_ORDER(1U)
|
||||
|
||||
/* ulp_mem_io.lock_addr fields */
|
||||
#define S_ULP_MEMIO_ADDR 0
|
||||
#define M_ULP_MEMIO_ADDR 0x7FFFFFF
|
||||
@ -2408,6 +2460,14 @@ struct ulp_mem_io {
|
||||
#define M_ULP_MEMIO_DATA_LEN 0x1F
|
||||
#define V_ULP_MEMIO_DATA_LEN(x) ((x) << S_ULP_MEMIO_DATA_LEN)
|
||||
|
||||
/* ULP_TXPKT field values */
|
||||
enum {
|
||||
ULP_TXPKT_DEST_TP = 0,
|
||||
ULP_TXPKT_DEST_SGE,
|
||||
ULP_TXPKT_DEST_UP,
|
||||
ULP_TXPKT_DEST_DEVNULL,
|
||||
};
|
||||
|
||||
struct ulp_txpkt {
|
||||
__be32 cmd_dest;
|
||||
__be32 len;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -64,8 +64,11 @@ typedef uint64_t __be64;
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define __BIG_ENDIAN_BITFIELD
|
||||
#define htobe32_const(x) (x)
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define __LITTLE_ENDIAN_BITFIELD
|
||||
#define htobe32_const(x) (((x) >> 24) | (((x) >> 8) & 0xff00) | \
|
||||
((((x) & 0xffffff) << 8) & 0xff0000) | ((((x) & 0xff) << 24) & 0xff000000))
|
||||
#else
|
||||
#error "Must set BYTE_ORDER"
|
||||
#endif
|
||||
|
@ -60,6 +60,7 @@ struct t4_reg {
|
||||
};
|
||||
|
||||
#define T4_REGDUMP_SIZE (160 * 1024)
|
||||
#define T5_REGDUMP_SIZE (332 * 1024)
|
||||
struct t4_regdump {
|
||||
uint32_t version;
|
||||
uint32_t len; /* bytes */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -68,6 +68,12 @@ static struct fl_buf_info fl_buf_info[FL_BUF_SIZES];
|
||||
#define FL_BUF_TYPE(x) (fl_buf_info[x].type)
|
||||
#define FL_BUF_ZONE(x) (fl_buf_info[x].zone)
|
||||
|
||||
#ifdef T4_PKT_TIMESTAMP
|
||||
#define RX_COPY_THRESHOLD (MINCLSIZE - 8)
|
||||
#else
|
||||
#define RX_COPY_THRESHOLD MINCLSIZE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ethernet frames are DMA'd at this byte offset into the freelist buffer.
|
||||
* 0-7 are valid values.
|
||||
@ -262,29 +268,38 @@ t4_sge_modload(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_sge_init - initialize SGE
|
||||
* @sc: the adapter
|
||||
*
|
||||
* Performs SGE initialization needed every time after a chip reset.
|
||||
* We do not initialize any of the queues here, instead the driver
|
||||
* top-level must request them individually.
|
||||
*/
|
||||
int
|
||||
t4_sge_init(struct adapter *sc)
|
||||
void
|
||||
t4_init_sge_cpl_handlers(struct adapter *sc)
|
||||
{
|
||||
struct sge *s = &sc->sge;
|
||||
int i, rc = 0;
|
||||
uint32_t ctrl_mask, ctrl_val, hpsize, v;
|
||||
|
||||
ctrl_mask = V_PKTSHIFT(M_PKTSHIFT) | F_RXPKTCPLMODE |
|
||||
V_INGPADBOUNDARY(M_INGPADBOUNDARY) |
|
||||
F_EGRSTATUSPAGESIZE;
|
||||
ctrl_val = V_PKTSHIFT(fl_pktshift) | F_RXPKTCPLMODE |
|
||||
t4_register_cpl_handler(sc, CPL_FW4_MSG, handle_fw_msg);
|
||||
t4_register_cpl_handler(sc, CPL_FW6_MSG, handle_fw_msg);
|
||||
t4_register_cpl_handler(sc, CPL_SGE_EGR_UPDATE, handle_sge_egr_update);
|
||||
t4_register_cpl_handler(sc, CPL_RX_PKT, t4_eth_rx);
|
||||
|
||||
t4_register_fw_msg_handler(sc, FW6_TYPE_CMD_RPL, t4_handle_fw_rpl);
|
||||
}
|
||||
|
||||
void
|
||||
t4_tweak_chip_settings(struct adapter *sc)
|
||||
{
|
||||
int i;
|
||||
uint32_t v, m;
|
||||
int intr_timer[SGE_NTIMERS] = {1, 5, 10, 50, 100, 200};
|
||||
int intr_pktcount[SGE_NCOUNTERS] = {1, 8, 16, 32}; /* 63 max */
|
||||
uint16_t indsz = min(RX_COPY_THRESHOLD - 1, M_INDICATESIZE);
|
||||
|
||||
KASSERT(sc->flags & MASTER_PF,
|
||||
("%s: trying to change chip settings when not master.", __func__));
|
||||
|
||||
m = V_PKTSHIFT(M_PKTSHIFT) | F_RXPKTCPLMODE |
|
||||
V_INGPADBOUNDARY(M_INGPADBOUNDARY) | F_EGRSTATUSPAGESIZE;
|
||||
v = V_PKTSHIFT(fl_pktshift) | F_RXPKTCPLMODE |
|
||||
V_INGPADBOUNDARY(ilog2(fl_pad) - 5) |
|
||||
V_EGRSTATUSPAGESIZE(spg_len == 128);
|
||||
t4_set_reg_field(sc, A_SGE_CONTROL, m, v);
|
||||
|
||||
hpsize = V_HOSTPAGESIZEPF0(PAGE_SHIFT - 10) |
|
||||
v = V_HOSTPAGESIZEPF0(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF1(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF2(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF3(PAGE_SHIFT - 10) |
|
||||
@ -292,50 +307,80 @@ t4_sge_init(struct adapter *sc)
|
||||
V_HOSTPAGESIZEPF5(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF6(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF7(PAGE_SHIFT - 10);
|
||||
t4_write_reg(sc, A_SGE_HOST_PAGE_SIZE, v);
|
||||
|
||||
if (sc->flags & MASTER_PF) {
|
||||
int intr_timer[SGE_NTIMERS] = {1, 5, 10, 50, 100, 200};
|
||||
int intr_pktcount[SGE_NCOUNTERS] = {1, 8, 16, 32}; /* 63 max */
|
||||
|
||||
t4_set_reg_field(sc, A_SGE_CONTROL, ctrl_mask, ctrl_val);
|
||||
t4_write_reg(sc, A_SGE_HOST_PAGE_SIZE, hpsize);
|
||||
for (i = 0; i < FL_BUF_SIZES; i++) {
|
||||
t4_write_reg(sc, A_SGE_FL_BUFFER_SIZE0 + (4 * i),
|
||||
FL_BUF_SIZE(i));
|
||||
}
|
||||
|
||||
t4_write_reg(sc, A_SGE_INGRESS_RX_THRESHOLD,
|
||||
V_THRESHOLD_0(intr_pktcount[0]) |
|
||||
V_THRESHOLD_1(intr_pktcount[1]) |
|
||||
V_THRESHOLD_2(intr_pktcount[2]) |
|
||||
V_THRESHOLD_3(intr_pktcount[3]));
|
||||
|
||||
t4_write_reg(sc, A_SGE_TIMER_VALUE_0_AND_1,
|
||||
V_TIMERVALUE0(us_to_core_ticks(sc, intr_timer[0])) |
|
||||
V_TIMERVALUE1(us_to_core_ticks(sc, intr_timer[1])));
|
||||
t4_write_reg(sc, A_SGE_TIMER_VALUE_2_AND_3,
|
||||
V_TIMERVALUE2(us_to_core_ticks(sc, intr_timer[2])) |
|
||||
V_TIMERVALUE3(us_to_core_ticks(sc, intr_timer[3])));
|
||||
t4_write_reg(sc, A_SGE_TIMER_VALUE_4_AND_5,
|
||||
V_TIMERVALUE4(us_to_core_ticks(sc, intr_timer[4])) |
|
||||
V_TIMERVALUE5(us_to_core_ticks(sc, intr_timer[5])));
|
||||
|
||||
if (cong_drop == 0) {
|
||||
t4_set_reg_field(sc, A_TP_PARA_REG3, F_TUNNELCNGDROP0 |
|
||||
F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 |
|
||||
F_TUNNELCNGDROP3, 0);
|
||||
}
|
||||
for (i = 0; i < FL_BUF_SIZES; i++) {
|
||||
t4_write_reg(sc, A_SGE_FL_BUFFER_SIZE0 + (4 * i),
|
||||
FL_BUF_SIZE(i));
|
||||
}
|
||||
|
||||
v = t4_read_reg(sc, A_SGE_CONTROL);
|
||||
if ((v & ctrl_mask) != ctrl_val) {
|
||||
device_printf(sc->dev, "invalid SGE_CONTROL(0x%x)\n", v);
|
||||
v = V_THRESHOLD_0(intr_pktcount[0]) | V_THRESHOLD_1(intr_pktcount[1]) |
|
||||
V_THRESHOLD_2(intr_pktcount[2]) | V_THRESHOLD_3(intr_pktcount[3]);
|
||||
t4_write_reg(sc, A_SGE_INGRESS_RX_THRESHOLD, v);
|
||||
|
||||
/* adap->params.vpd.cclk must be set up before this */
|
||||
v = V_TIMERVALUE0(us_to_core_ticks(sc, intr_timer[0])) |
|
||||
V_TIMERVALUE1(us_to_core_ticks(sc, intr_timer[1]));
|
||||
t4_write_reg(sc, A_SGE_TIMER_VALUE_0_AND_1, v);
|
||||
v = V_TIMERVALUE2(us_to_core_ticks(sc, intr_timer[2])) |
|
||||
V_TIMERVALUE3(us_to_core_ticks(sc, intr_timer[3]));
|
||||
t4_write_reg(sc, A_SGE_TIMER_VALUE_2_AND_3, v);
|
||||
v = V_TIMERVALUE4(us_to_core_ticks(sc, intr_timer[4])) |
|
||||
V_TIMERVALUE5(us_to_core_ticks(sc, intr_timer[5]));
|
||||
t4_write_reg(sc, A_SGE_TIMER_VALUE_4_AND_5, v);
|
||||
|
||||
if (cong_drop == 0) {
|
||||
m = F_TUNNELCNGDROP0 | F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 |
|
||||
F_TUNNELCNGDROP3;
|
||||
t4_set_reg_field(sc, A_TP_PARA_REG3, m, 0);
|
||||
}
|
||||
|
||||
/* 4K, 16K, 64K, 256K DDP "page sizes" */
|
||||
v = V_HPZ0(0) | V_HPZ1(2) | V_HPZ2(4) | V_HPZ3(6);
|
||||
t4_write_reg(sc, A_ULP_RX_TDDP_PSZ, v);
|
||||
|
||||
m = v = F_TDDPTAGTCB;
|
||||
t4_set_reg_field(sc, A_ULP_RX_CTL, m, v);
|
||||
|
||||
m = V_INDICATESIZE(M_INDICATESIZE) | F_REARMDDPOFFSET |
|
||||
F_RESETDDPOFFSET;
|
||||
v = V_INDICATESIZE(indsz) | F_REARMDDPOFFSET | F_RESETDDPOFFSET;
|
||||
t4_set_reg_field(sc, A_TP_PARA_REG5, m, v);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: driver really should be able to deal with unexpected settings.
|
||||
*/
|
||||
int
|
||||
t4_read_chip_settings(struct adapter *sc)
|
||||
{
|
||||
struct sge *s = &sc->sge;
|
||||
int i, rc = 0;
|
||||
uint32_t m, v, r;
|
||||
uint16_t indsz = min(RX_COPY_THRESHOLD - 1, M_INDICATESIZE);
|
||||
|
||||
m = V_PKTSHIFT(M_PKTSHIFT) | F_RXPKTCPLMODE |
|
||||
V_INGPADBOUNDARY(M_INGPADBOUNDARY) | F_EGRSTATUSPAGESIZE;
|
||||
v = V_PKTSHIFT(fl_pktshift) | F_RXPKTCPLMODE |
|
||||
V_INGPADBOUNDARY(ilog2(fl_pad) - 5) |
|
||||
V_EGRSTATUSPAGESIZE(spg_len == 128);
|
||||
r = t4_read_reg(sc, A_SGE_CONTROL);
|
||||
if ((r & m) != v) {
|
||||
device_printf(sc->dev, "invalid SGE_CONTROL(0x%x)\n", r);
|
||||
rc = EINVAL;
|
||||
}
|
||||
|
||||
v = t4_read_reg(sc, A_SGE_HOST_PAGE_SIZE);
|
||||
if (v != hpsize) {
|
||||
device_printf(sc->dev, "invalid SGE_HOST_PAGE_SIZE(0x%x)\n", v);
|
||||
v = V_HOSTPAGESIZEPF0(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF1(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF2(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF3(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF4(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF5(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF6(PAGE_SHIFT - 10) |
|
||||
V_HOSTPAGESIZEPF7(PAGE_SHIFT - 10);
|
||||
r = t4_read_reg(sc, A_SGE_HOST_PAGE_SIZE);
|
||||
if (r != v) {
|
||||
device_printf(sc->dev, "invalid SGE_HOST_PAGE_SIZE(0x%x)\n", r);
|
||||
rc = EINVAL;
|
||||
}
|
||||
|
||||
@ -348,31 +393,75 @@ t4_sge_init(struct adapter *sc)
|
||||
}
|
||||
}
|
||||
|
||||
v = t4_read_reg(sc, A_SGE_CONM_CTRL);
|
||||
s->fl_starve_threshold = G_EGRTHRESHOLD(v) * 2 + 1;
|
||||
r = t4_read_reg(sc, A_SGE_INGRESS_RX_THRESHOLD);
|
||||
s->counter_val[0] = G_THRESHOLD_0(r);
|
||||
s->counter_val[1] = G_THRESHOLD_1(r);
|
||||
s->counter_val[2] = G_THRESHOLD_2(r);
|
||||
s->counter_val[3] = G_THRESHOLD_3(r);
|
||||
|
||||
v = t4_read_reg(sc, A_SGE_INGRESS_RX_THRESHOLD);
|
||||
sc->sge.counter_val[0] = G_THRESHOLD_0(v);
|
||||
sc->sge.counter_val[1] = G_THRESHOLD_1(v);
|
||||
sc->sge.counter_val[2] = G_THRESHOLD_2(v);
|
||||
sc->sge.counter_val[3] = G_THRESHOLD_3(v);
|
||||
r = t4_read_reg(sc, A_SGE_TIMER_VALUE_0_AND_1);
|
||||
s->timer_val[0] = G_TIMERVALUE0(r) / core_ticks_per_usec(sc);
|
||||
s->timer_val[1] = G_TIMERVALUE1(r) / core_ticks_per_usec(sc);
|
||||
r = t4_read_reg(sc, A_SGE_TIMER_VALUE_2_AND_3);
|
||||
s->timer_val[2] = G_TIMERVALUE2(r) / core_ticks_per_usec(sc);
|
||||
s->timer_val[3] = G_TIMERVALUE3(r) / core_ticks_per_usec(sc);
|
||||
r = t4_read_reg(sc, A_SGE_TIMER_VALUE_4_AND_5);
|
||||
s->timer_val[4] = G_TIMERVALUE4(r) / core_ticks_per_usec(sc);
|
||||
s->timer_val[5] = G_TIMERVALUE5(r) / core_ticks_per_usec(sc);
|
||||
|
||||
v = t4_read_reg(sc, A_SGE_TIMER_VALUE_0_AND_1);
|
||||
sc->sge.timer_val[0] = G_TIMERVALUE0(v) / core_ticks_per_usec(sc);
|
||||
sc->sge.timer_val[1] = G_TIMERVALUE1(v) / core_ticks_per_usec(sc);
|
||||
v = t4_read_reg(sc, A_SGE_TIMER_VALUE_2_AND_3);
|
||||
sc->sge.timer_val[2] = G_TIMERVALUE2(v) / core_ticks_per_usec(sc);
|
||||
sc->sge.timer_val[3] = G_TIMERVALUE3(v) / core_ticks_per_usec(sc);
|
||||
v = t4_read_reg(sc, A_SGE_TIMER_VALUE_4_AND_5);
|
||||
sc->sge.timer_val[4] = G_TIMERVALUE4(v) / core_ticks_per_usec(sc);
|
||||
sc->sge.timer_val[5] = G_TIMERVALUE5(v) / core_ticks_per_usec(sc);
|
||||
if (cong_drop == 0) {
|
||||
m = F_TUNNELCNGDROP0 | F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 |
|
||||
F_TUNNELCNGDROP3;
|
||||
r = t4_read_reg(sc, A_TP_PARA_REG3);
|
||||
if (r & m) {
|
||||
device_printf(sc->dev,
|
||||
"invalid TP_PARA_REG3(0x%x)\n", r);
|
||||
rc = EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
t4_register_cpl_handler(sc, CPL_FW4_MSG, handle_fw_msg);
|
||||
t4_register_cpl_handler(sc, CPL_FW6_MSG, handle_fw_msg);
|
||||
t4_register_cpl_handler(sc, CPL_SGE_EGR_UPDATE, handle_sge_egr_update);
|
||||
t4_register_cpl_handler(sc, CPL_RX_PKT, t4_eth_rx);
|
||||
v = V_HPZ0(0) | V_HPZ1(2) | V_HPZ2(4) | V_HPZ3(6);
|
||||
r = t4_read_reg(sc, A_ULP_RX_TDDP_PSZ);
|
||||
if (r != v) {
|
||||
device_printf(sc->dev, "invalid ULP_RX_TDDP_PSZ(0x%x)\n", r);
|
||||
rc = EINVAL;
|
||||
}
|
||||
|
||||
t4_register_fw_msg_handler(sc, FW6_TYPE_CMD_RPL, t4_handle_fw_rpl);
|
||||
m = v = F_TDDPTAGTCB;
|
||||
r = t4_read_reg(sc, A_ULP_RX_CTL);
|
||||
if ((r & m) != v) {
|
||||
device_printf(sc->dev, "invalid ULP_RX_CTL(0x%x)\n", r);
|
||||
rc = EINVAL;
|
||||
}
|
||||
|
||||
m = V_INDICATESIZE(M_INDICATESIZE) | F_REARMDDPOFFSET |
|
||||
F_RESETDDPOFFSET;
|
||||
v = V_INDICATESIZE(indsz) | F_REARMDDPOFFSET | F_RESETDDPOFFSET;
|
||||
r = t4_read_reg(sc, A_TP_PARA_REG5);
|
||||
if ((r & m) != v) {
|
||||
device_printf(sc->dev, "invalid TP_PARA_REG5(0x%x)\n", r);
|
||||
rc = EINVAL;
|
||||
}
|
||||
|
||||
r = t4_read_reg(sc, A_SGE_CONM_CTRL);
|
||||
s->fl_starve_threshold = G_EGRTHRESHOLD(r) * 2 + 1;
|
||||
|
||||
if (is_t5(sc)) {
|
||||
r = t4_read_reg(sc, A_SGE_EGRESS_QUEUES_PER_PAGE_PF);
|
||||
r >>= S_QUEUESPERPAGEPF0 +
|
||||
(S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * sc->pf;
|
||||
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_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);
|
||||
}
|
||||
@ -549,7 +638,7 @@ mtu_to_bufsize(int mtu)
|
||||
|
||||
/* large enough for a frame even when VLAN extraction is disabled */
|
||||
bufsize = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + mtu;
|
||||
bufsize = roundup(bufsize + fl_pktshift, fl_pad);
|
||||
bufsize = roundup2(bufsize + fl_pktshift, fl_pad);
|
||||
|
||||
return (bufsize);
|
||||
}
|
||||
@ -1487,7 +1576,7 @@ init_iq(struct sge_iq *iq, struct adapter *sc, int tmr_idx, int pktc_idx,
|
||||
iq->intr_params |= F_QINTR_CNT_EN;
|
||||
iq->intr_pktc_idx = pktc_idx;
|
||||
}
|
||||
iq->qsize = roundup(qsize, 16); /* See FW_IQ_CMD/iqsize */
|
||||
iq->qsize = roundup2(qsize, 16); /* See FW_IQ_CMD/iqsize */
|
||||
iq->esize = max(esize, 16); /* See FW_IQ_CMD/iqesize */
|
||||
}
|
||||
|
||||
@ -1661,7 +1750,7 @@ alloc_iq_fl(struct port_info *pi, struct sge_iq *iq, struct sge_fl *fl,
|
||||
return (rc);
|
||||
}
|
||||
fl->needed = fl->cap;
|
||||
fl->lowat = roundup(sc->sge.fl_starve_threshold, 8);
|
||||
fl->lowat = roundup2(sc->sge.fl_starve_threshold, 8);
|
||||
|
||||
c.iqns_to_fl0congen |=
|
||||
htobe32(V_FW_IQ_CMD_FL0HOSTFCMODE(X_HOSTFCMODE_NONE) |
|
||||
@ -2164,6 +2253,7 @@ alloc_eq(struct adapter *sc, struct port_info *pi, struct sge_eq *eq)
|
||||
eq->spg = (void *)&eq->desc[eq->cap];
|
||||
eq->avail = eq->cap - 1; /* one less to avoid cidx = pidx */
|
||||
eq->pidx = eq->cidx = 0;
|
||||
eq->doorbells = sc->doorbells;
|
||||
|
||||
switch (eq->flags & EQ_TYPEMASK) {
|
||||
case EQ_CTRL:
|
||||
@ -2192,6 +2282,25 @@ alloc_eq(struct adapter *sc, struct port_info *pi, struct sge_eq *eq)
|
||||
|
||||
eq->tx_callout.c_cpu = eq->cntxt_id % mp_ncpus;
|
||||
|
||||
if (isset(&eq->doorbells, DOORBELL_UDB) ||
|
||||
isset(&eq->doorbells, DOORBELL_UDBWC) ||
|
||||
isset(&eq->doorbells, DOORBELL_WRWC)) {
|
||||
uint32_t s_qpp = sc->sge.s_qpp;
|
||||
uint32_t mask = (1 << s_qpp) - 1;
|
||||
volatile uint8_t *udb;
|
||||
|
||||
udb = sc->udbs_base + UDBS_DB_OFFSET;
|
||||
udb += (eq->cntxt_id >> s_qpp) << PAGE_SHIFT; /* pg offset */
|
||||
eq->udb_qid = eq->cntxt_id & mask; /* id in page */
|
||||
if (eq->udb_qid > PAGE_SIZE / UDBS_SEG_SIZE)
|
||||
clrbit(&eq->doorbells, DOORBELL_WRWC);
|
||||
else {
|
||||
udb += eq->udb_qid << UDBS_SEG_SHIFT; /* seg offset */
|
||||
eq->udb_qid = 0;
|
||||
}
|
||||
eq->udb = (volatile void *)udb;
|
||||
}
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
@ -2437,6 +2546,7 @@ static inline void
|
||||
ring_fl_db(struct adapter *sc, struct sge_fl *fl)
|
||||
{
|
||||
int ndesc = fl->pending / 8;
|
||||
uint32_t v;
|
||||
|
||||
if (FL_HW_IDX(fl->pidx) == FL_HW_IDX(fl->cidx))
|
||||
ndesc--; /* hold back one credit */
|
||||
@ -2444,10 +2554,13 @@ ring_fl_db(struct adapter *sc, struct sge_fl *fl)
|
||||
if (ndesc <= 0)
|
||||
return; /* nothing to do */
|
||||
|
||||
v = F_DBPRIO | V_QID(fl->cntxt_id) | V_PIDX(ndesc);
|
||||
if (is_t5(sc))
|
||||
v |= F_DBTYPE;
|
||||
|
||||
wmb();
|
||||
|
||||
t4_write_reg(sc, MYPF_REG(A_SGE_PF_KDOORBELL), F_DBPRIO |
|
||||
V_QID(fl->cntxt_id) | V_PIDX(ndesc));
|
||||
t4_write_reg(sc, MYPF_REG(A_SGE_PF_KDOORBELL), v);
|
||||
fl->pending -= ndesc * 8;
|
||||
}
|
||||
|
||||
@ -3312,10 +3425,53 @@ copy_to_txd(struct sge_eq *eq, caddr_t from, caddr_t *to, int len)
|
||||
static inline void
|
||||
ring_eq_db(struct adapter *sc, struct sge_eq *eq)
|
||||
{
|
||||
wmb();
|
||||
t4_write_reg(sc, MYPF_REG(A_SGE_PF_KDOORBELL),
|
||||
V_QID(eq->cntxt_id) | V_PIDX(eq->pending));
|
||||
u_int db, pending;
|
||||
|
||||
db = eq->doorbells;
|
||||
pending = eq->pending;
|
||||
if (pending > 1)
|
||||
clrbit(&db, DOORBELL_WRWC);
|
||||
eq->pending = 0;
|
||||
wmb();
|
||||
|
||||
switch (ffs(db) - 1) {
|
||||
case DOORBELL_UDB:
|
||||
*eq->udb = htole32(V_QID(eq->udb_qid) | V_PIDX(pending));
|
||||
return;
|
||||
|
||||
case DOORBELL_WRWC: {
|
||||
volatile uint64_t *dst, *src;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Queues whose 128B doorbell segment fits in the page do not
|
||||
* use relative qid (udb_qid is always 0). Only queues with
|
||||
* doorbell segments can do WRWC.
|
||||
*/
|
||||
KASSERT(eq->udb_qid == 0 && pending == 1,
|
||||
("%s: inappropriate doorbell (0x%x, %d, %d) for eq %p",
|
||||
__func__, eq->doorbells, pending, eq->pidx, eq));
|
||||
|
||||
dst = (volatile void *)((uintptr_t)eq->udb + UDBS_WR_OFFSET -
|
||||
UDBS_DB_OFFSET);
|
||||
i = eq->pidx ? eq->pidx - 1 : eq->cap - 1;
|
||||
src = (void *)&eq->desc[i];
|
||||
while (src != (void *)&eq->desc[i + 1])
|
||||
*dst++ = *src++;
|
||||
wmb();
|
||||
return;
|
||||
}
|
||||
|
||||
case DOORBELL_UDBWC:
|
||||
*eq->udb = htole32(V_QID(eq->udb_qid) | V_PIDX(pending));
|
||||
wmb();
|
||||
return;
|
||||
|
||||
case DOORBELL_KDB:
|
||||
t4_write_reg(sc, MYPF_REG(A_SGE_PF_KDOORBELL),
|
||||
V_QID(eq->cntxt_id) | V_PIDX(pending));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -241,8 +241,11 @@ calc_opt2a(struct socket *so, struct toepcb *toep)
|
||||
opt2 |= F_CCTRL_ECN;
|
||||
|
||||
opt2 |= V_TX_QUEUE(sc->params.tp.tx_modq[pi->tx_chan]);
|
||||
opt2 |= F_RX_COALESCE_VALID | V_RX_COALESCE(M_RX_COALESCE);
|
||||
opt2 |= F_RSS_QUEUE_VALID | V_RSS_QUEUE(toep->ofld_rxq->iq.abs_id);
|
||||
if (is_t4(sc))
|
||||
opt2 |= F_RX_COALESCE_VALID | V_RX_COALESCE(M_RX_COALESCE);
|
||||
else
|
||||
opt2 |= F_T5_OPT_2_VALID | V_RX_COALESCE(M_RX_COALESCE);
|
||||
|
||||
#ifdef USE_DDP_RX_FLOW_CONTROL
|
||||
if (toep->ulp_mode == ULP_MODE_TCPDDP)
|
||||
@ -266,6 +269,24 @@ t4_init_connect_cpl_handlers(struct adapter *sc)
|
||||
goto failed; \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
act_open_cpl_size(struct adapter *sc, int isipv6)
|
||||
{
|
||||
static const int sz_t4[] = {
|
||||
sizeof (struct cpl_act_open_req),
|
||||
sizeof (struct cpl_act_open_req6)
|
||||
};
|
||||
static const int sz_t5[] = {
|
||||
sizeof (struct cpl_t5_act_open_req),
|
||||
sizeof (struct cpl_t5_act_open_req6)
|
||||
};
|
||||
|
||||
if (is_t4(sc))
|
||||
return (sz_t4[!!isipv6]);
|
||||
else
|
||||
return (sz_t5[!!isipv6]);
|
||||
}
|
||||
|
||||
/*
|
||||
* active open (soconnect).
|
||||
*
|
||||
@ -320,8 +341,7 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
|
||||
DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
|
||||
|
||||
isipv6 = nam->sa_family == AF_INET6;
|
||||
wr = alloc_wrqe(isipv6 ? sizeof(struct cpl_act_open_req6) :
|
||||
sizeof(struct cpl_act_open_req), toep->ctrlq);
|
||||
wr = alloc_wrqe(act_open_cpl_size(sc, isipv6), toep->ctrlq);
|
||||
if (wr == NULL)
|
||||
DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
|
||||
|
||||
@ -373,8 +393,17 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
|
||||
cpl->peer_ip_lo = *(uint64_t *)&inp->in6p_faddr.s6_addr[8];
|
||||
cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale,
|
||||
toep->rx_credits, toep->ulp_mode);
|
||||
cpl->params = select_ntuple(pi, toep->l2te, sc->filter_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);
|
||||
|
||||
@ -385,8 +414,17 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
|
||||
&cpl->peer_ip, &cpl->peer_port);
|
||||
cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale,
|
||||
toep->rx_credits, toep->ulp_mode);
|
||||
cpl->params = select_ntuple(pi, toep->l2te, sc->filter_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__,
|
||||
|
@ -88,7 +88,7 @@ send_flowc_wr(struct toepcb *toep, struct flowc_tx_params *ftxp)
|
||||
|
||||
flowclen = sizeof(*flowc) + nparams * sizeof(struct fw_flowc_mnemval);
|
||||
|
||||
wr = alloc_wrqe(roundup(flowclen, 16), toep->ofld_txq);
|
||||
wr = alloc_wrqe(roundup2(flowclen, 16), toep->ofld_txq);
|
||||
if (wr == NULL) {
|
||||
/* XXX */
|
||||
panic("%s: allocation failure.", __func__);
|
||||
@ -632,7 +632,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep)
|
||||
|
||||
/* Immediate data tx */
|
||||
|
||||
wr = alloc_wrqe(roundup(sizeof(*txwr) + plen, 16),
|
||||
wr = alloc_wrqe(roundup2(sizeof(*txwr) + plen, 16),
|
||||
toep->ofld_txq);
|
||||
if (wr == NULL) {
|
||||
/* XXX: how will we recover from this? */
|
||||
@ -651,7 +651,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep)
|
||||
|
||||
wr_len = sizeof(*txwr) + sizeof(struct ulptx_sgl) +
|
||||
((3 * (nsegs - 1)) / 2 + ((nsegs - 1) & 1)) * 8;
|
||||
wr = alloc_wrqe(roundup(wr_len, 16), toep->ofld_txq);
|
||||
wr = alloc_wrqe(roundup2(wr_len, 16), toep->ofld_txq);
|
||||
if (wr == NULL) {
|
||||
/* XXX: how will we recover from this? */
|
||||
toep->flags |= TPF_TX_SUSPENDED;
|
||||
|
@ -358,8 +358,8 @@ mk_update_tcb_for_ddp(struct adapter *sc, struct toepcb *toep, int db_idx,
|
||||
* The ULPTX master commands that follow must all end at 16B boundaries
|
||||
* too so we round up the size to 16.
|
||||
*/
|
||||
len = sizeof(*wrh) + 3 * roundup(LEN__SET_TCB_FIELD_ULP, 16) +
|
||||
roundup(LEN__RX_DATA_ACK_ULP, 16);
|
||||
len = sizeof(*wrh) + 3 * roundup2(LEN__SET_TCB_FIELD_ULP, 16) +
|
||||
roundup2(LEN__RX_DATA_ACK_ULP, 16);
|
||||
|
||||
wr = alloc_wrqe(len, toep->ctrlq);
|
||||
if (wr == NULL)
|
||||
@ -755,7 +755,7 @@ write_page_pods(struct adapter *sc, struct toepcb *toep, struct ddp_buffer *db)
|
||||
/* How many page pods are we writing in this cycle */
|
||||
n = min(db->nppods - i, NUM_ULP_TX_SC_IMM_PPODS);
|
||||
chunk = PPOD_SZ(n);
|
||||
len = roundup(sizeof(*ulpmc) + sizeof(*ulpsc) + chunk, 16);
|
||||
len = roundup2(sizeof(*ulpmc) + sizeof(*ulpsc) + chunk, 16);
|
||||
|
||||
wr = alloc_wrqe(len, toep->ctrlq);
|
||||
if (wr == NULL)
|
||||
@ -764,7 +764,7 @@ write_page_pods(struct adapter *sc, struct toepcb *toep, struct ddp_buffer *db)
|
||||
|
||||
INIT_ULPTX_WR(ulpmc, len, 0, 0);
|
||||
ulpmc->cmd = htobe32(V_ULPTX_CMD(ULP_TX_MEM_WRITE) |
|
||||
F_ULP_MEMIO_ORDER);
|
||||
is_t4(sc) ? F_ULP_MEMIO_ORDER : F_T5_ULP_MEMIO_IMM);
|
||||
ulpmc->dlen = htobe32(V_ULP_MEMIO_DATA_LEN(chunk / 32));
|
||||
ulpmc->len16 = htobe32(howmany(len - sizeof(ulpmc->wr), 16));
|
||||
ulpmc->lock_addr = htobe32(V_ULP_MEMIO_ADDR(ppod_addr >> 5));
|
||||
|
@ -360,13 +360,13 @@ send_reset_synqe(struct toedev *tod, struct synq_entry *synqe)
|
||||
/* The wrqe will have two WRs - a flowc followed by an abort_req */
|
||||
flowclen = sizeof(*flowc) + nparams * sizeof(struct fw_flowc_mnemval);
|
||||
|
||||
wr = alloc_wrqe(roundup(flowclen, EQ_ESIZE) + sizeof(*req), ofld_txq);
|
||||
wr = alloc_wrqe(roundup2(flowclen, EQ_ESIZE) + sizeof(*req), ofld_txq);
|
||||
if (wr == NULL) {
|
||||
/* XXX */
|
||||
panic("%s: allocation failure.", __func__);
|
||||
}
|
||||
flowc = wrtod(wr);
|
||||
req = (void *)((caddr_t)flowc + roundup(flowclen, EQ_ESIZE));
|
||||
req = (void *)((caddr_t)flowc + roundup2(flowclen, EQ_ESIZE));
|
||||
|
||||
/* First the flowc ... */
|
||||
memset(flowc, 0, wr->wr_len);
|
||||
@ -944,7 +944,7 @@ get_qids_from_mbuf(struct mbuf *m, int *txqid, int *rxqid)
|
||||
static struct synq_entry *
|
||||
mbuf_to_synqe(struct mbuf *m)
|
||||
{
|
||||
int len = roundup(sizeof (struct synq_entry), 8);
|
||||
int len = roundup2(sizeof (struct synq_entry), 8);
|
||||
int tspace = M_TRAILINGSPACE(m);
|
||||
struct synq_entry *synqe = NULL;
|
||||
|
||||
@ -1006,8 +1006,11 @@ calc_opt2p(struct adapter *sc, struct port_info *pi, int rxqid,
|
||||
opt2 |= F_CCTRL_ECN;
|
||||
|
||||
opt2 |= V_TX_QUEUE(sc->params.tp.tx_modq[pi->tx_chan]);
|
||||
opt2 |= F_RX_COALESCE_VALID | V_RX_COALESCE(M_RX_COALESCE);
|
||||
opt2 |= F_RSS_QUEUE_VALID | V_RSS_QUEUE(ofld_rxq->iq.abs_id);
|
||||
if (is_t4(sc))
|
||||
opt2 |= F_RX_COALESCE_VALID | V_RX_COALESCE(M_RX_COALESCE);
|
||||
else
|
||||
opt2 |= F_T5_OPT_2_VALID | V_RX_COALESCE(M_RX_COALESCE);
|
||||
|
||||
#ifdef USE_DDP_RX_FLOW_CONTROL
|
||||
if (ulp_mode == ULP_MODE_TCPDDP)
|
||||
|
@ -512,7 +512,7 @@ calc_opt0(struct socket *so, struct port_info *pi, struct l2t_entry *e,
|
||||
#define VLAN_NONE 0xfff
|
||||
#define FILTER_SEL_VLAN_NONE 0xffff
|
||||
|
||||
uint32_t
|
||||
uint64_t
|
||||
select_ntuple(struct port_info *pi, struct l2t_entry *e, uint32_t filter_mode)
|
||||
{
|
||||
uint16_t viid = pi->viid;
|
||||
@ -535,7 +535,10 @@ select_ntuple(struct port_info *pi, struct l2t_entry *e, uint32_t filter_mode)
|
||||
ntuple |= IPPROTO_TCP << FILTER_SEL_WIDTH_VLD_TAG_P_FC;
|
||||
}
|
||||
|
||||
return (htobe32(ntuple));
|
||||
if (is_t4(pi->adapter))
|
||||
return (htobe32(ntuple));
|
||||
else
|
||||
return (htobe64(V_FILTER_TUPLE(ntuple)));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -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);
|
||||
uint32_t select_ntuple(struct port_info *, struct l2t_entry *, uint32_t);
|
||||
uint64_t select_ntuple(struct port_info *, struct l2t_entry *, uint32_t);
|
||||
void set_tcpddp_ulp_mode(struct toepcb *);
|
||||
int negative_advice(int);
|
||||
struct clip_entry *hold_lip(struct tom_data *, struct in6_addr *);
|
||||
|
@ -3,7 +3,8 @@
|
||||
#
|
||||
|
||||
SUBDIR = if_cxgbe
|
||||
SUBDIR+= firmware
|
||||
SUBDIR+= t4_firmware
|
||||
#SUBDIR+= t5_firmware
|
||||
SUBDIR+= ${_tom}
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
|
||||
|
@ -77,6 +77,7 @@ struct field_desc {
|
||||
|
||||
#include "reg_defs_t4.c"
|
||||
#include "reg_defs_t4vf.c"
|
||||
#include "reg_defs_t5.c"
|
||||
|
||||
static void
|
||||
usage(FILE *fp)
|
||||
@ -354,34 +355,75 @@ dump_regs_t4vf(int argc, const char *argv[], const uint32_t *regs)
|
||||
ARRAY_SIZE(t4vf_mod));
|
||||
}
|
||||
|
||||
#define T5_MODREGS(name) { #name, t5_##name##_regs }
|
||||
static int
|
||||
dump_regs_t5(int argc, const char *argv[], const uint32_t *regs)
|
||||
{
|
||||
static struct mod_regs t5_mod[] = {
|
||||
T5_MODREGS(sge),
|
||||
{ "pci", t5_pcie_regs },
|
||||
T5_MODREGS(dbg),
|
||||
{ "mc0", t5_mc_0_regs },
|
||||
{ "mc1", t5_mc_1_regs },
|
||||
T5_MODREGS(ma),
|
||||
{ "edc0", t5_edc_t50_regs },
|
||||
{ "edc1", t5_edc_t51_regs },
|
||||
T5_MODREGS(cim),
|
||||
T5_MODREGS(tp),
|
||||
{ "ulprx", t5_ulp_rx_regs },
|
||||
{ "ulptx", t5_ulp_tx_regs },
|
||||
{ "pmrx", t5_pm_rx_regs },
|
||||
{ "pmtx", t5_pm_tx_regs },
|
||||
T5_MODREGS(mps),
|
||||
{ "cplsw", t5_cpl_switch_regs },
|
||||
T5_MODREGS(smb),
|
||||
{ "i2c", t5_i2cm_regs },
|
||||
T5_MODREGS(mi),
|
||||
T5_MODREGS(uart),
|
||||
T5_MODREGS(pmu),
|
||||
T5_MODREGS(sf),
|
||||
T5_MODREGS(pl),
|
||||
T5_MODREGS(le),
|
||||
T5_MODREGS(ncsi),
|
||||
T5_MODREGS(mac),
|
||||
{ "hma", t5_hma_t5_regs }
|
||||
};
|
||||
|
||||
return dump_regs_table(argc, argv, regs, t5_mod, ARRAY_SIZE(t5_mod));
|
||||
}
|
||||
#undef T5_MODREGS
|
||||
|
||||
static int
|
||||
dump_regs(int argc, const char *argv[])
|
||||
{
|
||||
int vers, revision, is_pcie, rc;
|
||||
int vers, revision, rc;
|
||||
struct t4_regdump regs;
|
||||
uint32_t len;
|
||||
|
||||
regs.data = calloc(1, T4_REGDUMP_SIZE);
|
||||
len = max(T4_REGDUMP_SIZE, T5_REGDUMP_SIZE);
|
||||
regs.data = calloc(1, len);
|
||||
if (regs.data == NULL) {
|
||||
warnc(ENOMEM, "regdump");
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
regs.len = T4_REGDUMP_SIZE;
|
||||
regs.len = len;
|
||||
rc = doit(CHELSIO_T4_REGDUMP, ®s);
|
||||
if (rc != 0)
|
||||
return (rc);
|
||||
|
||||
vers = get_card_vers(regs.version);
|
||||
revision = (regs.version >> 10) & 0x3f;
|
||||
is_pcie = (regs.version & 0x80000000) != 0;
|
||||
|
||||
if (vers == 4) {
|
||||
if (revision == 0x3f)
|
||||
rc = dump_regs_t4vf(argc, argv, regs.data);
|
||||
else
|
||||
rc = dump_regs_t4(argc, argv, regs.data);
|
||||
} else {
|
||||
warnx("%s (type %d, rev %d) is not a T4 card.",
|
||||
} else if (vers == 5)
|
||||
rc = dump_regs_t5(argc, argv, regs.data);
|
||||
else {
|
||||
warnx("%s (type %d, rev %d) is not a known card.",
|
||||
nexus, vers, revision);
|
||||
return (ENOTSUP);
|
||||
}
|
||||
|
65039
tools/tools/cxgbetool/reg_defs_t5.c
Normal file
65039
tools/tools/cxgbetool/reg_defs_t5.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user