scsi: hisi_sas: Alloc debugfs snapshot buffer memory for all registers
authorLuo Jiaxing <luojiaxing@huawei.com>
Wed, 19 Dec 2018 15:56:40 +0000 (23:56 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 9 Jan 2019 02:58:37 +0000 (21:58 -0500)
This patch allocates snapshot memory for global reg, port regs, CQ, DQ,
IOST, ITCT.

When we fail to allocate memory for some registers, we free the memory
and set hisi_sas_debugfs_enable as 0 to stop loading debugfs from running.

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>
drivers/scsi/hisi_sas/hisi_sas.h
drivers/scsi/hisi_sas/hisi_sas_main.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

index 3ad87462593bdc60bf4e259a45578d9e02259e15..eca7e474ea018bb39d2e35768f10844b6fbc5a40 100644 (file)
@@ -221,6 +221,10 @@ struct hisi_sas_slot {
        u16     idx;
 };
 
+struct hisi_sas_debugfs_reg {
+       int count;
+};
+
 struct hisi_sas_hw {
        int (*hw_init)(struct hisi_hba *hisi_hba);
        void (*setup_itct)(struct hisi_hba *hisi_hba,
@@ -265,6 +269,9 @@ struct hisi_sas_hw {
        int max_command_entries;
        int complete_hdr_size;
        struct scsi_host_template *sht;
+
+       const struct hisi_sas_debugfs_reg *debugfs_reg_global;
+       const struct hisi_sas_debugfs_reg *debugfs_reg_port;
 };
 
 struct hisi_hba {
@@ -334,6 +341,14 @@ struct hisi_hba {
        u32 intr_coal_ticks;    /* Time of interrupt coalesce in us */
        u32 intr_coal_count;    /* Interrupt count to coalesce */
 
+       /* debugfs memories */
+       void *debugfs_global_reg;
+       void *debugfs_port_reg[HISI_SAS_MAX_PHYS];
+       void *debugfs_complete_hdr[HISI_SAS_MAX_QUEUES];
+       struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES];
+       struct hisi_sas_iost *debugfs_iost;
+       struct hisi_sas_itct *debugfs_itct;
+
        struct dentry *debugfs_dir;
 };
 
index 919cd3bd746a2c578125aab5203dc3fc0411bb33..0b0dbaabcce8c7a01859736a2f6da599158c6898 100644 (file)
@@ -2461,10 +2461,86 @@ struct dentry *hisi_sas_debugfs_dir;
 
 void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
 {
+       int max_command_entries = hisi_hba->hw->max_command_entries;
        struct device *dev = hisi_hba->dev;
+       int p, i, c, d;
+       size_t sz;
 
        hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
                                                   hisi_sas_debugfs_dir);
+
+       if (!hisi_hba->debugfs_dir)
+               return;
+
+       /* Alloc buffer for global */
+       sz = hisi_hba->hw->debugfs_reg_global->count * 4;
+       hisi_hba->debugfs_global_reg =
+               devm_kmalloc(dev, sz, GFP_KERNEL);
+
+       if (!hisi_hba->debugfs_global_reg)
+               goto fail_global;
+
+       /* Alloc buffer for port */
+       sz = hisi_hba->hw->debugfs_reg_port->count * 4;
+       for (p = 0; p < hisi_hba->n_phy; p++) {
+               hisi_hba->debugfs_port_reg[p] =
+                       devm_kmalloc(dev, sz, GFP_KERNEL);
+
+               if (!hisi_hba->debugfs_port_reg[p])
+                       goto fail_port;
+       }
+
+       /* Alloc buffer for cq */
+       sz = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
+       for (c = 0; c < hisi_hba->queue_count; c++) {
+               hisi_hba->debugfs_complete_hdr[c] =
+                       devm_kmalloc(dev, sz, GFP_KERNEL);
+
+               if (!hisi_hba->debugfs_complete_hdr[c])
+                       goto fail_cq;
+       }
+
+       /* Alloc buffer for dq */
+       sz = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
+       for (d = 0; d < hisi_hba->queue_count; d++) {
+               hisi_hba->debugfs_cmd_hdr[d] =
+                       devm_kmalloc(dev, sz, GFP_KERNEL);
+
+               if (!hisi_hba->debugfs_cmd_hdr[d])
+                       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 */
+       /* New memory allocation must be locate before itct */
+       sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
+
+       hisi_hba->debugfs_itct = devm_kmalloc(dev, sz, GFP_KERNEL);
+       if (!hisi_hba->debugfs_itct)
+               goto fail_itct;
+
+       return;
+fail_itct:
+       devm_kfree(dev, hisi_hba->debugfs_iost);
+fail_iost_dq:
+       for (i = 0; i < d; i++)
+               devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]);
+fail_cq:
+       for (i = 0; i < c; i++)
+               devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]);
+fail_port:
+       for (i = 0; i < p; i++)
+               devm_kfree(dev, hisi_hba->debugfs_port_reg[i]);
+       devm_kfree(dev, hisi_hba->debugfs_global_reg);
+fail_global:
+       debugfs_remove_recursive(hisi_hba->debugfs_dir);
+       dev_dbg(dev, "failed to init debugfs!\n");
 }
 EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init);
 
index a7d9651d1ec3aaf77769a9c918e93c412e71d4e3..c1b47022d6fd5b8f83233fba38adc144da38dc6c 100644 (file)
@@ -2332,6 +2332,12 @@ static struct device_attribute *host_attrs_v3_hw[] = {
        NULL
 };
 
+static const struct hisi_sas_debugfs_reg debugfs_port_reg = {
+};
+
+static const struct hisi_sas_debugfs_reg debugfs_global_reg = {
+};
+
 static struct scsi_host_template sht_v3_hw = {
        .name                   = DRV_NAME,
        .module                 = THIS_MODULE,
@@ -2380,6 +2386,8 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
        .get_events = phy_get_events_v3_hw,
        .write_gpio = write_gpio_v3_hw,
        .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw,
+       .debugfs_reg_global = &debugfs_global_reg,
+       .debugfs_reg_port = &debugfs_port_reg,
 };
 
 static struct Scsi_Host *