cxgb4: Common platform specific changes for DB Drop Recovery

Add platform-specific callback functions for interrupts.  This is
needed to do a single read-clear of the CAUSE register and then call
out to platform specific functions for DB threshold interrupts and DB
drop interrupts.

Add t4_mem_win_read_len() - mem-window reads for arbitrary lengths.
This is used to read the CIDX/PIDX values from EC contexts during DB
drop recovery.

Add t4_fwaddrspace_write() - sends addrspace write cmds to the fw.
Needed to flush the sge eq context cache.

Signed-off-by: Vipul Pandya <vipul@chelsio.com>
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
Vipul Pandya 2012-05-18 15:29:25 +05:30 committed by Roland Dreier
parent 881806bc15
commit 8caa1e8446
2 changed files with 61 additions and 11 deletions

View file

@ -723,4 +723,7 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
void t4_db_full(struct adapter *adapter); void t4_db_full(struct adapter *adapter);
void t4_db_dropped(struct adapter *adapter); void t4_db_dropped(struct adapter *adapter);
int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len);
int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
u32 addr, u32 val);
#endif /* __CXGB4_H__ */ #endif /* __CXGB4_H__ */

View file

@ -868,11 +868,14 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
} }
typedef void (*int_handler_t)(struct adapter *adap);
struct intr_info { struct intr_info {
unsigned int mask; /* bits to check in interrupt status */ unsigned int mask; /* bits to check in interrupt status */
const char *msg; /* message to print or NULL */ const char *msg; /* message to print or NULL */
short stat_idx; /* stat counter to increment or -1 */ short stat_idx; /* stat counter to increment or -1 */
unsigned short fatal; /* whether the condition reported is fatal */ unsigned short fatal; /* whether the condition reported is fatal */
int_handler_t int_handler; /* platform-specific int handler */
}; };
/** /**
@ -905,6 +908,8 @@ static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg,
} else if (acts->msg && printk_ratelimit()) } else if (acts->msg && printk_ratelimit())
dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg, dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg,
status & acts->mask); status & acts->mask);
if (acts->int_handler)
acts->int_handler(adapter);
mask |= acts->mask; mask |= acts->mask;
} }
status &= mask; status &= mask;
@ -1013,9 +1018,9 @@ static void sge_intr_handler(struct adapter *adapter)
{ ERR_INVALID_CIDX_INC, { ERR_INVALID_CIDX_INC,
"SGE GTS CIDX increment too large", -1, 0 }, "SGE GTS CIDX increment too large", -1, 0 },
{ ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 }, { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
{ F_DBFIFO_LP_INT, NULL, -1, 0 }, { F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full },
{ F_DBFIFO_HP_INT, NULL, -1, 0 }, { F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full },
{ ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 }, { F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped },
{ ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0, { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
"SGE IQID > 1023 received CPL for FL", -1, 0 }, "SGE IQID > 1023 received CPL for FL", -1, 0 },
{ ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1, { ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
@ -1036,20 +1041,14 @@ static void sge_intr_handler(struct adapter *adapter)
}; };
v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) | v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) |
((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32); ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32);
if (v) { if (v) {
dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n", dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n",
(unsigned long long)v); (unsigned long long)v);
t4_write_reg(adapter, SGE_INT_CAUSE1, v); t4_write_reg(adapter, SGE_INT_CAUSE1, v);
t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32); t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32);
} }
err = t4_read_reg(adapter, A_SGE_INT_CAUSE3);
if (err & (F_DBFIFO_HP_INT|F_DBFIFO_LP_INT))
t4_db_full(adapter);
if (err & F_ERR_DROPPED_DB)
t4_db_dropped(adapter);
if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) || if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) ||
v != 0) v != 0)
t4_fatal_err(adapter); t4_fatal_err(adapter);
@ -1995,6 +1994,54 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
(var).retval_len16 = htonl(FW_LEN16(var)); \ (var).retval_len16 = htonl(FW_LEN16(var)); \
} while (0) } while (0)
int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
u32 addr, u32 val)
{
struct fw_ldst_cmd c;
memset(&c, 0, sizeof(c));
c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
F_FW_CMD_WRITE |
V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE));
c.cycles_to_len16 = htonl(FW_LEN16(c));
c.u.addrval.addr = htonl(addr);
c.u.addrval.val = htonl(val);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
/*
* t4_mem_win_read_len - read memory through PCIE memory window
* @adap: the adapter
* @addr: address of first byte requested aligned on 32b.
* @data: len bytes to hold the data read
* @len: amount of data to read from window. Must be <=
* MEMWIN0_APERATURE after adjusting for 16B alignment
* requirements of the the memory window.
*
* Read len bytes of data from MC starting at @addr.
*/
int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
{
int i;
int off;
/*
* Align on a 16B boundary.
*/
off = addr & 15;
if ((addr & 3) || (len + off) > MEMWIN0_APERTURE)
return -EINVAL;
t4_write_reg(adap, A_PCIE_MEM_ACCESS_OFFSET, addr & ~15);
t4_read_reg(adap, A_PCIE_MEM_ACCESS_OFFSET);
for (i = 0; i < len; i += 4)
*data++ = t4_read_reg(adap, (MEMWIN0_BASE + off + i));
return 0;
}
/** /**
* t4_mdio_rd - read a PHY register through MDIO * t4_mdio_rd - read a PHY register through MDIO
* @adap: the adapter * @adap: the adapter