diff options
Diffstat (limited to 'drivers/scsi/hisi_sas')
| -rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas.h | 3 | ||||
| -rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_main.c | 38 | ||||
| -rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 6 | ||||
| -rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 44 |
4 files changed, 59 insertions, 32 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 2401a9575215..cf879cc59e4c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -346,8 +346,7 @@ struct hisi_sas_hw { u8 reg_index, u8 reg_count, u8 *write_data); void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba, int delay_ms, int timeout_ms); - void (*snapshot_prepare)(struct hisi_hba *hisi_hba); - void (*snapshot_restore)(struct hisi_hba *hisi_hba); + void (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba); int complete_hdr_size; struct scsi_host_template *sht; }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index a979edfd9a78..5a204074099c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1341,10 +1341,12 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) rc = hisi_sas_exec_internal_tmf_task(device, fis, s, NULL); if (rc != TMF_RESP_FUNC_COMPLETE) - dev_err(dev, "ata disk de-reset failed\n"); + dev_err(dev, "ata disk %016llx de-reset failed\n", + SAS_ADDR(device->sas_addr)); } } else { - dev_err(dev, "ata disk reset failed\n"); + dev_err(dev, "ata disk %016llx reset failed\n", + SAS_ADDR(device->sas_addr)); } if (rc == TMF_RESP_FUNC_COMPLETE) @@ -1568,21 +1570,26 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) } EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done); -static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) +static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba) { - struct device *dev = hisi_hba->dev; - struct Scsi_Host *shost = hisi_hba->shost; - int rc; - - if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) - queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); - if (!hisi_hba->hw->soft_reset) return -1; if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) return -1; + if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) + hisi_hba->hw->debugfs_snapshot_regs(hisi_hba); + + return 0; +} + +static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) +{ + struct device *dev = hisi_hba->dev; + struct Scsi_Host *shost = hisi_hba->shost; + int rc; + dev_info(dev, "controller resetting...\n"); hisi_sas_controller_reset_prepare(hisi_hba); @@ -2471,6 +2478,9 @@ void hisi_sas_rst_work_handler(struct work_struct *work) struct hisi_hba *hisi_hba = container_of(work, struct hisi_hba, rst_work); + if (hisi_sas_controller_prereset(hisi_hba)) + return; + hisi_sas_controller_reset(hisi_hba); } EXPORT_SYMBOL_GPL(hisi_sas_rst_work_handler); @@ -2480,8 +2490,12 @@ void hisi_sas_sync_rst_work_handler(struct work_struct *work) struct hisi_sas_rst *rst = container_of(work, struct hisi_sas_rst, work); + if (hisi_sas_controller_prereset(rst->hisi_hba)) + goto rst_complete; + if (!hisi_sas_controller_reset(rst->hisi_hba)) rst->done = true; +rst_complete: complete(rst->completion); } EXPORT_SYMBOL_GPL(hisi_sas_sync_rst_work_handler); @@ -2689,12 +2703,14 @@ int hisi_sas_probe(struct platform_device *pdev, rc = hisi_hba->hw->hw_init(hisi_hba); if (rc) - goto err_out_register_ha; + goto err_out_hw_init; scsi_scan_host(shost); return 0; +err_out_hw_init: + sas_unregister_ha(sha); err_out_register_ha: scsi_remove_host(shost); err_out_ha: diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 7451377c4cb6..3e359ac752fd 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1646,7 +1646,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) idx = i * HISI_SAS_PHY_INT_NR; for (j = 0; j < HISI_SAS_PHY_INT_NR; j++, idx++) { irq = platform_get_irq(pdev, idx); - if (!irq) { + if (irq < 0) { dev_err(dev, "irq init: fail map phy interrupt %d\n", idx); return -ENOENT; @@ -1665,7 +1665,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) idx = hisi_hba->n_phy * HISI_SAS_PHY_INT_NR; for (i = 0; i < hisi_hba->queue_count; i++, idx++) { irq = platform_get_irq(pdev, idx); - if (!irq) { + if (irq < 0) { dev_err(dev, "irq init: could not map cq interrupt %d\n", idx); return -ENOENT; @@ -1683,7 +1683,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) idx = (hisi_hba->n_phy * HISI_SAS_PHY_INT_NR) + hisi_hba->queue_count; for (i = 0; i < HISI_SAS_FATAL_INT_NR; i++, idx++) { irq = platform_get_irq(pdev, idx); - if (!irq) { + if (irq < 0) { dev_err(dev, "irq init: could not map fatal interrupt %d\n", idx); return -ENOENT; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 4580e081e489..499c770d405c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -531,6 +531,7 @@ module_param(prot_mask, int, 0); MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=0x0 "); static void debugfs_work_handler_v3_hw(struct work_struct *work); +static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba); static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) { @@ -1717,8 +1718,11 @@ static void handle_chl_int1_v3_hw(struct hisi_hba *hisi_hba, int phy_no) int i; irq_value &= ~irq_msk; - if (!irq_value) + if (!irq_value) { + dev_warn(dev, "phy%d channel int 1 received with status bits cleared\n", + phy_no); return; + } for (i = 0; i < ARRAY_SIZE(port_axi_error); i++) { const struct hisi_sas_hw_error *error = &port_axi_error[i]; @@ -1779,8 +1783,11 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no) BIT(CHL_INT2_RX_INVLD_DW_OFF); irq_value &= ~irq_msk; - if (!irq_value) + if (!irq_value) { + dev_warn(dev, "phy%d channel int 2 received with status bits cleared\n", + phy_no); return; + } if (irq_value & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) { dev_warn(dev, "phy%d identify timeout\n", phy_no); @@ -2252,8 +2259,9 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba, slot_err_v3_hw(hisi_hba, task, slot); if (ts->stat != SAS_DATA_UNDERRUN) - dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", + dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d addr=%016llx CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", slot->idx, task, sas_dev->device_id, + SAS_ADDR(device->sas_addr), dw0, dw1, complete_hdr->act, dw3, error_info[0], error_info[1], error_info[2], error_info[3]); @@ -3181,6 +3189,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { .get_events = phy_get_events_v3_hw, .write_gpio = write_gpio_v3_hw, .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw, + .debugfs_snapshot_regs = debugfs_snapshot_regs_v3_hw, }; static struct Scsi_Host * @@ -3665,6 +3674,19 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) { + int debugfs_dump_index = hisi_hba->debugfs_dump_index; + struct device *dev = hisi_hba->dev; + u64 timestamp = local_clock(); + + if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { + dev_warn(dev, "dump count exceeded!\n"); + return; + } + + do_div(timestamp, NSEC_PER_MSEC); + hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; + hisi_hba->debugfs_dump_index++; + debugfs_snapshot_prepare_v3_hw(hisi_hba); debugfs_snapshot_global_reg_v3_hw(hisi_hba); @@ -4407,20 +4429,8 @@ static void debugfs_work_handler_v3_hw(struct work_struct *work) { struct hisi_hba *hisi_hba = container_of(work, struct hisi_hba, debugfs_work); - int debugfs_dump_index = hisi_hba->debugfs_dump_index; - struct device *dev = hisi_hba->dev; - u64 timestamp = local_clock(); - - if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { - dev_warn(dev, "dump count exceeded!\n"); - return; - } - - do_div(timestamp, NSEC_PER_MSEC); - hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; debugfs_snapshot_regs_v3_hw(hisi_hba); - hisi_hba->debugfs_dump_index++; } static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index) @@ -4760,7 +4770,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) rc = hisi_sas_v3_init(hisi_hba); if (rc) - goto err_out_register_ha; + goto err_out_hw_init; scsi_scan_host(shost); @@ -4777,6 +4787,8 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; +err_out_hw_init: + sas_unregister_ha(sha); err_out_register_ha: scsi_remove_host(shost); err_out_free_irq_vectors: |
