336 lines
10 KiB
Diff
336 lines
10 KiB
Diff
From 846a6ad62232595239572185fdc141894504b6d3 Mon Sep 17 00:00:00 2001
|
|
From: Luo Jiaxing <luojiaxing@huawei.com>
|
|
Date: Mon, 5 Aug 2019 21:48:01 +0800
|
|
Subject: [PATCH 008/108] scsi: hisi_sas: Snapshot HW cache of IOST and ITCT at
|
|
debugfs
|
|
|
|
mainline inclusion
|
|
from mainline-v5.4-rc1
|
|
commit bbe0a7b348b336625292092c74fc7817aeb8d30b
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8F808
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bbe0a7b348b336625292092c74fc7817aeb8d30b
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
The value of IOST/ITCT is updated to cache first, and then synchronize to
|
|
DDR periodically. So the value in IOST/ITCT cache is the latest data and
|
|
it's important for debugging.
|
|
|
|
So, the HW cache of IOST and ITCT should be snapshot at debugfs.
|
|
|
|
Signed-off-by: Luo Jiaxing <luojiaxing@huawei.com>
|
|
Signed-off-by: John Garry <john.garry@huawei.com>
|
|
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
|
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>
|
|
|
|
Conflicts:
|
|
drivers/scsi/hisi_sas/hisi_sas.h
|
|
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
---
|
|
drivers/scsi/hisi_sas/hisi_sas.h | 16 ++++
|
|
drivers/scsi/hisi_sas/hisi_sas_main.c | 114 ++++++++++++++++++++++++-
|
|
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 32 +++++++
|
|
3 files changed, 160 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
|
|
index 94aeb3bb6329..bc2b6995dca1 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas.h
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
|
|
@@ -42,6 +42,9 @@
|
|
#define HISI_SAS_UNRESERVED_IPTT \
|
|
(HISI_SAS_MAX_COMMANDS - HISI_SAS_RESERVED_IPTT)
|
|
|
|
+#define HISI_SAS_IOST_ITCT_CACHE_NUM 64
|
|
+#define HISI_SAS_IOST_ITCT_CACHE_DW_SZ 10
|
|
+
|
|
#define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer))
|
|
#define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table))
|
|
|
|
@@ -293,6 +296,14 @@ enum {
|
|
HISI_SAS_BIST_CODE_MODE_FIXED_DATA,
|
|
};
|
|
|
|
+struct hisi_sas_iost_itct_cache {
|
|
+ u32 data[HISI_SAS_IOST_ITCT_CACHE_DW_SZ];
|
|
+};
|
|
+
|
|
+enum hisi_sas_debugfs_cache_type {
|
|
+ HISI_SAS_ITCT_CACHE,
|
|
+ HISI_SAS_IOST_CACHE,
|
|
+};
|
|
|
|
struct hisi_sas_hw {
|
|
int (*hw_init)(struct hisi_hba *hisi_hba);
|
|
@@ -340,6 +351,9 @@ struct hisi_sas_hw {
|
|
const struct cpumask *(*get_managed_irq_aff)(struct hisi_hba
|
|
*hisi_hba, int queue);
|
|
void (*debugfs_work_handler)(struct work_struct *work);
|
|
+ void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba,
|
|
+ enum hisi_sas_debugfs_cache_type type,
|
|
+ u32 *cache);
|
|
int complete_hdr_size;
|
|
struct scsi_host_template *sht;
|
|
|
|
@@ -432,6 +446,8 @@ struct hisi_hba {
|
|
struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES];
|
|
struct hisi_sas_iost *debugfs_iost;
|
|
struct hisi_sas_itct *debugfs_itct;
|
|
+ u64 *debugfs_iost_cache;
|
|
+ u64 *debugfs_itct_cache;
|
|
|
|
struct dentry *debugfs_dir;
|
|
struct dentry *debugfs_dump_dentry;
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
index 8733e34b624d..2d2373b11b20 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
@@ -2835,10 +2835,14 @@ static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba)
|
|
|
|
static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba)
|
|
{
|
|
+ void *cachebuf = hisi_hba->debugfs_itct_cache;
|
|
void *databuf = hisi_hba->debugfs_itct;
|
|
struct hisi_sas_itct *itct;
|
|
int i;
|
|
|
|
+ hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE,
|
|
+ cachebuf);
|
|
+
|
|
itct = hisi_hba->itct;
|
|
|
|
for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
|
|
@@ -2850,10 +2854,14 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba)
|
|
static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba)
|
|
{
|
|
int max_command_entries = HISI_SAS_MAX_COMMANDS;
|
|
+ void *cachebuf = hisi_hba->debugfs_iost_cache;
|
|
void *databuf = hisi_hba->debugfs_iost;
|
|
struct hisi_sas_iost *iost;
|
|
int i;
|
|
|
|
+ hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE,
|
|
+ cachebuf);
|
|
+
|
|
iost = hisi_hba->iost;
|
|
|
|
for (i = 0; i < max_command_entries; i++, iost++) {
|
|
@@ -3475,6 +3483,46 @@ static const struct file_operations hisi_sas_debugfs_iost_fops = {
|
|
.owner = THIS_MODULE,
|
|
};
|
|
|
|
+static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p)
|
|
+{
|
|
+ struct hisi_hba *hisi_hba = s->private;
|
|
+ struct hisi_sas_iost_itct_cache *iost_cache =
|
|
+ (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_iost_cache;
|
|
+ u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
|
|
+ int i, tab_idx;
|
|
+ __le64 *iost;
|
|
+
|
|
+ for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) {
|
|
+ /*
|
|
+ * Data struct of IOST cache:
|
|
+ * Data[1]: BIT0~15: Table index
|
|
+ * Bit16: Valid mask
|
|
+ * Data[2]~[9]: IOST table
|
|
+ */
|
|
+ tab_idx = (iost_cache->data[1] & 0xffff);
|
|
+ iost = (__le64 *)iost_cache;
|
|
+
|
|
+ hisi_sas_show_row_64(s, tab_idx, cache_size, iost);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int hisi_sas_debugfs_iost_cache_open(struct inode *inode,
|
|
+ struct file *filp)
|
|
+{
|
|
+ return single_open(filp, hisi_sas_debugfs_iost_cache_show,
|
|
+ inode->i_private);
|
|
+}
|
|
+
|
|
+static const struct file_operations hisi_sas_debugfs_iost_cache_fops = {
|
|
+ .open = hisi_sas_debugfs_iost_cache_open,
|
|
+ .read = seq_read,
|
|
+ .llseek = seq_lseek,
|
|
+ .release = single_release,
|
|
+ .owner = THIS_MODULE,
|
|
+};
|
|
+
|
|
static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p)
|
|
{
|
|
int i, ret;
|
|
@@ -3506,6 +3554,46 @@ static const struct file_operations hisi_sas_debugfs_itct_fops = {
|
|
.owner = THIS_MODULE,
|
|
};
|
|
|
|
+static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p)
|
|
+{
|
|
+ struct hisi_hba *hisi_hba = s->private;
|
|
+ struct hisi_sas_iost_itct_cache *itct_cache =
|
|
+ (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_itct_cache;
|
|
+ u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
|
|
+ int i, tab_idx;
|
|
+ __le64 *itct;
|
|
+
|
|
+ for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) {
|
|
+ /*
|
|
+ * Data struct of ITCT cache:
|
|
+ * Data[1]: BIT0~15: Table index
|
|
+ * Bit16: Valid mask
|
|
+ * Data[2]~[9]: ITCT table
|
|
+ */
|
|
+ tab_idx = itct_cache->data[1] & 0xffff;
|
|
+ itct = (__le64 *)itct_cache;
|
|
+
|
|
+ hisi_sas_show_row_64(s, tab_idx, cache_size, itct);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int hisi_sas_debugfs_itct_cache_open(struct inode *inode,
|
|
+ struct file *filp)
|
|
+{
|
|
+ return single_open(filp, hisi_sas_debugfs_itct_cache_show,
|
|
+ inode->i_private);
|
|
+}
|
|
+
|
|
+static const struct file_operations hisi_sas_debugfs_itct_cache_fops = {
|
|
+ .open = hisi_sas_debugfs_itct_cache_open,
|
|
+ .read = seq_read,
|
|
+ .llseek = seq_lseek,
|
|
+ .release = single_release,
|
|
+ .owner = THIS_MODULE,
|
|
+};
|
|
+
|
|
static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
|
|
{
|
|
struct dentry *dump_dentry;
|
|
@@ -3558,9 +3646,15 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
|
|
debugfs_create_file("iost", 0400, dump_dentry, hisi_hba,
|
|
&hisi_sas_debugfs_iost_fops);
|
|
|
|
+ debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba,
|
|
+ &hisi_sas_debugfs_iost_cache_fops);
|
|
+
|
|
debugfs_create_file("itct", 0400, dump_dentry, hisi_hba,
|
|
&hisi_sas_debugfs_itct_fops);
|
|
|
|
+ debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba,
|
|
+ &hisi_sas_debugfs_itct_cache_fops);
|
|
+
|
|
return;
|
|
}
|
|
|
|
@@ -3715,14 +3809,26 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
|
|
goto fail_iost_dq;
|
|
}
|
|
|
|
- /* Alloc buffer for iost */
|
|
sz = max_command_entries * sizeof(struct hisi_sas_iost);
|
|
|
|
hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL);
|
|
if (!hisi_hba->debugfs_iost)
|
|
goto fail_iost_dq;
|
|
|
|
- /* Alloc buffer for itct */
|
|
+ sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
|
|
+ sizeof(struct hisi_sas_iost_itct_cache);
|
|
+
|
|
+ hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
|
|
+ if (!hisi_hba->debugfs_iost_cache)
|
|
+ goto fail_iost_cache;
|
|
+
|
|
+ sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
|
|
+ sizeof(struct hisi_sas_iost_itct_cache);
|
|
+
|
|
+ hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
|
|
+ if (!hisi_hba->debugfs_itct_cache)
|
|
+ goto fail_itct_cache;
|
|
+
|
|
/* New memory allocation must be locate before itct */
|
|
sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
|
|
|
|
@@ -3732,6 +3838,10 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
|
|
|
|
return;
|
|
fail_itct:
|
|
+ devm_kfree(dev, hisi_hba->debugfs_iost_cache);
|
|
+fail_itct_cache:
|
|
+ devm_kfree(dev, hisi_hba->debugfs_iost_cache);
|
|
+fail_iost_cache:
|
|
devm_kfree(dev, hisi_hba->debugfs_iost);
|
|
fail_iost_dq:
|
|
for (i = 0; i < d; i++)
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
index 12fc3b370265..974a72d164c5 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
@@ -79,6 +79,7 @@
|
|
#define HGC_DQE_ECC_MB_ADDR_OFF 16
|
|
#define HGC_DQE_ECC_MB_ADDR_MSK (0xfff << HGC_DQE_ECC_MB_ADDR_OFF)
|
|
#define CHNL_INT_STATUS 0x148
|
|
+#define TAB_DFX 0x14c
|
|
#define HGC_ITCT_ECC_ADDR 0x150
|
|
#define HGC_ITCT_ECC_1B_ADDR_OFF 0
|
|
#define HGC_ITCT_ECC_1B_ADDR_MSK (0x3ff << \
|
|
@@ -91,6 +92,7 @@
|
|
#define AXI_ERR_INFO_MSK (0xff << AXI_ERR_INFO_OFF)
|
|
#define FIFO_ERR_INFO_OFF 8
|
|
#define FIFO_ERR_INFO_MSK (0xff << FIFO_ERR_INFO_OFF)
|
|
+#define TAB_RD_TYPE 0x15c
|
|
#define INT_COAL_EN 0x19c
|
|
#define OQ_INT_COAL_TIME 0x1a0
|
|
#define OQ_INT_COAL_CNT 0x1a4
|
|
@@ -3406,6 +3408,35 @@ struct device_attribute *host_attrs_v3_hw[] = {
|
|
NULL
|
|
};
|
|
|
|
+static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba,
|
|
+ enum hisi_sas_debugfs_cache_type type,
|
|
+ u32 *cache)
|
|
+{
|
|
+ u32 cache_dw_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ *
|
|
+ HISI_SAS_IOST_ITCT_CACHE_NUM;
|
|
+ u32 *buf = cache;
|
|
+ u32 i, val;
|
|
+
|
|
+ hisi_sas_write32(hisi_hba, TAB_RD_TYPE, type);
|
|
+
|
|
+ for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_DW_SZ; i++) {
|
|
+ val = hisi_sas_read32(hisi_hba, TAB_DFX);
|
|
+ if (val == 0xffffffff)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (val != 0xffffffff) {
|
|
+ pr_err("Issue occur when reading IOST/ITCT cache!\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ memset(buf, 0, cache_dw_size * 4);
|
|
+ buf[0] = val;
|
|
+
|
|
+ for (i = 1; i < cache_dw_size; i++)
|
|
+ buf[i] = hisi_sas_read32(hisi_hba, TAB_DFX);
|
|
+}
|
|
+
|
|
static struct scsi_host_template sht_v3_hw = {
|
|
.name = DRV_NAME,
|
|
.module = THIS_MODULE,
|
|
@@ -3463,6 +3494,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
|
|
.set_bist = debugfs_set_bist_v3_hw,
|
|
.get_managed_irq_aff = get_managed_irq_aff_v3_hw,
|
|
.debugfs_work_handler = hisi_sas_debugfs_work_handler,
|
|
+ .read_iost_itct_cache = read_iost_itct_cache_v3_hw,
|
|
};
|
|
|
|
static struct Scsi_Host *
|
|
--
|
|
2.27.0
|
|
|