aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHariprasad Shenai <hariprasad@chelsio.com>2014-07-14 12:04:53 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-15 19:25:16 -0400
commit031cf4769bc4504d046074274d1ecd70d89d20b8 (patch)
tree9fc2ee18f4ee2cf26c365e4e3083ed8994c105e7
parent4c2c5763227a14ce111d6f35df708459d2443cc3 (diff)
cxgb4/iw_cxgb4: display TPTE on errors
With ingress WRITE or READ RESPONSE errors, HW provides the offending stag from the packet. This patch adds logic to log the parsed TPTE in this case. cxgb4 now exports a function to read a TPTE entry from adapter memory. Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c28
-rw-r--r--drivers/infiniband/hw/cxgb4/ev.c55
-rw-r--r--drivers/infiniband/hw/cxgb4/t4.h4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c66
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h1
5 files changed, 143 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index e76358efcaa1..8386678f1159 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -241,12 +241,32 @@ static int dump_stag(int id, void *p, void *data)
241 struct c4iw_debugfs_data *stagd = data; 241 struct c4iw_debugfs_data *stagd = data;
242 int space; 242 int space;
243 int cc; 243 int cc;
244 struct fw_ri_tpte tpte;
245 int ret;
244 246
245 space = stagd->bufsize - stagd->pos - 1; 247 space = stagd->bufsize - stagd->pos - 1;
246 if (space == 0) 248 if (space == 0)
247 return 1; 249 return 1;
248 250
249 cc = snprintf(stagd->buf + stagd->pos, space, "0x%x\n", id<<8); 251 ret = cxgb4_read_tpte(stagd->devp->rdev.lldi.ports[0], (u32)id<<8,
252 (__be32 *)&tpte);
253 if (ret) {
254 dev_err(&stagd->devp->rdev.lldi.pdev->dev,
255 "%s cxgb4_read_tpte err %d\n", __func__, ret);
256 return ret;
257 }
258 cc = snprintf(stagd->buf + stagd->pos, space,
259 "stag: idx 0x%x valid %d key 0x%x state %d pdid %d "
260 "perm 0x%x ps %d len 0x%llx va 0x%llx\n",
261 (u32)id<<8,
262 G_FW_RI_TPTE_VALID(ntohl(tpte.valid_to_pdid)),
263 G_FW_RI_TPTE_STAGKEY(ntohl(tpte.valid_to_pdid)),
264 G_FW_RI_TPTE_STAGSTATE(ntohl(tpte.valid_to_pdid)),
265 G_FW_RI_TPTE_PDID(ntohl(tpte.valid_to_pdid)),
266 G_FW_RI_TPTE_PERM(ntohl(tpte.locread_to_qpid)),
267 G_FW_RI_TPTE_PS(ntohl(tpte.locread_to_qpid)),
268 ((u64)ntohl(tpte.len_hi) << 32) | ntohl(tpte.len_lo),
269 ((u64)ntohl(tpte.va_hi) << 32) | ntohl(tpte.va_lo_fbo));
250 if (cc < space) 270 if (cc < space)
251 stagd->pos += cc; 271 stagd->pos += cc;
252 return 0; 272 return 0;
@@ -259,7 +279,7 @@ static int stag_release(struct inode *inode, struct file *file)
259 printk(KERN_INFO "%s null stagd?\n", __func__); 279 printk(KERN_INFO "%s null stagd?\n", __func__);
260 return 0; 280 return 0;
261 } 281 }
262 kfree(stagd->buf); 282 vfree(stagd->buf);
263 kfree(stagd); 283 kfree(stagd);
264 return 0; 284 return 0;
265} 285}
@@ -282,8 +302,8 @@ static int stag_open(struct inode *inode, struct file *file)
282 idr_for_each(&stagd->devp->mmidr, count_idrs, &count); 302 idr_for_each(&stagd->devp->mmidr, count_idrs, &count);
283 spin_unlock_irq(&stagd->devp->lock); 303 spin_unlock_irq(&stagd->devp->lock);
284 304
285 stagd->bufsize = count * sizeof("0x12345678\n"); 305 stagd->bufsize = count * 256;
286 stagd->buf = kmalloc(stagd->bufsize, GFP_KERNEL); 306 stagd->buf = vmalloc(stagd->bufsize);
287 if (!stagd->buf) { 307 if (!stagd->buf) {
288 ret = -ENOMEM; 308 ret = -ENOMEM;
289 goto err1; 309 goto err1;
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index d61d0a18f784..fbe6051af254 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -35,6 +35,55 @@
35 35
36#include "iw_cxgb4.h" 36#include "iw_cxgb4.h"
37 37
38static void print_tpte(struct c4iw_dev *dev, u32 stag)
39{
40 int ret;
41 struct fw_ri_tpte tpte;
42
43 ret = cxgb4_read_tpte(dev->rdev.lldi.ports[0], stag,
44 (__be32 *)&tpte);
45 if (ret) {
46 dev_err(&dev->rdev.lldi.pdev->dev,
47 "%s cxgb4_read_tpte err %d\n", __func__, ret);
48 return;
49 }
50 PDBG("stag idx 0x%x valid %d key 0x%x state %d pdid %d "
51 "perm 0x%x ps %d len 0x%llx va 0x%llx\n",
52 stag & 0xffffff00,
53 G_FW_RI_TPTE_VALID(ntohl(tpte.valid_to_pdid)),
54 G_FW_RI_TPTE_STAGKEY(ntohl(tpte.valid_to_pdid)),
55 G_FW_RI_TPTE_STAGSTATE(ntohl(tpte.valid_to_pdid)),
56 G_FW_RI_TPTE_PDID(ntohl(tpte.valid_to_pdid)),
57 G_FW_RI_TPTE_PERM(ntohl(tpte.locread_to_qpid)),
58 G_FW_RI_TPTE_PS(ntohl(tpte.locread_to_qpid)),
59 ((u64)ntohl(tpte.len_hi) << 32) | ntohl(tpte.len_lo),
60 ((u64)ntohl(tpte.va_hi) << 32) | ntohl(tpte.va_lo_fbo));
61}
62
63static void dump_err_cqe(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
64{
65 __be64 *p = (void *)err_cqe;
66
67 dev_err(&dev->rdev.lldi.pdev->dev,
68 "AE qpid %d opcode %d status 0x%x "
69 "type %d len 0x%x wrid.hi 0x%x wrid.lo 0x%x\n",
70 CQE_QPID(err_cqe), CQE_OPCODE(err_cqe),
71 CQE_STATUS(err_cqe), CQE_TYPE(err_cqe), ntohl(err_cqe->len),
72 CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe));
73
74 PDBG("%016llx %016llx %016llx %016llx\n",
75 be64_to_cpu(p[0]), be64_to_cpu(p[1]), be64_to_cpu(p[2]),
76 be64_to_cpu(p[3]));
77
78 /*
79 * Ingress WRITE and READ_RESP errors provide
80 * the offending stag, so parse and log it.
81 */
82 if (RQ_TYPE(err_cqe) && (CQE_OPCODE(err_cqe) == FW_RI_RDMA_WRITE ||
83 CQE_OPCODE(err_cqe) == FW_RI_READ_RESP))
84 print_tpte(dev, CQE_WRID_STAG(err_cqe));
85}
86
38static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp, 87static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
39 struct c4iw_qp *qhp, 88 struct c4iw_qp *qhp,
40 struct t4_cqe *err_cqe, 89 struct t4_cqe *err_cqe,
@@ -44,11 +93,7 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
44 struct c4iw_qp_attributes attrs; 93 struct c4iw_qp_attributes attrs;
45 unsigned long flag; 94 unsigned long flag;
46 95
47 printk(KERN_ERR MOD "AE qpid 0x%x opcode %d status 0x%x " 96 dump_err_cqe(dev, err_cqe);
48 "type %d wrid.hi 0x%x wrid.lo 0x%x\n",
49 CQE_QPID(err_cqe), CQE_OPCODE(err_cqe),
50 CQE_STATUS(err_cqe), CQE_TYPE(err_cqe),
51 CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe));
52 97
53 if (qhp->attr.state == C4IW_QP_STATE_RTS) { 98 if (qhp->attr.state == C4IW_QP_STATE_RTS) {
54 attrs.next_state = C4IW_QP_STATE_TERMINATE; 99 attrs.next_state = C4IW_QP_STATE_TERMINATE;
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index e64fa8b2be06..dd45186d1c55 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -236,8 +236,8 @@ struct t4_cqe {
236#define CQE_WRID_SQ_IDX(x) ((x)->u.scqe.cidx) 236#define CQE_WRID_SQ_IDX(x) ((x)->u.scqe.cidx)
237 237
238/* generic accessor macros */ 238/* generic accessor macros */
239#define CQE_WRID_HI(x) ((x)->u.gen.wrid_hi) 239#define CQE_WRID_HI(x) (be32_to_cpu((x)->u.gen.wrid_hi))
240#define CQE_WRID_LOW(x) ((x)->u.gen.wrid_low) 240#define CQE_WRID_LOW(x) (be32_to_cpu((x)->u.gen.wrid_low))
241 241
242/* macros for flit 3 of the cqe */ 242/* macros for flit 3 of the cqe */
243#define S_CQE_GENBIT 63 243#define S_CQE_GENBIT 63
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 767cbbaa3d1e..ba7d13de5e83 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3832,6 +3832,72 @@ void cxgb4_enable_db_coalescing(struct net_device *dev)
3832} 3832}
3833EXPORT_SYMBOL(cxgb4_enable_db_coalescing); 3833EXPORT_SYMBOL(cxgb4_enable_db_coalescing);
3834 3834
3835int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte)
3836{
3837 struct adapter *adap;
3838 u32 offset, memtype, memaddr;
3839 u32 edc0_size, edc1_size, mc0_size, mc1_size;
3840 u32 edc0_end, edc1_end, mc0_end, mc1_end;
3841 int ret;
3842
3843 adap = netdev2adap(dev);
3844
3845 offset = ((stag >> 8) * 32) + adap->vres.stag.start;
3846
3847 /* Figure out where the offset lands in the Memory Type/Address scheme.
3848 * This code assumes that the memory is laid out starting at offset 0
3849 * with no breaks as: EDC0, EDC1, MC0, MC1. All cards have both EDC0
3850 * and EDC1. Some cards will have neither MC0 nor MC1, most cards have
3851 * MC0, and some have both MC0 and MC1.
3852 */
3853 edc0_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM0_BAR)) << 20;
3854 edc1_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM1_BAR)) << 20;
3855 mc0_size = EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR)) << 20;
3856
3857 edc0_end = edc0_size;
3858 edc1_end = edc0_end + edc1_size;
3859 mc0_end = edc1_end + mc0_size;
3860
3861 if (offset < edc0_end) {
3862 memtype = MEM_EDC0;
3863 memaddr = offset;
3864 } else if (offset < edc1_end) {
3865 memtype = MEM_EDC1;
3866 memaddr = offset - edc0_end;
3867 } else {
3868 if (offset < mc0_end) {
3869 memtype = MEM_MC0;
3870 memaddr = offset - edc1_end;
3871 } else if (is_t4(adap->params.chip)) {
3872 /* T4 only has a single memory channel */
3873 goto err;
3874 } else {
3875 mc1_size = EXT_MEM_SIZE_GET(
3876 t4_read_reg(adap,
3877 MA_EXT_MEMORY1_BAR)) << 20;
3878 mc1_end = mc0_end + mc1_size;
3879 if (offset < mc1_end) {
3880 memtype = MEM_MC1;
3881 memaddr = offset - mc0_end;
3882 } else {
3883 /* offset beyond the end of any memory */
3884 goto err;
3885 }
3886 }
3887 }
3888
3889 spin_lock(&adap->win0_lock);
3890 ret = t4_memory_rw(adap, 0, memtype, memaddr, 32, tpte, T4_MEMORY_READ);
3891 spin_unlock(&adap->win0_lock);
3892 return ret;
3893
3894err:
3895 dev_err(adap->pdev_dev, "stag %#x, offset %#x out of range\n",
3896 stag, offset);
3897 return -EINVAL;
3898}
3899EXPORT_SYMBOL(cxgb4_read_tpte);
3900
3835static struct pci_driver cxgb4_driver; 3901static struct pci_driver cxgb4_driver;
3836 3902
3837static void check_neigh_update(struct neighbour *neigh) 3903static void check_neigh_update(struct neighbour *neigh)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index df1d9446768a..c7170d68bf63 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -296,5 +296,6 @@ int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size);
296int cxgb4_flush_eq_cache(struct net_device *dev); 296int cxgb4_flush_eq_cache(struct net_device *dev);
297void cxgb4_disable_db_coalescing(struct net_device *dev); 297void cxgb4_disable_db_coalescing(struct net_device *dev);
298void cxgb4_enable_db_coalescing(struct net_device *dev); 298void cxgb4_enable_db_coalescing(struct net_device *dev);
299int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte);
299 300
300#endif /* !__CXGB4_OFLD_H */ 301#endif /* !__CXGB4_OFLD_H */