summaryrefslogtreecommitdiff
path: root/drivers/scsi/hisi_sas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/hisi_sas')
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h3
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c38
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v1_hw.c6
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c44
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: