From: Triviño Date: Fri, 10 Jun 2016 14:44:20 +0000 (+0200) Subject: sif: Add debugfs for workaround usage statistics X-Git-Tag: v4.1.12-92~129^2~24 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=79e8ef65928293c4ffea128383878f10867981ec;p=users%2Fjedix%2Flinux-maple.git sif: Add debugfs for workaround usage statistics This commit also adds: * WA#3714 usage counters and dump info * Rename 3713 (bug ticket) to 3714 (WA ticket) Signed-off-by: Triviño Reviewed-by: Knut Omang --- diff --git a/drivers/infiniband/hw/sif/sif_debug.c b/drivers/infiniband/hw/sif/sif_debug.c index 763f6b417263..56ed015b3ee7 100644 --- a/drivers/infiniband/hw/sif/sif_debug.c +++ b/drivers/infiniband/hw/sif/sif_debug.c @@ -20,6 +20,7 @@ #include "sif_query.h" #include "sif_qp.h" #include "sif_defs.h" +#include "sif_r3.h" /* A 'reference' element to identify each table type */ @@ -41,6 +42,7 @@ struct sif_dfs { struct sif_dfs_ref sd_eq; struct sif_dfs_ref sd_irq_ch; struct sif_dfs_ref sd_ipoffload; + struct sif_dfs_ref sd_wa_stats; }; /* A simple iterator */ @@ -437,6 +439,57 @@ static const struct file_operations table_fops_rw = { .release = sif_seq_release }; +/**** support for workaround statistics */ + +static int r_open(struct inode *inode, struct file *file) +{ + if (!try_module_get(THIS_MODULE)) + return -EIO; + + file->private_data = inode->i_private; + return 0; +}; + +static int r_release(struct inode *inode, struct file *file) +{ + module_put(THIS_MODULE); + return 0; +} + +static ssize_t rwa_read(struct file *file, char __user *buf, size_t sz, loff_t *off) +{ + struct sif_dev *sdev = ((struct sif_dfs_ref *)file->private_data)->sdev; + size_t len = 0; + struct xchar xc; + size_t dump_size = 12000; /* enough space for allocating the workaround statistics dump */ + char *dump; + + if (*off > 0) + return 0; + + dump = kmalloc(dump_size, GFP_KERNEL); + if (!dump) { + sif_log0(SIF_INFO, "Error allocating temp.storage for wa statistics"); + return -ENOMEM; + } + + memset(dump, 0, dump_size*sizeof(char)); + xc.buf = dump; + + sif_dfs_print_wa_stats(sdev, xc.buf); + + len = simple_read_from_buffer(buf, sz, off, dump, strlen(dump)); + kfree(dump); + + return len; +} + +static const struct file_operations wa_fops = { + .owner = THIS_MODULE, + .open = r_open, + .read = rwa_read, + .release = r_release, +}; /* Setup/teardown */ @@ -495,6 +548,15 @@ int sif_dfs_register(struct sif_dev *sdev) sif_log(sdev, SIF_INFO, "Unable to set up debugfs file for ipoffload qp stat"); return -ENOMEM; } + /* Single file for the wa statistics */ + sdr = &sdev->dfs->sd_wa_stats; + sdr->sdev = sdev; + df = debugfs_create_file("wa_stats", S_IRUGO, sdev->dfs->root, + (void *)sdr, &wa_fops); + if (!df) { + sif_log(sdev, SIF_INFO, "Unable to set up debugfs file for wa stat"); + return -ENOMEM; + } /* Single file for the int channel coalescing settings */ sdr = &sdev->dfs->sd_irq_ch; sdr->sdev = sdev; @@ -546,17 +608,6 @@ void sif_dfs_unregister(struct sif_dev *sdev) /**** support for raw QP state dump */ - -static int rqp_open(struct inode *inode, struct file *file) -{ - if (!try_module_get(THIS_MODULE)) - return -EIO; - - file->private_data = inode->i_private; - return 0; -}; - - static ssize_t rqp_read(struct file *file, char __user *buf, size_t sz, loff_t *off) { struct sif_qp *qp = (struct sif_qp *)file->private_data; @@ -597,22 +648,13 @@ static ssize_t rqp_read(struct file *file, char __user *buf, size_t sz, loff_t * return len; } - -static int rqp_release(struct inode *inode, struct file *file) -{ - module_put(THIS_MODULE); - return 0; -} - - static const struct file_operations qp_fops = { .owner = THIS_MODULE, - .open = rqp_open, + .open = r_open, .read = rqp_read, - .release = rqp_release, + .release = r_release, }; - /* TBD: Ref.cnt or other protection probably needed to protect agains "take down" while * a query is in progress */ diff --git a/drivers/infiniband/hw/sif/sif_dev.h b/drivers/infiniband/hw/sif/sif_dev.h index ca133132d966..109c3a75aab0 100644 --- a/drivers/infiniband/hw/sif/sif_dev.h +++ b/drivers/infiniband/hw/sif/sif_dev.h @@ -33,6 +33,8 @@ #include "sif_verbs.h" +#include "sif_r3.h" + #define PCI_VENDOR_ID_SUN 0x108e #define PCI_DEVICE_ID_PSIF_PF 0x2088 #define PCI_DEVICE_ID_PSIF_VF 0x2089 @@ -292,7 +294,7 @@ struct sif_dev { /* Support for workaround for #3552 - feature_mask create_do_not_evict_qp: */ u32 dne_qp; - /* Support for workaround for #3713 */ + /* Support for WA#3714 */ u32 flush_qp; struct mutex flush_lock; @@ -331,6 +333,8 @@ struct sif_dev { /* PSIF is degraded */ bool degraded; + /* Owned by sif_r3.c - wa support */ + struct sif_wa_stats wa_stats; }; /* TBD: These should probably come from common pci headers diff --git a/drivers/infiniband/hw/sif/sif_qp.c b/drivers/infiniband/hw/sif/sif_qp.c index 988ed7760e04..82408cb60313 100644 --- a/drivers/infiniband/hw/sif/sif_qp.c +++ b/drivers/infiniband/hw/sif/sif_qp.c @@ -808,7 +808,7 @@ int modify_qp_hw_wa_qp_retry(struct sif_dev *sdev, struct sif_qp *qp, .qp_state = IB_QPS_ERR }; - bool need_wa_3713 = PSIF_REVISION(sdev) <= 3 + bool need_wa_3714 = PSIF_REVISION(sdev) <= 3 && IS_PSIF(sdev) && qp_attr_mask & IB_QP_STATE && qp_attr->qp_state == IB_QPS_RESET; @@ -820,7 +820,7 @@ int modify_qp_hw_wa_qp_retry(struct sif_dev *sdev, struct sif_qp *qp, int ret = 0; - if (need_wa_3713 || need_wa_4074) { + if (need_wa_3714 || need_wa_4074) { if (qp->type != PSIF_QP_TRANSPORT_MANSP1 && !is_xtgt_qp(qp)) ret = pre_process_wa4074(sdev, qp); @@ -830,8 +830,8 @@ int modify_qp_hw_wa_qp_retry(struct sif_dev *sdev, struct sif_qp *qp, } } - if (need_wa_3713) { - /* Workaround for bug #3713 part 2 - see #3714 */ + if (need_wa_3714) { + /* WA#3714 part 2 - see bug #3714 */ ret = modify_qp_hw(sdev, qp, &mod_attr, IB_QP_STATE); if (ret) sif_log(sdev, SIF_INFO, "implicit modify qp %d to ERR failed - ignoring", @@ -840,7 +840,7 @@ int modify_qp_hw_wa_qp_retry(struct sif_dev *sdev, struct sif_qp *qp, ret = modify_qp_hw(sdev, qp, qp_attr, qp_attr_mask); - if (need_wa_3713 || need_wa_4074) { + if (need_wa_3714 || need_wa_4074) { struct ib_qp_attr attr = { .qp_state = IB_QPS_RESET }; @@ -2273,7 +2273,7 @@ static int reset_qp(struct sif_dev *sdev, struct sif_qp *qp) volatile struct psif_qp *qps = &qp->d; struct sif_rq *rq = get_rq(sdev, qp); struct sif_sq *sq = get_sq(sdev, qp); - bool need_wa_3713 = 0; + bool need_wa_3714 = 0; /* Bring down order needed by rev2 according to bug #3480 */ int ret = poll_wait_for_qp_writeback(sdev, qp); @@ -2281,15 +2281,15 @@ static int reset_qp(struct sif_dev *sdev, struct sif_qp *qp) if (ret) goto failed; - /* WA 3713 special handling */ - need_wa_3713 = (PSIF_REVISION(sdev) <= 3) + /* WA 3714 special handling */ + need_wa_3714 = (PSIF_REVISION(sdev) <= 3) && IS_PSIF(sdev) /* Next check if there is a retry outstanding */ && !qp->flush_sq_done_wa4074 && (get_psif_qp_core__retry_tag_committed(&qp->d.state) != get_psif_qp_core__retry_tag_err(&qp->d.state)) && (qp->qp_idx != sdev->flush_qp); - if (need_wa_3713) { + if (need_wa_3714) { ret = reset_qp_flush_retry(sdev); if (ret < 0) sif_log(sdev, SIF_INFO, "Flush_retry special handling failed with ret %d", ret); diff --git a/drivers/infiniband/hw/sif/sif_r3.c b/drivers/infiniband/hw/sif/sif_r3.c index 7bdf3652be0b..510a28748863 100644 --- a/drivers/infiniband/hw/sif/sif_r3.c +++ b/drivers/infiniband/hw/sif/sif_r3.c @@ -363,7 +363,7 @@ int reset_qp_flush_retry(struct sif_dev *sdev) mutex_lock(&sdev->flush_lock); if (!sdev->flush_qp) { - sif_log(sdev, SIF_INFO, "special handling WA_3713 failed: flush_qp does not exist"); + sif_log(sdev, SIF_INFO, "special handling WA_3714 failed: flush_qp does not exist"); ret = -EINVAL; goto err_flush_qp; } @@ -439,15 +439,18 @@ int reset_qp_flush_retry(struct sif_dev *sdev) } } + sdev->wa_stats.wa3714[0]++; mutex_unlock(&sdev->flush_lock); return ret; fail: + sdev->wa_stats.wa3714[1]++; sif_hw_free_flush_qp(sdev); sif_hw_allocate_flush_qp(sdev); mutex_unlock(&sdev->flush_lock); return ret; err_flush_qp: + sdev->wa_stats.wa3714[1]++; mutex_unlock(&sdev->flush_lock); return ret; } @@ -900,3 +903,15 @@ static u16 cq_walk_wa4074(struct sif_dev *sdev, struct sif_qp *qp, bool *last_se spin_unlock_irqrestore(&cq->lock, flags); return last_seq; } + +void sif_dfs_print_wa_stats(struct sif_dev *sdev, char *buf) +{ + /* Header */ + sprintf(buf, "#%7s %10s %10s %20s\n", "WA", "ok", "err", "desc"); + /* Content */ + sprintf(buf + strlen(buf), "#%8s %9llu %10llu %20s\n", + "WA3714", + sdev->wa_stats.wa3714[0], + sdev->wa_stats.wa3714[1], + "Destroying QPs with a retry in progress"); +} diff --git a/drivers/infiniband/hw/sif/sif_r3.h b/drivers/infiniband/hw/sif/sif_r3.h index 7086483ac2f8..69e4cfba2a9e 100644 --- a/drivers/infiniband/hw/sif/sif_r3.h +++ b/drivers/infiniband/hw/sif/sif_r3.h @@ -14,11 +14,16 @@ #ifndef _SIF_R3_H #define _SIF_R3_H +struct sif_wa_stats { + /* Destroying QPs with a retry in progress */ + u64 wa3714[2]; +}; + void sif_r3_pre_init(struct sif_dev *sdev); int sif_r3_init(struct sif_dev *sdev); void sif_r3_deinit(struct sif_dev *sdev); -/* WA for #3713 */ +/* WA for #3714 */ int reset_qp_flush_retry(struct sif_dev *sdev); void sif_r3_recreate_flush_qp(struct sif_dev *sdev); @@ -27,4 +32,6 @@ int pre_process_wa4074(struct sif_dev *sdev, struct sif_qp *qp); int post_process_wa4074(struct sif_dev *sdev, struct sif_qp *qp); int sq_flush_wa4074(struct sif_dev *sdev, struct sif_qp *qp); +/* Single file for the wa statistics */ +void sif_dfs_print_wa_stats(struct sif_dev *sdev, char *buf); #endif