#include "sif_query.h"
#include "sif_qp.h"
#include "sif_defs.h"
+#include "sif_r3.h"
/* A 'reference' element to identify each table type
*/
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 */
.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 */
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;
/**** 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;
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
*/
#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
/* 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;
/* 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
.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;
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);
}
}
- 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",
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
};
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);
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);
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;
}
}
}
+ 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;
}
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");
+}
#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);
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