aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/chelsio
diff options
context:
space:
mode:
authorVipul Pandya <vipul@chelsio.com>2012-05-18 05:59:25 -0400
committerRoland Dreier <roland@purestorage.com>2012-05-18 16:22:27 -0400
commit8caa1e8446948afefdb4dd2050a465f6da777652 (patch)
treece8b61eec0f0dc47b4b80fc9d352d46dcea9cdd0 /drivers/net/ethernet/chelsio
parent881806bc155c0d5d78196c8bfae0ea2e76ae7386 (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.h3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c69
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,
723int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); 723int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
724void t4_db_full(struct adapter *adapter); 724void t4_db_full(struct adapter *adapter);
725void t4_db_dropped(struct adapter *adapter); 725void t4_db_dropped(struct adapter *adapter);
726int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len);
727int 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
871typedef void (*int_handler_t)(struct adapter *adap);
872
871struct intr_info { 873struct 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
1997int 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 */
2024int 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