From 847e8355294597898ed3b6c2a3130ab962d03004 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Tue, 1 Sep 2020 19:13:03 +0800 Subject: scsi: hisi_sas: Avoid accessing to SSP task for SMP I/Os hisi_sas_slot_task_free() attempts to dereference SSP task for non-ATA tasks. If the task is SMP, the code may reference the wrong structure although this may not cause any problems. To avoid this, only access to SSP task when slot->n_elem_dif is not 0 which indicates this is an SSP task. Link: https://lore.kernel.org/r/1598958790-232272-2-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 11caa4b0d797..fdf5f0f1b60b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -229,17 +229,18 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, task->lldd_task = NULL; if (!sas_protocol_ata(task->task_proto)) { - struct sas_ssp_task *ssp_task = &task->ssp_task; - struct scsi_cmnd *scsi_cmnd = ssp_task->cmd; - if (slot->n_elem) dma_unmap_sg(dev, task->scatter, task->num_scatter, task->data_dir); - if (slot->n_elem_dif) + if (slot->n_elem_dif) { + struct sas_ssp_task *ssp_task = &task->ssp_task; + struct scsi_cmnd *scsi_cmnd = ssp_task->cmd; + dma_unmap_sg(dev, scsi_prot_sglist(scsi_cmnd), scsi_prot_sg_count(scsi_cmnd), task->data_dir); + } } } -- cgit v1.2.3 From 4b3a1f1feda62b0b15536548b6d31ca549de2e3a Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Tue, 1 Sep 2020 19:13:04 +0800 Subject: scsi: hisi_sas: Modify macro name for OOB phy linkrate The macro for OOB phy linkrate is named CFG_PROG_PHY_LINK_RATE_* but that is inaccurate. For clarification, include OOB in macro name. Link: https://lore.kernel.org/r/1598958790-232272-3-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 60adf5c32143..05b60cdf6b24 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -191,8 +191,8 @@ #define PHY_CFG_PHY_RST_OFF 3 #define PHY_CFG_PHY_RST_MSK (0x1 << PHY_CFG_PHY_RST_OFF) #define PROG_PHY_LINK_RATE (PORT_BASE + 0x8) -#define CFG_PROG_PHY_LINK_RATE_OFF 8 -#define CFG_PROG_PHY_LINK_RATE_MSK (0xf << CFG_PROG_PHY_LINK_RATE_OFF) +#define CFG_PROG_OOB_PHY_LINK_RATE_OFF 8 +#define CFG_PROG_OOB_PHY_LINK_RATE_MSK (0xf << CFG_PROG_OOB_PHY_LINK_RATE_OFF) #define PHY_CTRL (PORT_BASE + 0x14) #define PHY_CTRL_RESET_OFF 0 #define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF) @@ -2998,8 +2998,8 @@ static void hisi_sas_bist_test_restore_v3_hw(struct hisi_hba *hisi_hba) /* restore the linkrate */ reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, PROG_PHY_LINK_RATE); /* init OOB link rate as 1.5 Gbits */ - reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK; - reg_val |= (0x8 << CFG_PROG_PHY_LINK_RATE_OFF); + reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK; + reg_val |= (0x8 << CFG_PROG_OOB_PHY_LINK_RATE_OFF); hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val); /* enable PHY */ @@ -3027,8 +3027,8 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) /* set linkrate of bit test*/ reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, PROG_PHY_LINK_RATE); - reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK; - reg_val |= (linkrate << CFG_PROG_PHY_LINK_RATE_OFF); + reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK; + reg_val |= (linkrate << CFG_PROG_OOB_PHY_LINK_RATE_OFF); hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val); @@ -3050,8 +3050,7 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) hisi_sas_phy_write32(hisi_hba, phy_id, SAS_PHY_BIST_CODE, SAS_PHY_BIST_CODE_INIT); - hisi_sas_phy_write32(hisi_hba, phy_id, - SAS_PHY_BIST_CODE1, + hisi_sas_phy_write32(hisi_hba, phy_id, SAS_PHY_BIST_CODE1, SAS_PHY_BIST_CODE1_INIT); mdelay(100); -- cgit v1.2.3 From caeddc0453b9215669a39ea335f1af1f3f91cc99 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Tue, 1 Sep 2020 19:13:05 +0800 Subject: scsi: hisi_sas: Do not modify upper fields of PROG_PHY_LINK_RATE reg When updating PROG_PHY_LINK_RATE to set linkrate for a phy we used a hard-coded initial value instead of getting the current value from the register. The assumption was that this register would not be modified, but in fact it was partially modified in a new version of hardware. The hard-coded value we used changed the default value of the register to a an incorrect setting and as a result the SAS controller could not change linkrate for the phy. Delete hard-coded value and always read the latest value of register before updating it. Link: https://lore.kernel.org/r/1598958790-232272-4-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 05b60cdf6b24..b7d94f2e49ae 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -191,6 +191,8 @@ #define PHY_CFG_PHY_RST_OFF 3 #define PHY_CFG_PHY_RST_MSK (0x1 << PHY_CFG_PHY_RST_OFF) #define PROG_PHY_LINK_RATE (PORT_BASE + 0x8) +#define CFG_PROG_PHY_LINK_RATE_OFF 0 +#define CFG_PROG_PHY_LINK_RATE_MSK (0xff << CFG_PROG_PHY_LINK_RATE_OFF) #define CFG_PROG_OOB_PHY_LINK_RATE_OFF 8 #define CFG_PROG_OOB_PHY_LINK_RATE_MSK (0xf << CFG_PROG_OOB_PHY_LINK_RATE_OFF) #define PHY_CTRL (PORT_BASE + 0x14) @@ -598,20 +600,19 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); for (i = 0; i < hisi_hba->n_phy; i++) { + enum sas_linkrate max; struct hisi_sas_phy *phy = &hisi_hba->phy[i]; struct asd_sas_phy *sas_phy = &phy->sas_phy; - u32 prog_phy_link_rate = 0x800; + u32 prog_phy_link_rate = hisi_sas_phy_read32(hisi_hba, i, + PROG_PHY_LINK_RATE); + prog_phy_link_rate &= ~CFG_PROG_PHY_LINK_RATE_MSK; if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate < - SAS_LINK_RATE_1_5_GBPS)) { - prog_phy_link_rate = 0x855; - } else { - enum sas_linkrate max = sas_phy->phy->maximum_linkrate; - - prog_phy_link_rate = - hisi_sas_get_prog_phy_linkrate_mask(max) | - 0x800; - } + SAS_LINK_RATE_1_5_GBPS)) + max = SAS_LINK_RATE_12_0_GBPS; + else + max = sas_phy->phy->maximum_linkrate; + prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max); hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, prog_phy_link_rate); hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00); @@ -2501,8 +2502,10 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no, struct sas_phy_linkrates *r) { enum sas_linkrate max = r->maximum_linkrate; - u32 prog_phy_link_rate = 0x800; + u32 prog_phy_link_rate = hisi_sas_phy_read32(hisi_hba, phy_no, + PROG_PHY_LINK_RATE); + prog_phy_link_rate &= ~CFG_PROG_PHY_LINK_RATE_MSK; prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max); hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, prog_phy_link_rate); -- cgit v1.2.3 From ca06f2cd01d08fe01b155ee774a2c6518b03b275 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Tue, 1 Sep 2020 19:13:06 +0800 Subject: scsi: hisi_sas: Make phy index variable name consistent We use "phy_id" to identify phy in the BIST code but the rest of code always uses "phy_no". Change it for consistency. Link: https://lore.kernel.org/r/1598958790-232272-5-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 50 +++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index b7d94f2e49ae..8a5c6f5e2a7a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2971,42 +2971,42 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba) { u32 reg_val; - int phy_id = hisi_hba->debugfs_bist_phy_no; + int phy_no = hisi_hba->debugfs_bist_phy_no; /* disable PHY */ - hisi_sas_phy_enable(hisi_hba, phy_id, 0); + hisi_sas_phy_enable(hisi_hba, phy_no, 0); /* disable ALOS */ - reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG); + reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG); reg_val |= CFG_ALOS_CHK_DISABLE_MSK; - hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val); + hisi_sas_phy_write32(hisi_hba, phy_no, SERDES_CFG, reg_val); } static void hisi_sas_bist_test_restore_v3_hw(struct hisi_hba *hisi_hba) { u32 reg_val; - int phy_id = hisi_hba->debugfs_bist_phy_no; + int phy_no = hisi_hba->debugfs_bist_phy_no; /* disable loopback */ - reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL); + reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL); reg_val &= ~(CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK | CFG_BIST_TEST_MSK); - hisi_sas_phy_write32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL, reg_val); + hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, reg_val); /* enable ALOS */ - reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG); + reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG); reg_val &= ~CFG_ALOS_CHK_DISABLE_MSK; - hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val); + hisi_sas_phy_write32(hisi_hba, phy_no, SERDES_CFG, reg_val); /* restore the linkrate */ - reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, PROG_PHY_LINK_RATE); + reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE); /* init OOB link rate as 1.5 Gbits */ reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK; reg_val |= (0x8 << CFG_PROG_OOB_PHY_LINK_RATE_OFF); - hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val); + hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, reg_val); /* enable PHY */ - hisi_sas_phy_enable(hisi_hba, phy_id, 1); + hisi_sas_phy_enable(hisi_hba, phy_no, 1); } #define SAS_PHY_BIST_CODE_INIT 0x1 @@ -3015,28 +3015,28 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) { u32 reg_val, mode_tmp; u32 linkrate = hisi_hba->debugfs_bist_linkrate; - u32 phy_id = hisi_hba->debugfs_bist_phy_no; + u32 phy_no = hisi_hba->debugfs_bist_phy_no; u32 code_mode = hisi_hba->debugfs_bist_code_mode; u32 path_mode = hisi_hba->debugfs_bist_mode; struct device *dev = hisi_hba->dev; - dev_info(dev, "BIST info:linkrate=%d phy_id=%d code_mode=%d path_mode=%d\n", - linkrate, phy_id, code_mode, path_mode); + dev_info(dev, "BIST info:linkrate=%d phy_no=%d code_mode=%d path_mode=%d\n", + linkrate, phy_no, code_mode, path_mode); mode_tmp = path_mode ? 2 : 1; if (enable) { /* some preparations before bist test */ hisi_sas_bist_test_prep_v3_hw(hisi_hba); /* set linkrate of bit test*/ - reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, + reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE); reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK; reg_val |= (linkrate << CFG_PROG_OOB_PHY_LINK_RATE_OFF); - hisi_sas_phy_write32(hisi_hba, phy_id, - PROG_PHY_LINK_RATE, reg_val); + hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, + reg_val); /* set code mode of bit test */ - reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, + reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL); reg_val &= ~(CFG_BIST_MODE_SEL_MSK | CFG_LOOP_TEST_MODE_MSK | @@ -3046,28 +3046,28 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) reg_val |= ((code_mode << CFG_BIST_MODE_SEL_OFF) | (mode_tmp << CFG_LOOP_TEST_MODE_OFF) | CFG_BIST_TEST_MSK); - hisi_sas_phy_write32(hisi_hba, phy_id, + hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, reg_val); /* set the bist init value */ - hisi_sas_phy_write32(hisi_hba, phy_id, + hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CODE, SAS_PHY_BIST_CODE_INIT); - hisi_sas_phy_write32(hisi_hba, phy_id, SAS_PHY_BIST_CODE1, + hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CODE1, SAS_PHY_BIST_CODE1_INIT); mdelay(100); reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK); - hisi_sas_phy_write32(hisi_hba, phy_id, + hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, reg_val); /* clear error bit */ mdelay(100); - hisi_sas_phy_read32(hisi_hba, phy_id, SAS_BIST_ERR_CNT); + hisi_sas_phy_read32(hisi_hba, phy_no, SAS_BIST_ERR_CNT); } else { /* disable bist test and recover it */ hisi_hba->debugfs_bist_cnt += hisi_sas_phy_read32(hisi_hba, - phy_id, SAS_BIST_ERR_CNT); + phy_no, SAS_BIST_ERR_CNT); hisi_sas_bist_test_restore_v3_hw(hisi_hba); } -- cgit v1.2.3 From 2c4d582322ff412f83f5c538e33c9440a30db73d Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Tue, 1 Sep 2020 19:13:07 +0800 Subject: scsi: hisi_sas: Add BIST support for phy FFE Add BIST support for phy FFE (Feed forward equalizer) setting. The user can configure FFE through the new debugfs interface. FFE is a parameter used for link layer control. It will affect the link quality between the SAS controller and the backplane. In the BIST test, the FFE interface is provided to assist board testers in optimizing link parameters. The modification of the FFE parameter will affect the test after BIST or the normal running of the board. The user should save the initial FFE values and restore them after BIST test is complete. Link: https://lore.kernel.org/r/1598958790-232272-6-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 13 ++++++ drivers/scsi/hisi_sas/hisi_sas_main.c | 76 ++++++++++++++++++++++++++++++++++ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 25 +++++++++-- 3 files changed, 111 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 2bdd64648ef0..ce6a7d212afe 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -273,6 +273,18 @@ enum hisi_sas_debugfs_cache_type { HISI_SAS_IOST_CACHE, }; +enum hisi_sas_debugfs_bist_ffe_cfg { + FFE_SAS_1_5_GBPS, + FFE_SAS_3_0_GBPS, + FFE_SAS_6_0_GBPS, + FFE_SAS_12_0_GBPS, + FFE_RESV, + FFE_SATA_1_5_GBPS, + FFE_SATA_3_0_GBPS, + FFE_SATA_6_0_GBPS, + FFE_CFG_MAX +}; + struct hisi_sas_hw { int (*hw_init)(struct hisi_hba *hisi_hba); void (*setup_itct)(struct hisi_hba *hisi_hba, @@ -440,6 +452,7 @@ struct hisi_hba { int debugfs_bist_mode; u32 debugfs_bist_cnt; int debugfs_bist_enable; + u32 debugfs_bist_ffe[HISI_SAS_MAX_PHYS][FFE_CFG_MAX]; /* debugfs memories */ /* Put Global AXI and RAS Register into register array */ diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index fdf5f0f1b60b..6cd9b25fbbe7 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -3704,6 +3704,58 @@ static const struct file_operations hisi_sas_debugfs_bist_enable_ops = { .owner = THIS_MODULE, }; +static const struct { + char *name; +} hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = { + { "SAS_1_5_GBPS" }, + { "SAS_3_0_GBPS" }, + { "SAS_6_0_GBPS" }, + { "SAS_12_0_GBPS" }, + { "FFE_RESV" }, + { "SATA_1_5_GBPS" }, + { "SATA_3_0_GBPS" }, + { "SATA_6_0_GBPS" }, +}; + +static ssize_t hisi_sas_debugfs_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + u32 *val = m->private; + int res; + + res = kstrtouint_from_user(buf, count, 0, val); + if (res) + return res; + + return count; +} + +static int hisi_sas_debugfs_show(struct seq_file *s, void *p) +{ + u32 *val = s->private; + + seq_printf(s, "0x%x\n", *val); + + return 0; +} + +static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_ops = { + .open = hisi_sas_debugfs_open, + .read = seq_read, + .write = hisi_sas_debugfs_write, + .llseek = seq_lseek, + .release = single_release, + .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) @@ -3901,6 +3953,9 @@ static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba) static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba) { + struct dentry *ports_dentry; + int phy_no; + hisi_hba->debugfs_bist_dentry = debugfs_create_dir("bist", hisi_hba->debugfs_dir); debugfs_create_file("link_rate", 0600, @@ -3924,6 +3979,27 @@ static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba) debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry, hisi_hba, &hisi_sas_debugfs_bist_enable_ops); + ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry); + + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { + struct dentry *port_dentry; + struct dentry *ffe_dentry; + char name[256]; + int i; + + snprintf(name, 256, "%d", phy_no); + port_dentry = debugfs_create_dir(name, ports_dentry); + ffe_dentry = debugfs_create_dir("ffe", port_dentry); + for (i = 0; i < FFE_CFG_MAX; i++) { + if (i == FFE_RESV) + continue; + debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name, + 0600, ffe_dentry, + &hisi_hba->debugfs_bist_ffe[phy_no][i], + &hisi_sas_debugfs_ops); + } + } + hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 8a5c6f5e2a7a..f5d566832d6c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -297,6 +297,7 @@ #define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF) #define COARSETUNE_TIME (PORT_BASE + 0x304) +#define TXDEEMPH_G1 (PORT_BASE + 0x350) #define ERR_CNT_DWS_LOST (PORT_BASE + 0x380) #define ERR_CNT_RESET_PROB (PORT_BASE + 0x384) #define ERR_CNT_INVLD_DW (PORT_BASE + 0x390) @@ -567,7 +568,7 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba, static void init_reg_v3_hw(struct hisi_hba *hisi_hba) { - int i; + int i, j; /* Global registers init */ hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, @@ -637,6 +638,13 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) /* used for 12G negotiate */ hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff); + + /* get default FFE configuration for BIST */ + for (j = 0; j < FFE_CFG_MAX; j++) { + u32 val = hisi_sas_phy_read32(hisi_hba, i, + TXDEEMPH_G1 + (j * 0x4)); + hisi_hba->debugfs_bist_ffe[i][j] = val; + } } for (i = 0; i < hisi_hba->queue_count; i++) { @@ -2972,10 +2980,16 @@ static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba) { u32 reg_val; int phy_no = hisi_hba->debugfs_bist_phy_no; + int i; /* disable PHY */ hisi_sas_phy_enable(hisi_hba, phy_no, 0); + /* update FFE */ + for (i = 0; i < FFE_CFG_MAX; i++) + hisi_sas_phy_write32(hisi_hba, phy_no, TXDEEMPH_G1 + (i * 0x4), + hisi_hba->debugfs_bist_ffe[phy_no][i]); + /* disable ALOS */ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG); reg_val |= CFG_ALOS_CHK_DISABLE_MSK; @@ -3016,12 +3030,17 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) u32 reg_val, mode_tmp; u32 linkrate = hisi_hba->debugfs_bist_linkrate; u32 phy_no = hisi_hba->debugfs_bist_phy_no; + u32 *ffe = hisi_hba->debugfs_bist_ffe[phy_no]; u32 code_mode = hisi_hba->debugfs_bist_code_mode; u32 path_mode = hisi_hba->debugfs_bist_mode; struct device *dev = hisi_hba->dev; - dev_info(dev, "BIST info:linkrate=%d phy_no=%d code_mode=%d path_mode=%d\n", - linkrate, phy_no, code_mode, path_mode); + dev_info(dev, "BIST info:phy%d link_rate=%d code_mode=%d path_mode=%d ffe={0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x}\n", + phy_no, linkrate, code_mode, path_mode, + ffe[FFE_SAS_1_5_GBPS], ffe[FFE_SAS_3_0_GBPS], + ffe[FFE_SAS_6_0_GBPS], ffe[FFE_SAS_12_0_GBPS], + ffe[FFE_SATA_1_5_GBPS], ffe[FFE_SATA_3_0_GBPS], + ffe[FFE_SATA_6_0_GBPS]); mode_tmp = path_mode ? 2 : 1; if (enable) { /* some preparations before bist test */ -- cgit v1.2.3 From 981cc23e741a641ca92c37c7a3df180ced702118 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Tue, 1 Sep 2020 19:13:08 +0800 Subject: scsi: hisi_sas: Add BIST support for fixed code pattern Through the new debugfs interface the user can select fixed code patterns. Add two new interfaces fixed_code and fixed_code1. Link: https://lore.kernel.org/r/1598958790-232272-7-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 22 +++++++++++++++++ drivers/scsi/hisi_sas/hisi_sas_main.c | 25 ++++++++------------ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 43 +++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 31 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index ce6a7d212afe..c617ac8d8315 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -285,6 +285,27 @@ enum hisi_sas_debugfs_bist_ffe_cfg { FFE_CFG_MAX }; +enum hisi_sas_debugfs_bist_fixed_code { + FIXED_CODE, + FIXED_CODE_1, + FIXED_CODE_MAX +}; + +enum { + HISI_SAS_BIST_CODE_MODE_PRBS7, + HISI_SAS_BIST_CODE_MODE_PRBS23, + HISI_SAS_BIST_CODE_MODE_PRBS31, + HISI_SAS_BIST_CODE_MODE_JTPAT, + HISI_SAS_BIST_CODE_MODE_CJTPAT, + HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, + HISI_SAS_BIST_CODE_MODE_TRAIN, + HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, + HISI_SAS_BIST_CODE_MODE_HFTP, + HISI_SAS_BIST_CODE_MODE_MFTP, + HISI_SAS_BIST_CODE_MODE_LFTP, + HISI_SAS_BIST_CODE_MODE_FIXED_DATA, +}; + struct hisi_sas_hw { int (*hw_init)(struct hisi_hba *hisi_hba); void (*setup_itct)(struct hisi_hba *hisi_hba, @@ -453,6 +474,7 @@ struct hisi_hba { u32 debugfs_bist_cnt; int debugfs_bist_enable; u32 debugfs_bist_ffe[HISI_SAS_MAX_PHYS][FFE_CFG_MAX]; + u32 debugfs_bist_fixed_code[FIXED_CODE_MAX]; /* debugfs memories */ /* Put Global AXI and RAS Register into register array */ diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 6cd9b25fbbe7..6d1e42389cd6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -3334,21 +3334,6 @@ enum { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, }; -enum { - HISI_SAS_BIST_CODE_MODE_PRBS7 = 0, - HISI_SAS_BIST_CODE_MODE_PRBS23, - HISI_SAS_BIST_CODE_MODE_PRBS31, - HISI_SAS_BIST_CODE_MODE_JTPAT, - HISI_SAS_BIST_CODE_MODE_CJTPAT, - HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, - HISI_SAS_BIST_CODE_MODE_TRAIN, - HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, - HISI_SAS_BIST_CODE_MODE_HFTP, - HISI_SAS_BIST_CODE_MODE_MFTP, - HISI_SAS_BIST_CODE_MODE_LFTP, - HISI_SAS_BIST_CODE_MODE_FIXED_DATA, -}; - static const struct { int value; char *name; @@ -3966,6 +3951,16 @@ static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba) hisi_hba->debugfs_bist_dentry, hisi_hba, &hisi_sas_debugfs_bist_code_mode_ops); + debugfs_create_file("fixed_code", 0600, + hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_fixed_code[0], + &hisi_sas_debugfs_ops); + + debugfs_create_file("fixed_code_1", 0600, + hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_fixed_code[1], + &hisi_sas_debugfs_ops); + debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, hisi_hba, &hisi_sas_debugfs_bist_phy_ops); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index f5d566832d6c..8522f693033f 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3033,14 +3033,16 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) u32 *ffe = hisi_hba->debugfs_bist_ffe[phy_no]; u32 code_mode = hisi_hba->debugfs_bist_code_mode; u32 path_mode = hisi_hba->debugfs_bist_mode; + u32 *fix_code = &hisi_hba->debugfs_bist_fixed_code[0]; struct device *dev = hisi_hba->dev; - dev_info(dev, "BIST info:phy%d link_rate=%d code_mode=%d path_mode=%d ffe={0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x}\n", + dev_info(dev, "BIST info:phy%d link_rate=%d code_mode=%d path_mode=%d ffe={0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x} fixed_code={0x%x, 0x%x}\n", phy_no, linkrate, code_mode, path_mode, ffe[FFE_SAS_1_5_GBPS], ffe[FFE_SAS_3_0_GBPS], ffe[FFE_SAS_6_0_GBPS], ffe[FFE_SAS_12_0_GBPS], ffe[FFE_SATA_1_5_GBPS], ffe[FFE_SATA_3_0_GBPS], - ffe[FFE_SATA_6_0_GBPS]); + ffe[FFE_SATA_6_0_GBPS], fix_code[FIXED_CODE], + fix_code[FIXED_CODE_1]); mode_tmp = path_mode ? 2 : 1; if (enable) { /* some preparations before bist test */ @@ -3057,28 +3059,37 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) /* set code mode of bit test */ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL); - reg_val &= ~(CFG_BIST_MODE_SEL_MSK | - CFG_LOOP_TEST_MODE_MSK | - CFG_RX_BIST_EN_MSK | - CFG_TX_BIST_EN_MSK | - CFG_BIST_TEST_MSK); + reg_val &= ~(CFG_BIST_MODE_SEL_MSK | CFG_LOOP_TEST_MODE_MSK | + CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK | + CFG_BIST_TEST_MSK); reg_val |= ((code_mode << CFG_BIST_MODE_SEL_OFF) | (mode_tmp << CFG_LOOP_TEST_MODE_OFF) | CFG_BIST_TEST_MSK); - hisi_sas_phy_write32(hisi_hba, phy_no, - SAS_PHY_BIST_CTRL, reg_val); + hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, + reg_val); /* set the bist init value */ - hisi_sas_phy_write32(hisi_hba, phy_no, - SAS_PHY_BIST_CODE, - SAS_PHY_BIST_CODE_INIT); - hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CODE1, - SAS_PHY_BIST_CODE1_INIT); + if (code_mode == HISI_SAS_BIST_CODE_MODE_FIXED_DATA) { + reg_val = hisi_hba->debugfs_bist_fixed_code[0]; + hisi_sas_phy_write32(hisi_hba, phy_no, + SAS_PHY_BIST_CODE, reg_val); + + reg_val = hisi_hba->debugfs_bist_fixed_code[1]; + hisi_sas_phy_write32(hisi_hba, phy_no, + SAS_PHY_BIST_CODE1, reg_val); + } else { + hisi_sas_phy_write32(hisi_hba, phy_no, + SAS_PHY_BIST_CODE, + SAS_PHY_BIST_CODE_INIT); + hisi_sas_phy_write32(hisi_hba, phy_no, + SAS_PHY_BIST_CODE1, + SAS_PHY_BIST_CODE1_INIT); + } mdelay(100); reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK); - hisi_sas_phy_write32(hisi_hba, phy_no, - SAS_PHY_BIST_CTRL, reg_val); + hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, + reg_val); /* clear error bit */ mdelay(100); -- cgit v1.2.3 From b601577df68af896e563ca62ca07d8681912eabc Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Tue, 1 Sep 2020 19:13:09 +0800 Subject: scsi: hisi_sas: Add missing newlines Newline is missing from some printk() statements. Add them. Link: https://lore.kernel.org/r/1598958790-232272-8-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 24 ++++++++++++------------ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 6d1e42389cd6..f5ad8e662b4b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -335,7 +335,7 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, } if (*n_elem > HISI_SAS_SGE_PAGE_CNT) { - dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT", + dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT\n", *n_elem); rc = -EINVAL; goto err_out_dma_unmap; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 7922a9bb1b28..45e866cb9164 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -752,7 +752,7 @@ static int hw_init_v1_hw(struct hisi_hba *hisi_hba) rc = reset_hw_v1_hw(hisi_hba); if (rc) { - dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc); + dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc); return rc; } @@ -1166,7 +1166,7 @@ static void slot_err_v1_hw(struct hisi_hba *hisi_hba, case SAS_PROTOCOL_STP: case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: { - dev_err(dev, "slot err: SATA/STP not supported"); + dev_err(dev, "slot err: SATA/STP not supported\n"); } break; default: @@ -1218,35 +1218,35 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, u32 info_reg = hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO); if (info_reg & HGC_INVLD_DQE_INFO_DQ_MSK) - dev_err(dev, "slot complete: [%d:%d] has dq IPTT err", + dev_err(dev, "slot complete: [%d:%d] has dq IPTT err\n", slot->cmplt_queue, slot->cmplt_queue_slot); if (info_reg & HGC_INVLD_DQE_INFO_TYPE_MSK) - dev_err(dev, "slot complete: [%d:%d] has dq type err", + dev_err(dev, "slot complete: [%d:%d] has dq type err\n", slot->cmplt_queue, slot->cmplt_queue_slot); if (info_reg & HGC_INVLD_DQE_INFO_FORCE_MSK) - dev_err(dev, "slot complete: [%d:%d] has dq force phy err", + dev_err(dev, "slot complete: [%d:%d] has dq force phy err\n", slot->cmplt_queue, slot->cmplt_queue_slot); if (info_reg & HGC_INVLD_DQE_INFO_PHY_MSK) - dev_err(dev, "slot complete: [%d:%d] has dq phy id err", + dev_err(dev, "slot complete: [%d:%d] has dq phy id err\n", slot->cmplt_queue, slot->cmplt_queue_slot); if (info_reg & HGC_INVLD_DQE_INFO_ABORT_MSK) - dev_err(dev, "slot complete: [%d:%d] has dq abort flag err", + dev_err(dev, "slot complete: [%d:%d] has dq abort flag err\n", slot->cmplt_queue, slot->cmplt_queue_slot); if (info_reg & HGC_INVLD_DQE_INFO_IPTT_OF_MSK) - dev_err(dev, "slot complete: [%d:%d] has dq IPTT or ICT err", + dev_err(dev, "slot complete: [%d:%d] has dq IPTT or ICT err\n", slot->cmplt_queue, slot->cmplt_queue_slot); if (info_reg & HGC_INVLD_DQE_INFO_SSP_ERR_MSK) - dev_err(dev, "slot complete: [%d:%d] has dq SSP frame type err", + dev_err(dev, "slot complete: [%d:%d] has dq SSP frame type err\n", slot->cmplt_queue, slot->cmplt_queue_slot); if (info_reg & HGC_INVLD_DQE_INFO_OFL_MSK) - dev_err(dev, "slot complete: [%d:%d] has dq order frame len err", + dev_err(dev, "slot complete: [%d:%d] has dq order frame len err\n", slot->cmplt_queue, slot->cmplt_queue_slot); ts->stat = SAS_OPEN_REJECT; @@ -1294,7 +1294,7 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, case SAS_PROTOCOL_SATA: case SAS_PROTOCOL_STP: case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: - dev_err(dev, "slot complete: SATA/STP not supported"); + dev_err(dev, "slot complete: SATA/STP not supported\n"); break; default: @@ -1417,7 +1417,7 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p) irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2); if (!(irq_value & CHL_INT2_SL_RX_BC_ACK_MSK)) { - dev_err(dev, "bcast: irq_value = %x not set enable bit", + dev_err(dev, "bcast: irq_value = %x not set enable bit\n", irq_value); res = IRQ_NONE; goto end; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 043f47ba3600..68d07a4f8422 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1382,7 +1382,7 @@ static int hw_init_v2_hw(struct hisi_hba *hisi_hba) rc = reset_hw_v2_hw(hisi_hba); if (rc) { - dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc); + dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc); return rc; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 8522f693033f..397846388e85 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -909,7 +909,7 @@ static int hw_init_v3_hw(struct hisi_hba *hisi_hba) rc = reset_hw_v3_hw(hisi_hba); if (rc) { - dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc); + dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc); return rc; } -- cgit v1.2.3 From 26f84f9bc3ba04dd415a93e4ca16eda896cf94ea Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Tue, 1 Sep 2020 19:13:10 +0800 Subject: scsi: hisi_sas: Code style cleanup Remove extra blank lines and add spaces around operators. Link: https://lore.kernel.org/r/1598958790-232272-9-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 1 - drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +--- 3 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index f5ad8e662b4b..f18452942508 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1430,7 +1430,6 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) } else { hisi_sas_phy_down(hisi_hba, phy_no, 0); } - } } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 68d07a4f8422..b57177b52fac 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1202,7 +1202,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0x7ffe20fe); hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0xfff00c30); for (i = 0; i < hisi_hba->queue_count; i++) - hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0); + hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0); hisi_sas_write32(hisi_hba, AXI_AHB_CLK_CFG, 1); hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 397846388e85..87bda037303f 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -596,7 +596,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, AWQOS_AWCACHE_CFG, 0xf0f0); hisi_sas_write32(hisi_hba, ARQOS_ARCACHE_CFG, 0xf0f0); for (i = 0; i < hisi_hba->queue_count; i++) - hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0); + hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0); hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); @@ -1350,7 +1350,6 @@ static void prep_smp_v3_hw(struct hisi_hba *hisi_hba, hdr->cmd_table_addr = cpu_to_le64(req_dma_addr); hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot)); - } static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, @@ -1456,7 +1455,6 @@ static void prep_abort_v3_hw(struct hisi_hba *hisi_hba, /* dw7 */ hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF); hdr->transfer_tags = cpu_to_le32(slot->idx); - } static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) -- cgit v1.2.3 From 7f054da7738a66fc70239ee899e74d899bad3834 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Fri, 2 Oct 2020 22:30:32 +0800 Subject: scsi: hisi_sas: Use hisi_hba->cq_nvecs for calling calling synchronize_irq() A call trace is observed when running function level reset with online CPUs less than 16 and MSI auto-affinity enabled. [16538.348038] Call trace: [16538.348422] pci_irq_vector+0x98/0xc0 [16538.348947] disable_host_v3_hw+0x8c/0x288 [hisi_sas_v3_hw] [16538.349706] hisi_sas_reset_prepare_v3_hw+0x60/0x88 [hisi_sas_v3_hw] [16538.350631] pci_dev_save_and_disable+0x38/0x68 [16538.351290] pci_reset_function+0x44/0x88 [16538.351846] reset_store+0x6c/0xb8 [16538.352429] dev_attr_store+0x44/0x60 [16538.353035] sysfs_kf_write+0x58/0x80 [16538.353558] kernfs_fop_write+0x140/0x230 [16538.354175] __vfs_write+0x48/0x80 [16538.354675] vfs_write+0xb8/0x1d8 [16538.355145] ksys_write+0x74/0xf8 [16538.355615] __arm64_sys_write+0x24/0x30 [16538.356240] el0_svc_common.constprop.4+0x80/0x1f0 [16538.356905] do_el0_svc+0x2c/0x38 [16538.357408] el0_svc+0x14/0x40 [16538.357848] el0_sync_handler+0xbc/0x2ec [16538.358388] el0_sync+0x140/0x180 The reason is that if we use pci_alloc_irq_vectors_affinity() to allocate IRQs, the number of CQ IRQs can only be less than or equal to the number of online CPUs, but we use hisi_hba->queue_count (always 16) to iterate during interrupt_disable_v3_hw(). Use hisi_hba->cq_nvecs to replace hisi_hba->queue_count to avoid synchronize IRQ on a CPU which does not exist. Link: https://lore.kernel.org/r/1601649038-25534-2-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 87bda037303f..0cc186fcbca8 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2525,10 +2525,11 @@ static void interrupt_disable_v3_hw(struct hisi_hba *hisi_hba) synchronize_irq(pci_irq_vector(pdev, 1)); synchronize_irq(pci_irq_vector(pdev, 2)); synchronize_irq(pci_irq_vector(pdev, 11)); - for (i = 0; i < hisi_hba->queue_count; i++) { + for (i = 0; i < hisi_hba->queue_count; i++) hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0x1); + + for (i = 0; i < hisi_hba->cq_nvecs; i++) synchronize_irq(pci_irq_vector(pdev, i + 16)); - } hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xffffffff); hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xffffffff); -- cgit v1.2.3 From 6c459ea1542b8937779cbeefb2b1cc77a554c29c Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 2 Oct 2020 22:30:33 +0800 Subject: scsi: hisi_sas: Switch to new framework to support suspend and resume For v3 hw we will add support for runtime PM which is only supported in new framework. Legacy PM support and new framework are not allowed to be used together. Switch to new framework to support suspend and resume. Link: https://lore.kernel.org/r/1601649038-25534-3-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 0cc186fcbca8..e73c124355e5 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3407,8 +3407,9 @@ enum { hip08, }; -static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state) +static int suspend_v3_hw(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct sas_ha_struct *sha = pci_get_drvdata(pdev); struct hisi_hba *hisi_hba = sha->lldd_ha; struct device *dev = hisi_hba->dev; @@ -3439,7 +3440,7 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state) hisi_sas_init_mem(hisi_hba); - device_state = pci_choose_state(pdev, state); + device_state = pci_choose_state(pdev, PMSG_SUSPEND); dev_warn(dev, "entering operating state [D%d]\n", device_state); pci_save_state(pdev); @@ -3452,8 +3453,9 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } -static int hisi_sas_v3_resume(struct pci_dev *pdev) +static int resume_v3_hw(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct sas_ha_struct *sha = pci_get_drvdata(pdev); struct hisi_hba *hisi_hba = sha->lldd_ha; struct Scsi_Host *shost = hisi_hba->shost; @@ -3501,14 +3503,17 @@ static const struct pci_error_handlers hisi_sas_err_handler = { .reset_done = hisi_sas_reset_done_v3_hw, }; +static const struct dev_pm_ops hisi_sas_v3_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(suspend_v3_hw, resume_v3_hw) +}; + static struct pci_driver sas_v3_pci_driver = { .name = DRV_NAME, .id_table = sas_v3_pci_table, .probe = hisi_sas_v3_probe, .remove = hisi_sas_v3_remove, - .suspend = hisi_sas_v3_suspend, - .resume = hisi_sas_v3_resume, .err_handler = &hisi_sas_err_handler, + .driver.pm = &hisi_sas_v3_pm_ops, }; module_pci_driver(sas_v3_pci_driver); -- cgit v1.2.3 From 65ff4aef7e9bde00871875c5fbc9c6b79df6f5ba Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 2 Oct 2020 22:30:34 +0800 Subject: scsi: hisi_sas: Add controller runtime PM support for v3 hw Add controller runtime PM support for v3 hw. Link: https://lore.kernel.org/r/1601649038-25534-4-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 2 ++ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 56 ++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index c617ac8d8315..961842ee8906 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES #define HISI_SAS_RESET_BIT 0 #define HISI_SAS_REJECT_CMD_BIT 1 +#define HISI_SAS_PM_BIT 2 #define HISI_SAS_MAX_COMMANDS (HISI_SAS_QUEUE_SLOTS) #define HISI_SAS_RESERVED_IPTT 96 #define HISI_SAS_UNRESERVED_IPTT \ diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index e73c124355e5..9b0e2aac75a6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3314,6 +3314,17 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) scsi_scan_host(shost); + /* + * For the situation that there are ATA disks connected with SAS + * controller, it additionally creates ata_port which will affect the + * child_count of hisi_hba->dev. Even if suspended all the disks, + * ata_port is still and the child_count of hisi_hba->dev is not 0. + * So use pm_suspend_ignore_children() to ignore the effect to + * hisi_hba->dev. + */ + pm_suspend_ignore_children(dev, true); + pm_runtime_put_noidle(&pdev->dev); + return 0; err_out_register_ha: @@ -3353,6 +3364,7 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev) struct hisi_hba *hisi_hba = sha->lldd_ha; struct Scsi_Host *shost = sha->core.shost; + pm_runtime_get_noresume(dev); if (timer_pending(&hisi_hba->timer)) del_timer(&hisi_hba->timer); @@ -3407,7 +3419,7 @@ enum { hip08, }; -static int suspend_v3_hw(struct device *device) +static int _suspend_v3_hw(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct sas_ha_struct *sha = pci_get_drvdata(pdev); @@ -3453,7 +3465,7 @@ static int suspend_v3_hw(struct device *device) return 0; } -static int resume_v3_hw(struct device *device) +static int _resume_v3_hw(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct sas_ha_struct *sha = pci_get_drvdata(pdev); @@ -3492,6 +3504,34 @@ static int resume_v3_hw(struct device *device) return 0; } +static int suspend_v3_hw(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct sas_ha_struct *sha = pci_get_drvdata(pdev); + struct hisi_hba *hisi_hba = sha->lldd_ha; + int rc; + + set_bit(HISI_SAS_PM_BIT, &hisi_hba->flags); + + rc = _suspend_v3_hw(device); + if (rc) + clear_bit(HISI_SAS_PM_BIT, &hisi_hba->flags); + + return rc; +} + +static int resume_v3_hw(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct sas_ha_struct *sha = pci_get_drvdata(pdev); + struct hisi_hba *hisi_hba = sha->lldd_ha; + int rc = _resume_v3_hw(device); + + clear_bit(HISI_SAS_PM_BIT, &hisi_hba->flags); + + return rc; +} + static const struct pci_device_id sas_v3_pci_table[] = { { PCI_VDEVICE(HUAWEI, 0xa230), hip08 }, {} @@ -3503,8 +3543,20 @@ static const struct pci_error_handlers hisi_sas_err_handler = { .reset_done = hisi_sas_reset_done_v3_hw, }; +static int runtime_suspend_v3_hw(struct device *dev) +{ + return suspend_v3_hw(dev); +} + +static int runtime_resume_v3_hw(struct device *dev) +{ + return resume_v3_hw(dev); +} + static const struct dev_pm_ops hisi_sas_v3_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(suspend_v3_hw, resume_v3_hw) + SET_RUNTIME_PM_OPS(runtime_suspend_v3_hw, + runtime_resume_v3_hw, NULL) }; static struct pci_driver sas_v3_pci_driver = { -- cgit v1.2.3 From e06596d5000c58f35721f334fe2eee28e3b01a77 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 2 Oct 2020 22:30:35 +0800 Subject: scsi: hisi_sas: Add check for methods _PS0 and _PR0 To support system suspend/resume or runtime suspend/resume, need to use the function pci_set_power_state() to change the power state which requires at least method _PS0 or _PR0 be filled by platform for v3 hw. So check whether the method is supported, if not, print a warning. A Kconfig dependency is added as there is no stub for acpi_device_power_manageable(). Link: https://lore.kernel.org/r/1601649038-25534-5-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/Kconfig | 1 + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig index 13ed9073fc72..b8148b1733f8 100644 --- a/drivers/scsi/hisi_sas/Kconfig +++ b/drivers/scsi/hisi_sas/Kconfig @@ -15,5 +15,6 @@ config SCSI_HISI_SAS_PCI tristate "HiSilicon SAS on PCI bus" depends on SCSI_HISI_SAS depends on PCI + depends on ACPI help This driver supports HiSilicon's SAS HBA based on PCI device diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 9b0e2aac75a6..da2c42999c80 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -903,6 +903,7 @@ static int reset_hw_v3_hw(struct hisi_hba *hisi_hba) static int hw_init_v3_hw(struct hisi_hba *hisi_hba) { struct device *dev = hisi_hba->dev; + struct acpi_device *acpi_dev; union acpi_object *obj; guid_t guid; int rc; @@ -933,6 +934,9 @@ static int hw_init_v3_hw(struct hisi_hba *hisi_hba) else ACPI_FREE(obj); + acpi_dev = ACPI_COMPANION(dev); + if (!acpi_device_power_manageable(acpi_dev)) + dev_notice(dev, "neither _PS0 nor _PR0 is defined\n"); return 0; } -- cgit v1.2.3 From 16fd4a7c5917097e9a3da03b39a92381eee40724 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 2 Oct 2020 22:30:36 +0800 Subject: scsi: hisi_sas: Add device link between SCSI devices and hisi_hba Runtime PM of SCSI devices is already supported in SCSI layer, we can suspend/resume every SCSI device separately. But if there is no link between hisi_hba and SCSI devices or SCSI targets it will cause issues if the controller is suspended while SCSI devices are still resuming. Only when all the SCSI devices under the controller are suspended, the controller can be suspended. Add the device link between SCSI devices and the controller. Link: https://lore.kernel.org/r/1601649038-25534-6-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index da2c42999c80..dfabfb4f7ef3 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2758,6 +2758,33 @@ static ssize_t intr_coal_count_v3_hw_store(struct device *dev, } static DEVICE_ATTR_RW(intr_coal_count_v3_hw); +static int slave_configure_v3_hw(struct scsi_device *sdev) +{ + struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev); + struct domain_device *ddev = sdev_to_domain_dev(sdev); + struct hisi_hba *hisi_hba = shost_priv(shost); + struct device *dev = hisi_hba->dev; + int ret = sas_slave_configure(sdev); + + if (ret) + return ret; + if (!dev_is_sata(ddev)) + sas_change_queue_depth(sdev, 64); + + if (sdev->type == TYPE_ENCLOSURE) + return 0; + + if (!device_link_add(&sdev->sdev_gendev, dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)) { + if (pm_runtime_enabled(dev)) { + dev_info(dev, "add device link failed, disable runtime PM for the host\n"); + pm_runtime_disable(dev); + } + } + + return 0; +} + static struct device_attribute *host_attrs_v3_hw[] = { &dev_attr_phy_event_threshold, &dev_attr_intr_conv_v3_hw, @@ -3114,7 +3141,7 @@ static struct scsi_host_template sht_v3_hw = { .queuecommand = sas_queuecommand, .dma_need_drain = ata_scsi_dma_need_drain, .target_alloc = sas_target_alloc, - .slave_configure = hisi_sas_slave_configure, + .slave_configure = slave_configure_v3_hw, .scan_finished = hisi_sas_scan_finished, .scan_start = hisi_sas_scan_start, .change_queue_depth = sas_change_queue_depth, -- cgit v1.2.3 From b14a37e011d829404c29a5ae17849d7efb034893 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 2 Oct 2020 22:30:37 +0800 Subject: scsi: hisi_sas: Filter out new PHY up events during suspend Currently sas_resume_ha() is called while resuming the controller to wait for all suspended PHYs to come up and all the libsas events to be completed. There is a scenario which will cause task hung: For direct attach with two disks connected with two PHYs, disable phy0 before suspending the disk on phy1 and the controller, then enable phy0 and resume the controller, and task hung occurs as follows: [ 591.901463] hisi_sas_v3_hw 0000:b4:02.0: resuming from operating state [D0] [ 593.113525] hisi_sas_v3_hw 0000:b4:02.0: neither _PS0 nor _PR0 is defined [ 593.120301] hisi_sas_v3_hw 0000:b4:02.0: waiting up to 25 seconds for 1 phy to resume [ 593.120836] hisi_sas_v3_hw 0000:b4:02.0: phyup: phy0 link_rate=10(sata) [ 593.134680] hisi_sas_v3_hw 0000:b4:02.0: phyup: phy1 link_rate=10(sata) [ 593.134733] sas: phy-2:0 added to port-2:0, phy_mask:0x1 (5000000000000200) [ 593.148350] sas: DOING DISCOVERY on port 0, pid:948 [ 593.153227] hisi_sas_v3_hw 0000:b4:02.0: dev[3:5] found [ 593.159840] sas: Enter sas_scsi_recover_host busy: 0 failed: 0 [ 593.165663] sas: ata7: end_device-2:0: dev error handler [ 593.165730] sas: ata2: end_device-2:1: dev error handler [ 593.172532] hisi_sas_v3_hw 0000:b4:02.0: phydown: phy0 phy_state=0x2 [ 593.182570] hisi_sas_v3_hw 0000:b4:02.0: ignore flutter phy0 down [ 593.331277] hisi_sas_v3_hw 0000:b4:02.0: phyup: phy0 link_rate=10(sata) [ 593.498956] ata7.00: ATA-11: SAMSUNG MZ7LH960HAJR-00005, HXT7404Q, max UDMA/133 [ 593.506235] ata7.00: 1875385008 sectors, multi 16: LBA48 NCQ (depth 32) [ 593.514295] ata7.00: configured for UDMA/133 [ 593.518557] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 0 tries: 1 [ 593.528613] sas: ata7: end_device-2:0: model:SAMSUNG MZ7LH960HAJR-00005 serial:S45NNA0M712225 [ 593.537520] device_link_add 316: dev=2:0:2:0 supplier:2 consumer:0 [ 593.543674] device_link_add 324 [ 593.546801] device_link_add 352 [ 593.549930] device_link_add 406 [ 593.553058] device_link_add 440: dev=2:0:2:0 supplier:2 consumer:0 [ 593.559208] device_link_add 444 [ 593.562335] device_link_add 455 [ 593.565517] scsi 2:0:2:0: Direct-Access ATA SAMSUNG MZ7LH960 404Q PQ: 0 ANSI: 5 [ 620.057464] phy-2:1: resume timeout [ 738.841445] INFO: task kworker/u256:0:8 blocked for more than 120 seconds. [ 738.848295] Not tainted 5.8.0-rc1-76154-g0d52b59-dirty #744 [ 738.854361] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 738.862155] kworker/u256:0 D 0 8 2 0x00000028 [ 738.867626] Workqueue: 0000:b4:02.0_event_q sas_port_event_worker [ 738.873693] Call trace: [ 738.876133] __switch_to+0xf4/0x148 [ 738.879613] __schedule+0x270/0x5d8 [ 738.883091] schedule+0x78/0x110 [ 738.886307] schedule_timeout+0x1ac/0x280 [ 738.890299] wait_for_completion+0x94/0x138 [ 738.894472] flush_workqueue+0x114/0x438 [ 738.898377] sas_porte_bytes_dmaed+0x400/0x500 [ 738.902801] sas_port_event_worker+0x28/0x40 [ 738.907053] process_one_work+0x1e8/0x360 [ 738.911046] worker_thread+0x44/0x478 [ 738.914698] kthread+0x150/0x158 [ 738.917915] ret_from_fork+0x10/0x1c [ 738.921534] INFO: task kworker/u256:1:948 blocked for more than 120 seconds. [ 738.928550] Not tainted 5.8.0-rc1-76154-g0d52b59-dirty #744 [ 738.934614] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 738.942408] kworker/u256:1 D 0 948 2 0x00000028 [ 738.947873] Workqueue: 0000:b4:02.0_disco_q sas_discover_domain [ 738.953766] Call trace: [ 738.956203] __switch_to+0xf4/0x148 [ 738.959678] __schedule+0x270/0x5d8 [ 738.963152] schedule+0x78/0x110 [ 738.966368] rpm_resume+0xcc/0x550 [ 738.969757] __pm_runtime_resume+0x3c/0x88 [ 738.973836] rpm_get_suppliers+0x50/0x148 [ 738.977829] __pm_runtime_set_status+0x124/0x2f0 [ 738.982427] scsi_sysfs_add_sdev+0x1a0/0x2a8 [ 738.986679] scsi_probe_and_add_lun+0x888/0xab0 [ 738.991190] __scsi_scan_target+0xec/0x520 [ 738.995268] scsi_scan_target+0x11c/0x128 [ 738.999261] sas_rphy_add+0x15c/0x1e8 [ 739.002907] sas_probe_devices+0xe4/0x150 [ 739.006899] sas_discover_domain+0x33c/0x588 [ 739.011150] process_one_work+0x1e8/0x360 [ 739.015143] worker_thread+0x44/0x478 [ 739.018789] kthread+0x150/0x158 [ 739.022003] ret_from_fork+0x10/0x1c ... If an extra phy0 up happens during resume of the SAS controller, it will emit a new libsas event (event PORTE_BYTES_DMAED and event DISCE_DISCOVER_DOMAIN). We will call function scsi_sysfs_add_sdev() in event DISCE_DISCOVER_DOMAIN, which will call __pm_runtime_set_status() to resume supplier (host controller). For runtime PM core, if device is in the resuming state, the later resume request of the device will wait for previous resume request to complete synchronously. At that point in time the state of the controller is still resuming as it waits for all libsas events to be completed, while libsas event DISCE_DISCOVER_DOMAIN is blocked as the state of the controller is resuming which causes a deadlock. To avoid the issue, filter out new PHY up events while the controller is suspended. Link: https://lore.kernel.org/r/1601649038-25534-7-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index f18452942508..ef3922ad70c0 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -619,6 +619,12 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no) if (!phy->phy_attached) return; + if (test_bit(HISI_SAS_PM_BIT, &hisi_hba->flags) && + !sas_phy->suspended) { + dev_warn(hisi_hba->dev, "phy%d during suspend filtered out\n", phy_no); + return; + } + sas_ha = &hisi_hba->sha; sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE); -- cgit v1.2.3 From 69f4ec1edb136d2d2511d1ef96f94ef0aeecefdf Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 2 Oct 2020 22:30:38 +0800 Subject: scsi: hisi_sas: Recover PHY state according to the status before reset Currently the PHY state is set according to the state of the PHYs after reset. This is invalid as the PHYs are already re-initialized. Set PHY state according to the state before the reset instead of after. Link: https://lore.kernel.org/r/1601649038-25534-8-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/scsi/hisi_sas') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index ef3922ad70c0..5b7357a5620d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1551,7 +1551,6 @@ EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_prepare); void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) { struct Scsi_Host *shost = hisi_hba->shost; - u32 state; /* Init and wait for PHYs to come up and all libsas event finished. */ hisi_hba->hw->phys_init(hisi_hba); @@ -1566,8 +1565,7 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) scsi_unblock_requests(shost); clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); - state = hisi_hba->hw->get_phys_state(hisi_hba); - hisi_sas_rescan_topology(hisi_hba, state); + hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state); } EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done); -- cgit v1.2.3