diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-14 15:15:35 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-14 15:15:35 -0700 |
commit | 55e0500eb5c0440a3d43074edbd8db3e95851b66 (patch) | |
tree | 874b9da7a764df298441242ce79b9fd89c2910df /drivers/scsi/hisi_sas | |
parent | 4815519ed0af833884ce9c288183bf1ae3cb9caa (diff) | |
parent | 69f4ec1edb136d2d2511d1ef96f94ef0aeecefdf (diff) |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"The usual driver updates (ufs, qla2xxx, tcmu, ibmvfc, lpfc, smartpqi,
hisi_sas, qedi, qedf, mpt3sas) and minor bug fixes.
There are only three core changes: adding sense codes, cleaning up
noretry and adding an option for limitless retries"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (226 commits)
scsi: hisi_sas: Recover PHY state according to the status before reset
scsi: hisi_sas: Filter out new PHY up events during suspend
scsi: hisi_sas: Add device link between SCSI devices and hisi_hba
scsi: hisi_sas: Add check for methods _PS0 and _PR0
scsi: hisi_sas: Add controller runtime PM support for v3 hw
scsi: hisi_sas: Switch to new framework to support suspend and resume
scsi: hisi_sas: Use hisi_hba->cq_nvecs for calling calling synchronize_irq()
scsi: qedf: Remove redundant assignment to variable 'rc'
scsi: lpfc: Remove unneeded variable 'status' in lpfc_fcp_cpu_map_store()
scsi: snic: Convert to use DEFINE_SEQ_ATTRIBUTE macro
scsi: qla4xxx: Delete unneeded variable 'status' in qla4xxx_process_ddb_changed
scsi: sun_esp: Use module_platform_driver to simplify the code
scsi: sun3x_esp: Use module_platform_driver to simplify the code
scsi: sni_53c710: Use module_platform_driver to simplify the code
scsi: qlogicpti: Use module_platform_driver to simplify the code
scsi: mac_esp: Use module_platform_driver to simplify the code
scsi: jazz_esp: Use module_platform_driver to simplify the code
scsi: mvumi: Fix error return in mvumi_io_attach()
scsi: lpfc: Drop nodelist reference on error in lpfc_gen_req()
scsi: be2iscsi: Fix a theoretical leak in beiscsi_create_eqs()
...
Diffstat (limited to 'drivers/scsi/hisi_sas')
-rw-r--r-- | drivers/scsi/hisi_sas/Kconfig | 1 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas.h | 37 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_main.c | 123 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 24 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 251 |
6 files changed, 336 insertions, 104 deletions
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.h b/drivers/scsi/hisi_sas/hisi_sas.h index e6acbf940712..a25cfc11c96d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -21,6 +21,7 @@ #include <linux/of_address.h> #include <linux/pci.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/property.h> #include <linux/regmap.h> #include <linux/timer.h> @@ -34,6 +35,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 \ @@ -275,6 +277,39 @@ 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 +}; + +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, @@ -441,6 +476,8 @@ 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]; + 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 a994c7b8d26f..128583dfccf2 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); + } } } @@ -334,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; @@ -620,6 +621,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); @@ -1431,7 +1438,6 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) } else { hisi_sas_phy_down(hisi_hba, phy_no, 0); } - } } @@ -1547,7 +1553,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); @@ -1562,8 +1567,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); @@ -3335,21 +3339,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; @@ -3705,6 +3694,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) @@ -3902,6 +3943,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, @@ -3912,6 +3956,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); @@ -3925,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_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..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); @@ -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 b6f75a1764df..7133ca859b5e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -191,8 +191,10 @@ #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_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) #define PHY_CTRL_RESET_OFF 0 #define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF) @@ -295,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) @@ -565,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, @@ -593,25 +596,24 @@ 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); 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); @@ -636,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++) { @@ -894,13 +903,14 @@ 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; 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; } @@ -924,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; } @@ -1341,7 +1354,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, @@ -1447,7 +1459,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) @@ -2469,8 +2480,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); @@ -2484,10 +2497,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); @@ -2712,6 +2726,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, @@ -2936,42 +2977,48 @@ 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; + int i; /* disable PHY */ - hisi_sas_phy_enable(hisi_hba, phy_id, 0); + 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_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_PHY_LINK_RATE_MSK; - reg_val |= (0x8 << CFG_PROG_PHY_LINK_RATE_OFF); - hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val); + 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_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 @@ -2980,60 +3027,75 @@ 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 *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:linkrate=%d phy_id=%d code_mode=%d path_mode=%d\n", - linkrate, phy_id, 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} 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], fix_code[FIXED_CODE], + fix_code[FIXED_CODE_1]); 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_PHY_LINK_RATE_MSK; - reg_val |= (linkrate << CFG_PROG_PHY_LINK_RATE_OFF); - hisi_sas_phy_write32(hisi_hba, phy_id, - PROG_PHY_LINK_RATE, reg_val); + 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_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 | - 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_id, - 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_id, - SAS_PHY_BIST_CODE, - SAS_PHY_BIST_CODE_INIT); - hisi_sas_phy_write32(hisi_hba, phy_id, - 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_id, - 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); - 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); } @@ -3056,7 +3118,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, .map_queues = hisi_sas_map_queues, @@ -3266,6 +3328,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: @@ -3305,6 +3378,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); @@ -3359,8 +3433,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; @@ -3391,7 +3466,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); @@ -3404,8 +3479,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; @@ -3442,6 +3518,34 @@ static int hisi_sas_v3_resume(struct pci_dev *pdev) 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 }, {} @@ -3453,14 +3557,29 @@ 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 = { .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); |