diff options
author | Vipul Pandya <vipul@chelsio.com> | 2012-05-18 05:59:25 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-05-18 16:22:27 -0400 |
commit | 8caa1e8446948afefdb4dd2050a465f6da777652 (patch) | |
tree | ce8b61eec0f0dc47b4b80fc9d352d46dcea9cdd0 /drivers/net/ethernet/chelsio | |
parent | 881806bc155c0d5d78196c8bfae0ea2e76ae7386 (diff) |
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>
Diffstat (limited to 'drivers/net/ethernet/chelsio')
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 69 |
2 files changed, 61 insertions, 11 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index f91b259f19be..5f3c0a728e18 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | |||
@@ -723,4 +723,7 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, | |||
723 | int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); | 723 | int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); |
724 | void t4_db_full(struct adapter *adapter); | 724 | void t4_db_full(struct adapter *adapter); |
725 | void t4_db_dropped(struct adapter *adapter); | 725 | void t4_db_dropped(struct adapter *adapter); |
726 | int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len); | ||
727 | int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, | ||
728 | u32 addr, u32 val); | ||
726 | #endif /* __CXGB4_H__ */ | 729 | #endif /* __CXGB4_H__ */ |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 13609bf056b0..32e1dd566a14 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | |||
@@ -868,11 +868,14 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port) | |||
868 | return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); | 868 | return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); |
869 | } | 869 | } |
870 | 870 | ||
871 | typedef void (*int_handler_t)(struct adapter *adap); | ||
872 | |||
871 | struct intr_info { | 873 | struct intr_info { |
872 | unsigned int mask; /* bits to check in interrupt status */ | 874 | unsigned int mask; /* bits to check in interrupt status */ |
873 | const char *msg; /* message to print or NULL */ | 875 | const char *msg; /* message to print or NULL */ |
874 | short stat_idx; /* stat counter to increment or -1 */ | 876 | short stat_idx; /* stat counter to increment or -1 */ |
875 | unsigned short fatal; /* whether the condition reported is fatal */ | 877 | unsigned short fatal; /* whether the condition reported is fatal */ |
878 | int_handler_t int_handler; /* platform-specific int handler */ | ||
876 | }; | 879 | }; |
877 | 880 | ||
878 | /** | 881 | /** |
@@ -905,6 +908,8 @@ static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg, | |||
905 | } else if (acts->msg && printk_ratelimit()) | 908 | } else if (acts->msg && printk_ratelimit()) |
906 | dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg, | 909 | dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg, |
907 | status & acts->mask); | 910 | status & acts->mask); |
911 | if (acts->int_handler) | ||
912 | acts->int_handler(adapter); | ||
908 | mask |= acts->mask; | 913 | mask |= acts->mask; |
909 | } | 914 | } |
910 | status &= mask; | 915 | status &= mask; |
@@ -1013,9 +1018,9 @@ static void sge_intr_handler(struct adapter *adapter) | |||
1013 | { ERR_INVALID_CIDX_INC, | 1018 | { ERR_INVALID_CIDX_INC, |
1014 | "SGE GTS CIDX increment too large", -1, 0 }, | 1019 | "SGE GTS CIDX increment too large", -1, 0 }, |
1015 | { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 }, | 1020 | { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 }, |
1016 | { F_DBFIFO_LP_INT, NULL, -1, 0 }, | 1021 | { F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full }, |
1017 | { F_DBFIFO_HP_INT, NULL, -1, 0 }, | 1022 | { F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full }, |
1018 | { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 }, | 1023 | { F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped }, |
1019 | { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0, | 1024 | { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0, |
1020 | "SGE IQID > 1023 received CPL for FL", -1, 0 }, | 1025 | "SGE IQID > 1023 received CPL for FL", -1, 0 }, |
1021 | { ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1, | 1026 | { ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1, |
@@ -1036,20 +1041,14 @@ static void sge_intr_handler(struct adapter *adapter) | |||
1036 | }; | 1041 | }; |
1037 | 1042 | ||
1038 | v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) | | 1043 | v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) | |
1039 | ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32); | 1044 | ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32); |
1040 | if (v) { | 1045 | if (v) { |
1041 | dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n", | 1046 | dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n", |
1042 | (unsigned long long)v); | 1047 | (unsigned long long)v); |
1043 | t4_write_reg(adapter, SGE_INT_CAUSE1, v); | 1048 | t4_write_reg(adapter, SGE_INT_CAUSE1, v); |
1044 | t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32); | 1049 | t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32); |
1045 | } | 1050 | } |
1046 | 1051 | ||
1047 | err = t4_read_reg(adapter, A_SGE_INT_CAUSE3); | ||
1048 | if (err & (F_DBFIFO_HP_INT|F_DBFIFO_LP_INT)) | ||
1049 | t4_db_full(adapter); | ||
1050 | if (err & F_ERR_DROPPED_DB) | ||
1051 | t4_db_dropped(adapter); | ||
1052 | |||
1053 | if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) || | 1052 | if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) || |
1054 | v != 0) | 1053 | v != 0) |
1055 | t4_fatal_err(adapter); | 1054 | t4_fatal_err(adapter); |
@@ -1995,6 +1994,54 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, | |||
1995 | (var).retval_len16 = htonl(FW_LEN16(var)); \ | 1994 | (var).retval_len16 = htonl(FW_LEN16(var)); \ |
1996 | } while (0) | 1995 | } while (0) |
1997 | 1996 | ||
1997 | int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, | ||
1998 | u32 addr, u32 val) | ||
1999 | { | ||
2000 | struct fw_ldst_cmd c; | ||
2001 | |||
2002 | memset(&c, 0, sizeof(c)); | ||
2003 | c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST | | ||
2004 | F_FW_CMD_WRITE | | ||
2005 | V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE)); | ||
2006 | c.cycles_to_len16 = htonl(FW_LEN16(c)); | ||
2007 | c.u.addrval.addr = htonl(addr); | ||
2008 | c.u.addrval.val = htonl(val); | ||
2009 | |||
2010 | return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); | ||
2011 | } | ||
2012 | |||
2013 | /* | ||
2014 | * t4_mem_win_read_len - read memory through PCIE memory window | ||
2015 | * @adap: the adapter | ||
2016 | * @addr: address of first byte requested aligned on 32b. | ||
2017 | * @data: len bytes to hold the data read | ||
2018 | * @len: amount of data to read from window. Must be <= | ||
2019 | * MEMWIN0_APERATURE after adjusting for 16B alignment | ||
2020 | * requirements of the the memory window. | ||
2021 | * | ||
2022 | * Read len bytes of data from MC starting at @addr. | ||
2023 | */ | ||
2024 | int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len) | ||
2025 | { | ||
2026 | int i; | ||
2027 | int off; | ||
2028 | |||
2029 | /* | ||
2030 | * Align on a 16B boundary. | ||
2031 | */ | ||
2032 | off = addr & 15; | ||
2033 | if ((addr & 3) || (len + off) > MEMWIN0_APERTURE) | ||
2034 | return -EINVAL; | ||
2035 | |||
2036 | t4_write_reg(adap, A_PCIE_MEM_ACCESS_OFFSET, addr & ~15); | ||
2037 | t4_read_reg(adap, A_PCIE_MEM_ACCESS_OFFSET); | ||
2038 | |||
2039 | for (i = 0; i < len; i += 4) | ||
2040 | *data++ = t4_read_reg(adap, (MEMWIN0_BASE + off + i)); | ||
2041 | |||
2042 | return 0; | ||
2043 | } | ||
2044 | |||
1998 | /** | 2045 | /** |
1999 | * t4_mdio_rd - read a PHY register through MDIO | 2046 | * t4_mdio_rd - read a PHY register through MDIO |
2000 | * @adap: the adapter | 2047 | * @adap: the adapter |