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:
parent
881806bc15
commit
8caa1e8446
|
@ -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);
|
||||
void t4_db_full(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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
typedef void (*int_handler_t)(struct adapter *adap);
|
||||
|
||||
struct intr_info {
|
||||
unsigned int mask; /* bits to check in interrupt status */
|
||||
const char *msg; /* message to print or NULL */
|
||||
short stat_idx; /* stat counter to increment or -1 */
|
||||
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())
|
||||
dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg,
|
||||
status & acts->mask);
|
||||
if (acts->int_handler)
|
||||
acts->int_handler(adapter);
|
||||
mask |= acts->mask;
|
||||
}
|
||||
status &= mask;
|
||||
|
@ -1013,9 +1018,9 @@ static void sge_intr_handler(struct adapter *adapter)
|
|||
{ ERR_INVALID_CIDX_INC,
|
||||
"SGE GTS CIDX increment too large", -1, 0 },
|
||||
{ ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
|
||||
{ F_DBFIFO_LP_INT, NULL, -1, 0 },
|
||||
{ F_DBFIFO_HP_INT, NULL, -1, 0 },
|
||||
{ ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
|
||||
{ F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full },
|
||||
{ F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full },
|
||||
{ F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped },
|
||||
{ ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
|
||||
"SGE IQID > 1023 received CPL for FL", -1, 0 },
|
||||
{ ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
|
||||
|
@ -1044,12 +1049,6 @@ static void sge_intr_handler(struct adapter *adapter)
|
|||
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) ||
|
||||
v != 0)
|
||||
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)); \
|
||||
} 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
|
||||
* @adap: the adapter
|
||||
|
|
Loading…
Reference in New Issue