diff options
author | kmacy <kmacy@FreeBSD.org> | 2007-09-09 01:28:03 +0000 |
---|---|---|
committer | kmacy <kmacy@FreeBSD.org> | 2007-09-09 01:28:03 +0000 |
commit | 36e50690beafcb223cb1b34751cd4f28ad095394 (patch) | |
tree | 4cef61463d4eb54cc5156a6cc7cf54ed763f4010 /sys/dev/cxgb/common | |
parent | 8fc160dac01fee84ee885f1358e4dffb7e772df5 (diff) | |
download | FreeBSD-src-36e50690beafcb223cb1b34751cd4f28ad095394.zip FreeBSD-src-36e50690beafcb223cb1b34751cd4f28ad095394.tar.gz |
- fix qset to port binding as a proper fix for the problems encountered on the 4-port
- fix the use after free seen when sending packets small enough to fit as an immediate
and bpf peers are present
- update to firmware rev 4.7 along with various small vendor fixes
Supported by: Chelsio
Approved by: re (blanket)
MFC after: 3 days
Diffstat (limited to 'sys/dev/cxgb/common')
-rw-r--r-- | sys/dev/cxgb/common/cxgb_common.h | 5 | ||||
-rw-r--r-- | sys/dev/cxgb/common/cxgb_ctl_defs.h | 10 | ||||
-rw-r--r-- | sys/dev/cxgb/common/cxgb_sge_defs.h | 4 | ||||
-rw-r--r-- | sys/dev/cxgb/common/cxgb_t3_hw.c | 170 | ||||
-rw-r--r-- | sys/dev/cxgb/common/cxgb_vsc7323.c | 34 | ||||
-rw-r--r-- | sys/dev/cxgb/common/cxgb_xgmac.c | 15 |
6 files changed, 175 insertions, 63 deletions
diff --git a/sys/dev/cxgb/common/cxgb_common.h b/sys/dev/cxgb/common/cxgb_common.h index 9d75102..0b4b6aa 100644 --- a/sys/dev/cxgb/common/cxgb_common.h +++ b/sys/dev/cxgb/common/cxgb_common.h @@ -40,6 +40,7 @@ $FreeBSD$ enum { MAX_FRAME_SIZE = 10240, /* max MAC frame size, includes header + FCS */ EEPROMSIZE = 8192, /* Serial EEPROM size */ + SERNUM_LEN = 16, /* Serial # length */ RSS_TABLE_SIZE = 64, /* size of RSS lookup and mapping tables */ TCB_SIZE = 128, /* TCB size */ NMTUS = 16, /* size of MTU table */ @@ -98,7 +99,7 @@ enum { enum { FW_VERSION_MAJOR = 4, - FW_VERSION_MINOR = 5, + FW_VERSION_MINOR = 7, FW_VERSION_MICRO = 0 }; @@ -348,6 +349,7 @@ struct vpd_params { unsigned int uclk; unsigned int mdc; unsigned int mem_timing; + u8 sn[SERNUM_LEN + 1]; u8 eth_base[6]; u8 port_type[MAX_NPORTS]; unsigned short xauicfg[2]; @@ -474,6 +476,7 @@ struct cmac { u64 rx_mcnt; unsigned int toggle_cnt; unsigned int txen; + u64 rx_pause; struct mac_stats stats; }; diff --git a/sys/dev/cxgb/common/cxgb_ctl_defs.h b/sys/dev/cxgb/common/cxgb_ctl_defs.h index e96f497..3a2eb4f 100644 --- a/sys/dev/cxgb/common/cxgb_ctl_defs.h +++ b/sys/dev/cxgb/common/cxgb_ctl_defs.h @@ -35,13 +35,13 @@ enum { RDMA_CTRL_QP_SETUP, RDMA_GET_MEM, - FAILOVER, - FAILOVER_DONE, - FAILOVER_CLEAR, + FAILOVER = 30, + FAILOVER_DONE = 31, + FAILOVER_CLEAR = 32, - GET_CPUIDX_OF_QSET, + GET_CPUIDX_OF_QSET = 40, - GET_RX_PAGE_INFO, + GET_RX_PAGE_INFO = 50, }; /* diff --git a/sys/dev/cxgb/common/cxgb_sge_defs.h b/sys/dev/cxgb/common/cxgb_sge_defs.h index d850103..2aae7f8 100644 --- a/sys/dev/cxgb/common/cxgb_sge_defs.h +++ b/sys/dev/cxgb/common/cxgb_sge_defs.h @@ -136,6 +136,10 @@ $FreeBSD$ #define V_CQ_GEN(x) ((x) << S_CQ_GEN) #define F_CQ_GEN V_CQ_GEN(1U) +#define S_CQ_ERR 30 +#define V_CQ_ERR(x) ((x) << S_CQ_ERR) +#define F_CQ_ERR V_CQ_ERR(1U) + #define S_CQ_OVERFLOW_MODE 31 #define V_CQ_OVERFLOW_MODE(x) ((x) << S_CQ_OVERFLOW_MODE) #define F_CQ_OVERFLOW_MODE V_CQ_OVERFLOW_MODE(1U) diff --git a/sys/dev/cxgb/common/cxgb_t3_hw.c b/sys/dev/cxgb/common/cxgb_t3_hw.c index 69e0e83..ea097b3 100644 --- a/sys/dev/cxgb/common/cxgb_t3_hw.c +++ b/sys/dev/cxgb/common/cxgb_t3_hw.c @@ -28,7 +28,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +_FBSDID("$FreeBSD$"); #ifdef CONFIG_DEFINED @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #undef msleep #define msleep t3_os_sleep - /** * t3_wait_op_done_val - wait until an operation is completed * @adapter: the adapter performing the operation @@ -515,7 +514,7 @@ struct t3_vpd { u8 vpdr_len[2]; VPD_ENTRY(pn, 16); /* part number */ VPD_ENTRY(ec, 16); /* EC level */ - VPD_ENTRY(sn, 16); /* serial number */ + VPD_ENTRY(sn, SERNUM_LEN); /* serial number */ VPD_ENTRY(na, 12); /* MAC address base */ VPD_ENTRY(cclk, 6); /* core clock */ VPD_ENTRY(mclk, 6); /* mem clock */ @@ -658,6 +657,7 @@ static int get_vpd_params(adapter_t *adapter, struct vpd_params *p) p->uclk = simple_strtoul(vpd.uclk_data, NULL, 10); p->mdc = simple_strtoul(vpd.mdc_data, NULL, 10); p->mem_timing = simple_strtoul(vpd.mt_data, NULL, 10); + memcpy(p->sn, vpd.sn_data, SERNUM_LEN); /* Old eeproms didn't have port information */ if (adapter->params.rev == 0 && !vpd.port0_data[0]) { @@ -908,7 +908,7 @@ int t3_check_tpsram_version(adapter_t *adapter) if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR) return 0; - CH_ERR(adapter, "found wrong TP version (%u.%u), " + CH_WARN(adapter, "found wrong TP version (%u.%u), " "driver needs version %d.%d\n", major, minor, TP_VERSION_MAJOR, TP_VERSION_MINOR); return -EINVAL; @@ -984,9 +984,9 @@ int t3_check_fw_version(adapter_t *adapter) minor == FW_VERSION_MINOR) return 0; - CH_ERR(adapter, "found wrong FW version (%u.%u), " - "driver needs version %d.%d\n", major, minor, - FW_VERSION_MAJOR, FW_VERSION_MINOR); + CH_WARN(adapter, "found wrong FW version (%u.%u), " + "driver needs version %d.%d\n", major, minor, + FW_VERSION_MAJOR, FW_VERSION_MINOR); return -EINVAL; } @@ -1072,7 +1072,6 @@ out: /** * t3_cim_ctl_blk_read - read a block from CIM control region - * * @adap: the adapter * @addr: the start address within the CIM control region * @n: number of words to read @@ -1348,6 +1347,10 @@ static void pcie_intr_handler(adapter_t *adapter) { 0 } }; + if (t3_read_reg(adapter, A_PCIE_INT_CAUSE) & F_PEXERR) + CH_ALERT(adapter, "PEX error code 0x%x\n", + t3_read_reg(adapter, A_PCIE_PEX_ERR)); + if (t3_handle_intr_status(adapter, A_PCIE_INT_CAUSE, PCIE_INTR_MASK, pcie_intr_info, adapter->irq_stats)) t3_fatal_err(adapter); @@ -1646,8 +1649,13 @@ int t3_phy_intr_handler(adapter_t *adapter) return 0; } -/* - * T3 slow path (non-data) interrupt handler. +/** + * t3_slow_intr_handler - control path interrupt handler + * @adapter: the adapter + * + * T3 interrupt handler for non-data interrupt events, e.g., errors. + * The designation 'slow' is because it involves register reads, while + * data interrupts typically don't involve any MMIOs. */ int t3_slow_intr_handler(adapter_t *adapter) { @@ -1803,6 +1811,8 @@ void t3_intr_clear(adapter_t *adapter) for (i = 0; i < ARRAY_SIZE(cause_reg_addr); ++i) t3_write_reg(adapter, cause_reg_addr[i], 0xffffffff); + if (is_pcie(adapter)) + t3_write_reg(adapter, A_PCIE_PEX_ERR, 0xffffffff); t3_write_reg(adapter, A_PL_INT_CAUSE0, 0xffffffff); (void) t3_read_reg(adapter, A_PL_INT_CAUSE0); /* flush */ } @@ -1855,6 +1865,8 @@ void t3_port_intr_clear(adapter_t *adapter, int idx) pi->phy.ops->intr_clear(&pi->phy); } +#define SG_CONTEXT_CMD_ATTEMPTS 100 + /** * t3_sge_write_context - write an SGE context * @adapter: the adapter @@ -1874,7 +1886,7 @@ static int t3_sge_write_context(adapter_t *adapter, unsigned int id, t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id)); return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); + 0, SG_CONTEXT_CMD_ATTEMPTS, 1); } /** @@ -2030,7 +2042,8 @@ int t3_sge_init_cqcntxt(adapter_t *adapter, unsigned int id, u64 base_addr, base_addr >>= 32; t3_write_reg(adapter, A_SG_CONTEXT_DATA2, V_CQ_BASE_HI((u32)base_addr) | V_CQ_RSPQ(rspq) | - V_CQ_GEN(1) | V_CQ_OVERFLOW_MODE(ovfl_mode)); + V_CQ_GEN(1) | V_CQ_OVERFLOW_MODE(ovfl_mode) | + V_CQ_ERR(ovfl_mode)); t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_CQ_CREDITS(credits) | V_CQ_CREDIT_THRES(credit_thres)); return t3_sge_write_context(adapter, id, F_CQ); @@ -2058,7 +2071,7 @@ int t3_sge_enable_ecntxt(adapter_t *adapter, unsigned int id, int enable) t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(1) | F_EGRESS | V_CONTEXT(id)); return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); + 0, SG_CONTEXT_CMD_ATTEMPTS, 1); } /** @@ -2082,7 +2095,7 @@ int t3_sge_disable_fl(adapter_t *adapter, unsigned int id) t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(1) | F_FREELIST | V_CONTEXT(id)); return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); + 0, SG_CONTEXT_CMD_ATTEMPTS, 1); } /** @@ -2106,7 +2119,7 @@ int t3_sge_disable_rspcntxt(adapter_t *adapter, unsigned int id) t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(1) | F_RESPONSEQ | V_CONTEXT(id)); return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); + 0, SG_CONTEXT_CMD_ATTEMPTS, 1); } /** @@ -2130,7 +2143,7 @@ int t3_sge_disable_cqcntxt(adapter_t *adapter, unsigned int id) t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(1) | F_CQ | V_CONTEXT(id)); return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); + 0, SG_CONTEXT_CMD_ATTEMPTS, 1); } /** @@ -2138,10 +2151,14 @@ int t3_sge_disable_cqcntxt(adapter_t *adapter, unsigned int id) * @adapter: the adapter * @id: the context id * @op: the operation to perform + * @credits: credits to return to the CQ * * Perform the selected operation on an SGE completion queue context. * The caller is responsible for ensuring only one context operation * occurs at a time. + * + * For most operations the function returns the current HW position in + * the completion queue. */ int t3_sge_cqcntxt_op(adapter_t *adapter, unsigned int id, unsigned int op, unsigned int credits) @@ -2155,7 +2172,7 @@ int t3_sge_cqcntxt_op(adapter_t *adapter, unsigned int id, unsigned int op, t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(op) | V_CONTEXT(id) | F_CQ); if (t3_wait_op_done_val(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1, &val)) + 0, SG_CONTEXT_CMD_ATTEMPTS, 1, &val)) return -EIO; if (op >= 2 && op < 7) { @@ -2165,7 +2182,8 @@ int t3_sge_cqcntxt_op(adapter_t *adapter, unsigned int id, unsigned int op, t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(0) | F_CQ | V_CONTEXT(id)); if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, - F_CONTEXT_CMD_BUSY, 0, 5, 1)) + F_CONTEXT_CMD_BUSY, 0, + SG_CONTEXT_CMD_ATTEMPTS, 1)) return -EIO; return G_CQ_INDEX(t3_read_reg(adapter, A_SG_CONTEXT_DATA0)); } @@ -2191,7 +2209,7 @@ static int t3_sge_read_context(unsigned int type, adapter_t *adapter, t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(0) | type | V_CONTEXT(id)); if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 0, - 5, 1)) + SG_CONTEXT_CMD_ATTEMPTS, 1)) return -EIO; data[0] = t3_read_reg(adapter, A_SG_CONTEXT_DATA0); data[1] = t3_read_reg(adapter, A_SG_CONTEXT_DATA1); @@ -2354,6 +2372,15 @@ void t3_tp_set_offload_mode(adapter_t *adap, int enable) V_NICMODE(!enable)); } +/** + * tp_wr_bits_indirect - set/clear bits in an indirect TP register + * @adap: the adapter + * @addr: the indirect TP register address + * @mask: specifies the field within the register to modify + * @val: new value for the field + * + * Sets a field of an indirect TP register to the given value. + */ static void tp_wr_bits_indirect(adapter_t *adap, unsigned int addr, unsigned int mask, unsigned int val) { @@ -2397,7 +2424,7 @@ static inline unsigned int pm_num_pages(unsigned int mem_size, t3_write_reg((adap), A_ ## reg, (start)); \ start += size -/* +/** * partition_mem - partition memory and configure TP memory settings * @adap: the adapter * @p: the TP parameters @@ -2646,8 +2673,12 @@ static void __devinit init_mtus(unsigned short mtus[]) mtus[15] = 9600; } -/* - * Initial congestion control parameters. +/** + * init_cong_ctrl - initialize congestion control parameters + * @a: the alpha values for congestion control + * @b: the beta values for congestion control + * + * Initialize the congestion control parameters. */ static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b) { @@ -2693,7 +2724,7 @@ static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b) * t3_load_mtus - write the MTU and congestion control HW tables * @adap: the adapter * @mtus: the unrestricted values for the MTU table - * @alphs: the values for the congestion control alpha parameter + * @alpha: the values for the congestion control alpha parameter * @beta: the values for the congestion control beta parameter * @mtu_cap: the maximum permitted effective MTU * @@ -2860,7 +2891,7 @@ static void ulp_config(adapter_t *adap, const struct tp_params *p) int t3_set_proto_sram(adapter_t *adap, const u8 *data) { int i; - u32 *buf = (u32 *)(uintptr_t)data; + const u32 *buf = (const u32 *)data; for (i = 0; i < PROTO_SRAM_LINES; i++) { t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++)); @@ -2877,6 +2908,16 @@ int t3_set_proto_sram(adapter_t *adap, const u8 *data) } #endif +/** + * t3_config_trace_filter - configure one of the tracing filters + * @adapter: the adapter + * @tp: the desired trace filter parameters + * @filter_index: which filter to configure + * @invert: if set non-matching packets are traced instead of matching ones + * @enable: whether to enable or disable the filter + * + * Configures one of the tracing filters available in HW. + */ void t3_config_trace_filter(adapter_t *adapter, const struct trace_params *tp, int filter_index, int invert, int enable) { @@ -3022,6 +3063,13 @@ void t3_get_tx_sched(adapter_t *adap, unsigned int sched, unsigned int *kbps, } } +/** + * tp_init - configure TP + * @adap: the adapter + * @p: TP configuration parameters + * + * Initializes the TP HW module. + */ static int tp_init(adapter_t *adap, const struct tp_params *p) { int busy = 0; @@ -3043,6 +3091,13 @@ static int tp_init(adapter_t *adap, const struct tp_params *p) return busy; } +/** + * t3_mps_set_active_ports - configure port failover + * @adap: the adapter + * @port_mask: bitmap of active ports + * + * Sets the active ports according to the supplied bitmap. + */ int t3_mps_set_active_ports(adapter_t *adap, unsigned int port_mask) { if (port_mask & ~((1 << adap->params.nports) - 1)) @@ -3052,9 +3107,13 @@ int t3_mps_set_active_ports(adapter_t *adap, unsigned int port_mask) return 0; } -/* - * Perform the bits of HW initialization that are dependent on the Tx - * channels being used. +/** + * chan_init_hw - channel-dependent HW initialization + * @adap: the adapter + * @chan_map: bitmap of Tx channels being used + * + * Perform the bits of HW initialization that are dependent on the Tx + * channels being used. */ static void chan_init_hw(adapter_t *adap, unsigned int chan_map) { @@ -3068,6 +3127,11 @@ static void chan_init_hw(adapter_t *adap, unsigned int chan_map) F_TPTXPORT1EN | F_PORT1ACTIVE)); t3_write_reg(adap, A_PM1_TX_CFG, chan_map == 1 ? 0xffffffff : 0); + if (chan_map == 2) + t3_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP, + V_TX_MOD_QUEUE_REQ_MAP(0xff)); + t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE, (12 << 16) | 0xd9c8); + t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE, (13 << 16) | 0xfbea); } else { /* two channels */ t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN); t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB); @@ -3083,6 +3147,8 @@ static void chan_init_hw(adapter_t *adap, unsigned int chan_map) for (i = 0; i < 16; i++) t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE, (i << 16) | 0x1010); + t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE, (12 << 16) | 0xba98); + t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE, (13 << 16) | 0xfedc); } } @@ -3320,13 +3386,18 @@ static void config_pcie(adapter_t *adap) t3_set_reg_field(adap, A_PCIE_CFG, F_PCIE_CLIDECEN, F_PCIE_CLIDECEN); } -/* - * Initialize and configure T3 HW modules. This performs the - * initialization steps that need to be done once after a card is reset. - * MAC and PHY initialization is handled separarely whenever a port is enabled. +/** + * t3_init_hw - initialize and configure T3 HW modules + * @adapter: the adapter + * @fw_params: initial parameters to pass to firmware (optional) * - * fw_params are passed to FW and their value is platform dependent. Only the - * top 8 bits are available for use, the rest must be 0. + * Initialize and configure T3 HW modules. This performs the + * initialization steps that need to be done once after a card is reset. + * MAC and PHY initialization is handled separarely whenever a port is + * enabled. + * + * @fw_params are passed to FW and their value is platform dependent. + * Only the top 8 bits are available for use, the rest must be 0. */ int t3_init_hw(adapter_t *adapter, u32 fw_params) { @@ -3370,6 +3441,8 @@ int t3_init_hw(adapter_t *adapter, u32 fw_params) t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN); t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff); + t3_write_reg(adapter, A_PM1_RX_MODE, 0); + t3_write_reg(adapter, A_PM1_TX_MODE, 0); chan_init_hw(adapter, adapter->params.chan_map); t3_sge_init(adapter, &adapter->params.sge); @@ -3433,7 +3506,7 @@ static void __devinit get_pci_mode(adapter_t *adapter, struct pci_params *p) /** * init_link_config - initialize a link's SW state * @lc: structure holding the link state - * @ai: information about the current card + * @caps: link capabilities * * Initializes the SW state maintained for each link, including the link's * capabilities and default speed/duplex/flow-control/autonegotiation @@ -3508,6 +3581,15 @@ void mac_prep(struct cmac *mac, adapter_t *adapter, int index) } } +/** + * early_hw_init - HW initialization done at card detection time + * @adapter: the adapter + * @ai: contains information about the adapter type and properties + * + * Perfoms the part of HW initialization that is done early on when the + * driver first detecs the card. Most of the HW state is initialized + * lazily later on when a port or an offload function are first used. + */ void early_hw_init(adapter_t *adapter, const struct adapter_info *ai) { u32 val = V_PORTSPEED(is_10G(adapter) || adapter->params.nports > 2 ? @@ -3534,9 +3616,11 @@ void early_hw_init(adapter_t *adapter, const struct adapter_info *ai) (void) t3_read_reg(adapter, A_XGM_PORT_CFG); } -/* - * Reset the adapter. PCIe cards lose their config space during reset, PCI-X - * ones don't. +/** + * t3_reset_adapter - reset the adapter + * @adapter: the adapter + * + * Reset the adapter. */ static int t3_reset_adapter(adapter_t *adapter) { @@ -3567,10 +3651,14 @@ static int t3_reset_adapter(adapter_t *adapter) return 0; } -/* - * Initialize adapter SW state for the various HW modules, set initial values - * for some adapter tunables, take PHYs out of reset, and initialize the MDIO - * interface. +/** + * t3_prep_adapter - prepare SW and HW for operation + * @adapter: the adapter + * @ai: contains information about the adapter type and properties + * + * Initialize adapter SW state for the various HW modules, set initial + * values for some adapter tunables, take PHYs out of reset, and + * initialize the MDIO interface. */ int __devinit t3_prep_adapter(adapter_t *adapter, const struct adapter_info *ai, int reset) diff --git a/sys/dev/cxgb/common/cxgb_vsc7323.c b/sys/dev/cxgb/common/cxgb_vsc7323.c index 4efd24e..ded8261 100644 --- a/sys/dev/cxgb/common/cxgb_vsc7323.c +++ b/sys/dev/cxgb/common/cxgb_vsc7323.c @@ -43,6 +43,11 @@ enum { ELMR_DATA_LO = 2, ELMR_DATA_HI = 3, + ELMR_THRES0 = 0xe000, + ELMR_BW = 0xe00c, + ELMR_FIFO_SZ = 0xe00d, + ELMR_STATS = 0xf000, + ELMR_MDIO_ADDR = 10 }; @@ -74,7 +79,7 @@ static int elmr_write(adapter_t *adap, int addr, u32 val) int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n) { - int ret; + int i, ret; unsigned int v; const struct mdio_ops *mo = adapter_info(adap)->mdio_ops; @@ -83,9 +88,15 @@ int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n) ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start); if (ret) goto out; - ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v); - if (ret) - goto out; + + for (i = 0; i < 5; i++) { + ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v); + if (ret) + goto out; + if (v == 1) + break; + udelay(5); + } if (v != 1) { ret = -ETIMEDOUT; goto out; @@ -148,7 +159,7 @@ int t3_vsc7323_init(adapter_t *adap, int nports) (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i), ((ing_bot + ing_step) << 16) | ing_bot)) || (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i), - 0x6000a00)) || + 0x6000bc0)) || (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) || (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i), ((egr_bot + egr_step) << 16) | egr_bot)) || @@ -175,8 +186,13 @@ int t3_vsc7323_init(adapter_t *adap, int nports) (ret = elmr_write(adap, VSC_REG(1, i, 5), (i << 12) | 0x63)) || (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) || - (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21))) + (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)) || + (ret = elmr_write(adap, ELMR_THRES0 + i, 768))) return ret; + + if ((ret = elmr_write(adap, ELMR_BW, 7))) + return ret; + return ret; } @@ -269,6 +285,8 @@ int t3_vsc7323_disable(adapter_t *adap, int port, int which) #define NSTATS0 (0x1d - STATS0_START + 1) #define NSTATS1 (0x2a - STATS1_START + 1) +#define ELMR_STAT(port, reg) (ELMR_STATS + port * 0x40 + reg) + const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac) { int ret; @@ -276,11 +294,11 @@ const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac) u32 stats0[NSTATS0], stats1[NSTATS1]; ret = t3_elmr_blk_read(mac->adapter, - VSC_REG(4, mac->ext_port, STATS0_START), + ELMR_STAT(mac->ext_port, STATS0_START), stats0, NSTATS0); if (!ret) ret = t3_elmr_blk_read(mac->adapter, - VSC_REG(4, mac->ext_port, STATS1_START), + ELMR_STAT(mac->ext_port, STATS1_START), stats1, NSTATS1); if (ret) goto out; diff --git a/sys/dev/cxgb/common/cxgb_xgmac.c b/sys/dev/cxgb/common/cxgb_xgmac.c index f11b343..ca8801f 100644 --- a/sys/dev/cxgb/common/cxgb_xgmac.c +++ b/sys/dev/cxgb/common/cxgb_xgmac.c @@ -492,9 +492,11 @@ int t3_mac_enable(struct cmac *mac, int which) A_XGM_TX_SPI4_SOP_EOP_CNT + oft))); mac->rx_mcnt = s->rx_frames; + mac->rx_pause = s->rx_pause; mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_RX_SPI4_SOP_EOP_CNT + oft))); + mac->rx_ocnt = s->rx_fifo_ovfl; mac->txen = F_TXEN; mac->toggle_cnt = 0; } @@ -506,22 +508,21 @@ int t3_mac_enable(struct cmac *mac, int which) int t3_mac_disable(struct cmac *mac, int which) { adapter_t *adap = mac->adapter; - int val; if (mac->multiport) return t3_vsc7323_disable(adap, mac->ext_port, which); if (which & MAC_DIRECTION_TX) { - val = t3_read_reg(adap, A_MPS_CFG); t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); mac->txen = 0; } if (which & MAC_DIRECTION_RX) { + int val = F_MAC_RESET_; + t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, F_PCS_RESET_, 0); msleep(100); t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); - val = F_MAC_RESET_; if (is_10G(adap)) val |= F_PCS_RESET_; else if (uses_xaui(adap)) @@ -554,7 +555,7 @@ int t3b2_mac_watchdog_task(struct cmac *mac) tx_xcnt = 1; /* By default tx_xcnt is making progress*/ tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt*/ rx_xcnt = 1; /* By default rx_xcnt is making progress*/ - if (tx_mcnt == mac->tx_mcnt) { + if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) { tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_TX_SPI4_SOP_EOP_CNT + mac->offset))); @@ -571,10 +572,7 @@ int t3b2_mac_watchdog_task(struct cmac *mac) goto rxcheck; } - if (((tx_tcnt != mac->tx_tcnt) && - (tx_xcnt == 0) && (mac->tx_xcnt == 0)) || - ((mac->tx_mcnt == tx_mcnt) && - (tx_xcnt != 0) && (mac->tx_xcnt != 0))) { + if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) { if (mac->toggle_cnt > 4) { status = 2; goto out; @@ -609,6 +607,7 @@ out: mac->tx_mcnt = s->tx_frames; mac->rx_xcnt = rx_xcnt; mac->rx_mcnt = s->rx_frames; + mac->rx_pause = s->rx_pause; if (status == 1) { t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ |