scsi: hisi_sas: Record the phy down event in debugfs
authorLuo Jiaxing <luojiaxing@huawei.com>
Thu, 24 Oct 2019 14:08:25 +0000 (22:08 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 25 Oct 2019 01:31:15 +0000 (21:31 -0400)
The number of phy down reflects the quality of the link between SAS
controller and disk. In order to allow the user to confirm the link quality
of the system, we record the number of phy down for each phy.

The user can check the current phy down count by reading the debugfs file
corresponding to the specific phy, or clear the phy down count by writing 0
to the debugfs file.

Link: https://lore.kernel.org/r/1571926105-74636-19-git-send-email-john.garry@huawei.com
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 72823222e08fe3dfe859eb08b616eea9f695cb19..233c73e01246cf5a4a046fcc974a694da7ce3a9a 100644 (file)
@@ -169,6 +169,7 @@ struct hisi_sas_phy {
        enum sas_linkrate       minimum_linkrate;
        enum sas_linkrate       maximum_linkrate;
        int enable;
+       atomic_t down_cnt;
 };
 
 struct hisi_sas_port {
index 669ad7463615682af6600f58b640c1eacf858257..18c95b33592b0fcd2d4ebb5e0477d85c8f5a8c95 100644 (file)
@@ -3705,6 +3705,52 @@ static const struct file_operations hisi_sas_debugfs_bist_enable_ops = {
        .owner = THIS_MODULE,
 };
 
+static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp,
+                                                  const char __user *buf,
+                                                  size_t count, loff_t *ppos)
+{
+       struct seq_file *s = filp->private_data;
+       struct hisi_sas_phy *phy = s->private;
+       unsigned int set_val;
+       int res;
+
+       res = kstrtouint_from_user(buf, count, 0, &set_val);
+       if (res)
+               return res;
+
+       if (set_val > 0)
+               return -EINVAL;
+
+       atomic_set(&phy->down_cnt, 0);
+
+       return count;
+}
+
+static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p)
+{
+       struct hisi_sas_phy *phy = s->private;
+
+       seq_printf(s, "%d\n", atomic_read(&phy->down_cnt));
+
+       return 0;
+}
+
+static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode,
+                                             struct file *filp)
+{
+       return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show,
+                          inode->i_private);
+}
+
+static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = {
+       .open = hisi_sas_debugfs_phy_down_cnt_open,
+       .read = seq_read,
+       .write = hisi_sas_debugfs_phy_down_cnt_write,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
 void hisi_sas_debugfs_work_handler(struct work_struct *work)
 {
        struct hisi_hba *hisi_hba =
@@ -3839,6 +3885,21 @@ fail:
        return -ENOMEM;
 }
 
+static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba)
+{
+       struct dentry *dir = debugfs_create_dir("phy_down_cnt",
+                                               hisi_hba->debugfs_dir);
+       char name[16];
+       int phy_no;
+
+       for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
+               snprintf(name, 16, "%d", phy_no);
+               debugfs_create_file(name, 0600, dir,
+                                   &hisi_hba->phy[phy_no],
+                                   &hisi_sas_debugfs_phy_down_cnt_ops);
+       }
+}
+
 static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba)
 {
        hisi_hba->debugfs_bist_dentry =
@@ -3885,6 +3946,8 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
        hisi_hba->debugfs_dump_dentry =
                        debugfs_create_dir("dump", hisi_hba->debugfs_dir);
 
+       hisi_sas_debugfs_phy_down_cnt_init(hisi_hba);
+
        for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
                if (hisi_sas_debugfs_alloc(hisi_hba, i)) {
                        debugfs_remove_recursive(hisi_hba->debugfs_dir);
index e4da309009c0f184e154695cbe78d7a958bfdc47..2ae7070db41a268c0c599f390b99ae029a760c27 100644 (file)
@@ -1549,6 +1549,8 @@ static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
        u32 phy_state, sl_ctrl, txid_auto;
        struct device *dev = hisi_hba->dev;
 
+       atomic_inc(&phy->down_cnt);
+
        del_timer(&phy->timer);
        hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);