summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgb/common
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2007-09-09 01:28:03 +0000
committerkmacy <kmacy@FreeBSD.org>2007-09-09 01:28:03 +0000
commit36e50690beafcb223cb1b34751cd4f28ad095394 (patch)
tree4cef61463d4eb54cc5156a6cc7cf54ed763f4010 /sys/dev/cxgb/common
parent8fc160dac01fee84ee885f1358e4dffb7e772df5 (diff)
downloadFreeBSD-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.h5
-rw-r--r--sys/dev/cxgb/common/cxgb_ctl_defs.h10
-rw-r--r--sys/dev/cxgb/common/cxgb_sge_defs.h4
-rw-r--r--sys/dev/cxgb/common/cxgb_t3_hw.c170
-rw-r--r--sys/dev/cxgb/common/cxgb_vsc7323.c34
-rw-r--r--sys/dev/cxgb/common/cxgb_xgmac.c15
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 */
OpenPOWER on IntegriCloud