summaryrefslogtreecommitdiffstats
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.c104
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v1_hw.c21
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c49
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c473
5 files changed, 380 insertions, 270 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 9bfa9f12d81e..fc87994b5d73 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -170,6 +170,7 @@ struct hisi_sas_phy {
u32 code_violation_err_count;
enum sas_linkrate minimum_linkrate;
enum sas_linkrate maximum_linkrate;
+ int enable;
};
struct hisi_sas_port {
@@ -551,6 +552,8 @@ extern int hisi_sas_slave_configure(struct scsi_device *sdev);
extern int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time);
extern void hisi_sas_scan_start(struct Scsi_Host *shost);
extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
+extern void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no,
+ int enable);
extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
struct sas_task *task,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 14bac4966c87..8a7feb8ed8d6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -10,7 +10,6 @@
*/
#include "hisi_sas.h"
-#include "../libsas/sas_internal.h"
#define DRV_NAME "hisi_sas"
#define DEV_IS_GONE(dev) \
@@ -171,7 +170,7 @@ void hisi_sas_stop_phys(struct hisi_hba *hisi_hba)
int phy_no;
for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++)
- hisi_hba->hw->phy_disable(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 0);
}
EXPORT_SYMBOL_GPL(hisi_sas_stop_phys);
@@ -684,7 +683,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no)
id->initiator_bits = SAS_PROTOCOL_ALL;
id->target_bits = phy->identify.target_port_protocols;
} else if (phy->phy_type & PORT_TYPE_SATA) {
- /*Nothing*/
+ /* Nothing */
}
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
@@ -755,7 +754,8 @@ static int hisi_sas_init_device(struct domain_device *device)
* STP target port
*/
local_phy = sas_get_local_phy(device);
- if (!scsi_is_sas_phy_local(local_phy)) {
+ if (!scsi_is_sas_phy_local(local_phy) &&
+ !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {
unsigned long deadline = ata_deadline(jiffies, 20000);
struct sata_device *sata_dev = &device->sata_dev;
struct ata_host *ata_host = sata_dev->ata_host;
@@ -770,8 +770,7 @@ static int hisi_sas_init_device(struct domain_device *device)
}
sas_put_local_phy(local_phy);
if (rc) {
- dev_warn(dev, "SATA disk hardreset fail: 0x%x\n",
- rc);
+ dev_warn(dev, "SATA disk hardreset fail: %d\n", rc);
return rc;
}
@@ -976,6 +975,30 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
timer_setup(&phy->timer, hisi_sas_wait_phyup_timedout, 0);
}
+/* Wrapper to ensure we track hisi_sas_phy.enable properly */
+void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no, int enable)
+{
+ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+ struct asd_sas_phy *aphy = &phy->sas_phy;
+ struct sas_phy *sphy = aphy->phy;
+ unsigned long flags;
+
+ spin_lock_irqsave(&phy->lock, flags);
+
+ if (enable) {
+ /* We may have been enabled already; if so, don't touch */
+ if (!phy->enable)
+ sphy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+ hisi_hba->hw->phy_start(hisi_hba, phy_no);
+ } else {
+ sphy->negotiated_linkrate = SAS_PHY_DISABLED;
+ hisi_hba->hw->phy_disable(hisi_hba, phy_no);
+ }
+ phy->enable = enable;
+ spin_unlock_irqrestore(&phy->lock, flags);
+}
+EXPORT_SYMBOL_GPL(hisi_sas_phy_enable);
+
static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
{
struct sas_ha_struct *sas_ha = sas_phy->ha;
@@ -1112,10 +1135,10 @@ static int hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
sas_phy->phy->maximum_linkrate = max;
sas_phy->phy->minimum_linkrate = min;
- hisi_hba->hw->phy_disable(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 0);
msleep(100);
hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, &_r);
- hisi_hba->hw->phy_start(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 1);
return 0;
}
@@ -1133,13 +1156,13 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
break;
case PHY_FUNC_LINK_RESET:
- hisi_hba->hw->phy_disable(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 0);
msleep(100);
- hisi_hba->hw->phy_start(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 1);
break;
case PHY_FUNC_DISABLE:
- hisi_hba->hw->phy_disable(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 0);
break;
case PHY_FUNC_SET_LINK_RATE:
@@ -1264,8 +1287,7 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
/* no error, but return the number of bytes of
* underrun
*/
- dev_warn(dev, "abort tmf: task to dev %016llx "
- "resp: 0x%x sts 0x%x underrun\n",
+ dev_warn(dev, "abort tmf: task to dev %016llx resp: 0x%x sts 0x%x underrun\n",
SAS_ADDR(device->sas_addr),
task->task_status.resp,
task->task_status.stat);
@@ -1280,10 +1302,16 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
break;
}
- dev_warn(dev, "abort tmf: task to dev "
- "%016llx resp: 0x%x status 0x%x\n",
- SAS_ADDR(device->sas_addr), task->task_status.resp,
- task->task_status.stat);
+ if (task->task_status.resp == SAS_TASK_COMPLETE &&
+ task->task_status.stat == SAS_OPEN_REJECT) {
+ dev_warn(dev, "abort tmf: open reject failed\n");
+ res = -EIO;
+ } else {
+ dev_warn(dev, "abort tmf: task to dev %016llx resp: 0x%x status 0x%x\n",
+ SAS_ADDR(device->sas_addr),
+ task->task_status.resp,
+ task->task_status.stat);
+ }
sas_free_task(task);
task = NULL;
}
@@ -1427,9 +1455,9 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
sas_ha->notify_port_event(sas_phy,
PORTE_BROADCAST_RCVD);
}
- } else if (old_state & (1 << phy_no))
- /* PHY down but was up before */
+ } else {
hisi_sas_phy_down(hisi_hba, phy_no, 0);
+ }
}
}
@@ -1711,7 +1739,7 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev;
struct hisi_sas_tmf_task tmf_task;
- int rc = TMF_RESP_FUNC_FAILED;
+ int rc;
rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_DEV, 0);
@@ -1803,7 +1831,7 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
if (dev_is_sata(device)) {
rc = hisi_sas_softreset_ata_disk(device);
- if (rc)
+ if (rc == TMF_RESP_FUNC_FAILED)
return TMF_RESP_FUNC_FAILED;
}
@@ -2100,10 +2128,8 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
}
exit:
- dev_dbg(dev, "internal task abort: task to dev %016llx task=%p "
- "resp: 0x%x sts 0x%x\n",
- SAS_ADDR(device->sas_addr),
- task,
+ dev_dbg(dev, "internal task abort: task to dev %016llx task=%p resp: 0x%x sts 0x%x\n",
+ SAS_ADDR(device->sas_addr), task,
task->task_status.resp, /* 0 is complete, -1 is undelivered */
task->task_status.stat);
sas_free_task(task);
@@ -2172,16 +2198,18 @@ static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
{
struct asd_sas_phy *sas_phy = &phy->sas_phy;
struct sas_phy *sphy = sas_phy->phy;
- struct sas_phy_data *d = sphy->hostdata;
+ unsigned long flags;
phy->phy_attached = 0;
phy->phy_type = 0;
phy->port = NULL;
- if (d->enable)
+ spin_lock_irqsave(&phy->lock, flags);
+ if (phy->enable)
sphy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
else
sphy->negotiated_linkrate = SAS_PHY_DISABLED;
+ spin_unlock_irqrestore(&phy->lock, flags);
}
void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
@@ -2234,6 +2262,19 @@ void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba)
}
EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
+int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type)
+{
+ struct hisi_hba *hisi_hba = shost_priv(shost);
+
+ if (reset_type != SCSI_ADAPTER_RESET)
+ return -EOPNOTSUPP;
+
+ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hisi_sas_host_reset);
+
struct scsi_transport_template *hisi_sas_stt;
EXPORT_SYMBOL_GPL(hisi_sas_stt);
@@ -2491,22 +2532,19 @@ int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba)
if (device_property_read_u32(dev, "ctrl-reset-reg",
&hisi_hba->ctrl_reset_reg)) {
- dev_err(dev,
- "could not get property ctrl-reset-reg\n");
+ dev_err(dev, "could not get property ctrl-reset-reg\n");
return -ENOENT;
}
if (device_property_read_u32(dev, "ctrl-reset-sts-reg",
&hisi_hba->ctrl_reset_sts_reg)) {
- dev_err(dev,
- "could not get property ctrl-reset-sts-reg\n");
+ dev_err(dev, "could not get property ctrl-reset-sts-reg\n");
return -ENOENT;
}
if (device_property_read_u32(dev, "ctrl-clock-ena-reg",
&hisi_hba->ctrl_clock_ena_reg)) {
- dev_err(dev,
- "could not get property ctrl-clock-ena-reg\n");
+ dev_err(dev, "could not get property ctrl-clock-ena-reg\n");
return -ENOENT;
}
}
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 293807443480..78fe7d344848 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -798,16 +798,11 @@ static void start_phy_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
enable_phy_v1_hw(hisi_hba, phy_no);
}
-static void stop_phy_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
-{
- disable_phy_v1_hw(hisi_hba, phy_no);
-}
-
static void phy_hard_reset_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
{
- stop_phy_v1_hw(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 0);
msleep(100);
- start_phy_v1_hw(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 1);
}
static void start_phys_v1_hw(struct timer_list *t)
@@ -817,7 +812,7 @@ static void start_phys_v1_hw(struct timer_list *t)
for (i = 0; i < hisi_hba->n_phy; i++) {
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x12a);
- start_phy_v1_hw(hisi_hba, i);
+ hisi_sas_phy_enable(hisi_hba, i, 1);
}
}
@@ -1695,8 +1690,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba)
for (j = 0; j < HISI_SAS_PHY_INT_NR; j++, idx++) {
irq = platform_get_irq(pdev, idx);
if (!irq) {
- dev_err(dev,
- "irq init: fail map phy interrupt %d\n",
+ dev_err(dev, "irq init: fail map phy interrupt %d\n",
idx);
return -ENOENT;
}
@@ -1704,8 +1698,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba)
rc = devm_request_irq(dev, irq, phy_interrupts[j], 0,
DRV_NAME " phy", phy);
if (rc) {
- dev_err(dev, "irq init: could not request "
- "phy interrupt %d, rc=%d\n",
+ dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n",
irq, rc);
return -ENOENT;
}
@@ -1742,8 +1735,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba)
rc = devm_request_irq(dev, irq, fatal_interrupts[i], 0,
DRV_NAME " fatal", hisi_hba);
if (rc) {
- dev_err(dev,
- "irq init: could not request fatal interrupt %d, rc=%d\n",
+ dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n",
irq, rc);
return -ENOENT;
}
@@ -1823,6 +1815,7 @@ static struct scsi_host_template sht_v1_hw = {
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = host_attrs_v1_hw,
+ .host_reset = hisi_sas_host_reset,
};
static const struct hisi_sas_hw hisi_sas_v1_hw = {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 89160ab3efb0..d4650bed8274 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1546,14 +1546,14 @@ static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
u32 txid_auto;
- disable_phy_v2_hw(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 0);
if (phy->identify.device_type == SAS_END_DEVICE) {
txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
txid_auto | TX_HARDRST_MSK);
}
msleep(100);
- start_phy_v2_hw(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 1);
}
static void phy_get_events_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
@@ -1586,7 +1586,7 @@ static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
if (!sas_phy->phy->enabled)
continue;
- start_phy_v2_hw(hisi_hba, i);
+ hisi_sas_phy_enable(hisi_hba, i, 1);
}
}
@@ -2423,14 +2423,12 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
slot_err_v2_hw(hisi_hba, task, slot, 2);
if (ts->stat != SAS_DATA_UNDERRUN)
- dev_info(dev, "erroneous completion iptt=%d task=%p dev id=%d "
- "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,
- complete_hdr->dw0, complete_hdr->dw1,
- complete_hdr->act, complete_hdr->dw3,
- error_info[0], error_info[1],
- error_info[2], error_info[3]);
+ dev_info(dev, "erroneous completion iptt=%d task=%p dev id=%d 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,
+ complete_hdr->dw0, complete_hdr->dw1,
+ complete_hdr->act, complete_hdr->dw3,
+ error_info[0], error_info[1],
+ error_info[2], error_info[3]);
if (unlikely(slot->abort))
return ts->stat;
@@ -2502,7 +2500,7 @@ out:
spin_lock_irqsave(&device->done_lock, flags);
if (test_bit(SAS_HA_FROZEN, &ha->state)) {
spin_unlock_irqrestore(&device->done_lock, flags);
- dev_info(dev, "slot complete: task(%p) ignored\n ",
+ dev_info(dev, "slot complete: task(%p) ignored\n",
task);
return sts;
}
@@ -2935,7 +2933,7 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
if (irq_value2 & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) {
dev_warn(dev, "phy%d identify timeout\n",
- phy_no);
+ phy_no);
hisi_sas_notify_phy_event(phy,
HISI_PHYE_LINK_RESET);
}
@@ -3036,7 +3034,7 @@ static const struct hisi_sas_hw_error axi_error[] = {
{ .msk = BIT(5), .msg = "SATA_AXI_R_ERR" },
{ .msk = BIT(6), .msg = "DQE_AXI_R_ERR" },
{ .msk = BIT(7), .msg = "CQE_AXI_W_ERR" },
- {},
+ {}
};
static const struct hisi_sas_hw_error fifo_error[] = {
@@ -3045,7 +3043,7 @@ static const struct hisi_sas_hw_error fifo_error[] = {
{ .msk = BIT(10), .msg = "GETDQE_FIFO" },
{ .msk = BIT(11), .msg = "CMDP_FIFO" },
{ .msk = BIT(12), .msg = "AWTCTRL_FIFO" },
- {},
+ {}
};
static const struct hisi_sas_hw_error fatal_axi_errors[] = {
@@ -3109,12 +3107,12 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p)
if (!(err_value & sub->msk))
continue;
dev_err(dev, "%s (0x%x) found!\n",
- sub->msg, irq_value);
+ sub->msg, irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
} else {
dev_err(dev, "%s (0x%x) found!\n",
- axi_error->msg, irq_value);
+ axi_error->msg, irq_value);
queue_work(hisi_hba->wq, &hisi_hba->rst_work);
}
}
@@ -3258,7 +3256,7 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
/* check ERR bit of Status Register */
if (fis->status & ATA_ERR) {
dev_warn(dev, "sata int: phy%d FIS status: 0x%x\n", phy_no,
- fis->status);
+ fis->status);
hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET);
res = IRQ_NONE;
goto end;
@@ -3349,8 +3347,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
rc = devm_request_irq(dev, irq, phy_interrupts[i], 0,
DRV_NAME " phy", hisi_hba);
if (rc) {
- dev_err(dev, "irq init: could not request "
- "phy interrupt %d, rc=%d\n",
+ dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n",
irq, rc);
rc = -ENOENT;
goto free_phy_int_irqs;
@@ -3364,8 +3361,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
rc = devm_request_irq(dev, irq, sata_int_v2_hw, 0,
DRV_NAME " sata", phy);
if (rc) {
- dev_err(dev, "irq init: could not request "
- "sata interrupt %d, rc=%d\n",
+ dev_err(dev, "irq init: could not request sata interrupt %d, rc=%d\n",
irq, rc);
rc = -ENOENT;
goto free_sata_int_irqs;
@@ -3377,8 +3373,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
rc = devm_request_irq(dev, irq, fatal_interrupts[fatal_no], 0,
DRV_NAME " fatal", hisi_hba);
if (rc) {
- dev_err(dev,
- "irq init: could not request fatal interrupt %d, rc=%d\n",
+ dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n",
irq, rc);
rc = -ENOENT;
goto free_fatal_int_irqs;
@@ -3393,8 +3388,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
rc = devm_request_irq(dev, irq, cq_interrupt_v2_hw, 0,
DRV_NAME " cq", cq);
if (rc) {
- dev_err(dev,
- "irq init: could not request cq interrupt %d, rc=%d\n",
+ dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n",
irq, rc);
rc = -ENOENT;
goto free_cq_int_irqs;
@@ -3546,7 +3540,7 @@ static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type,
break;
default:
dev_err(dev, "write gpio: unsupported or bad reg type %d\n",
- reg_type);
+ reg_type);
return -EINVAL;
}
@@ -3599,6 +3593,7 @@ static struct scsi_host_template sht_v2_hw = {
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = host_attrs_v2_hw,
+ .host_reset = hisi_sas_host_reset,
};
static const struct hisi_sas_hw hisi_sas_v2_hw = {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 086695a4099f..49620c2411df 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -52,7 +52,36 @@
#define CFG_ABT_SET_IPTT_DONE 0xd8
#define CFG_ABT_SET_IPTT_DONE_OFF 0
#define HGC_IOMB_PROC1_STATUS 0x104
+#define HGC_LM_DFX_STATUS2 0x128
+#define HGC_LM_DFX_STATUS2_IOSTLIST_OFF 0
+#define HGC_LM_DFX_STATUS2_IOSTLIST_MSK (0xfff << \
+ HGC_LM_DFX_STATUS2_IOSTLIST_OFF)
+#define HGC_LM_DFX_STATUS2_ITCTLIST_OFF 12
+#define HGC_LM_DFX_STATUS2_ITCTLIST_MSK (0x7ff << \
+ HGC_LM_DFX_STATUS2_ITCTLIST_OFF)
+#define HGC_CQE_ECC_ADDR 0x13c
+#define HGC_CQE_ECC_1B_ADDR_OFF 0
+#define HGC_CQE_ECC_1B_ADDR_MSK (0x3f << HGC_CQE_ECC_1B_ADDR_OFF)
+#define HGC_CQE_ECC_MB_ADDR_OFF 8
+#define HGC_CQE_ECC_MB_ADDR_MSK (0x3f << HGC_CQE_ECC_MB_ADDR_OFF)
+#define HGC_IOST_ECC_ADDR 0x140
+#define HGC_IOST_ECC_1B_ADDR_OFF 0
+#define HGC_IOST_ECC_1B_ADDR_MSK (0x3ff << HGC_IOST_ECC_1B_ADDR_OFF)
+#define HGC_IOST_ECC_MB_ADDR_OFF 16
+#define HGC_IOST_ECC_MB_ADDR_MSK (0x3ff << HGC_IOST_ECC_MB_ADDR_OFF)
+#define HGC_DQE_ECC_ADDR 0x144
+#define HGC_DQE_ECC_1B_ADDR_OFF 0
+#define HGC_DQE_ECC_1B_ADDR_MSK (0xfff << HGC_DQE_ECC_1B_ADDR_OFF)
+#define HGC_DQE_ECC_MB_ADDR_OFF 16
+#define HGC_DQE_ECC_MB_ADDR_MSK (0xfff << HGC_DQE_ECC_MB_ADDR_OFF)
#define CHNL_INT_STATUS 0x148
+#define HGC_ITCT_ECC_ADDR 0x150
+#define HGC_ITCT_ECC_1B_ADDR_OFF 0
+#define HGC_ITCT_ECC_1B_ADDR_MSK (0x3ff << \
+ HGC_ITCT_ECC_1B_ADDR_OFF)
+#define HGC_ITCT_ECC_MB_ADDR_OFF 16
+#define HGC_ITCT_ECC_MB_ADDR_MSK (0x3ff << \
+ HGC_ITCT_ECC_MB_ADDR_OFF)
#define HGC_AXI_FIFO_ERR_INFO 0x154
#define AXI_ERR_INFO_OFF 0
#define AXI_ERR_INFO_MSK (0xff << AXI_ERR_INFO_OFF)
@@ -81,6 +110,10 @@
#define ENT_INT_SRC3_ITC_INT_OFF 15
#define ENT_INT_SRC3_ITC_INT_MSK (0x1 << ENT_INT_SRC3_ITC_INT_OFF)
#define ENT_INT_SRC3_ABT_OFF 16
+#define ENT_INT_SRC3_DQE_POISON_OFF 18
+#define ENT_INT_SRC3_IOST_POISON_OFF 19
+#define ENT_INT_SRC3_ITCT_POISON_OFF 20
+#define ENT_INT_SRC3_ITCT_NCQ_POISON_OFF 21
#define ENT_INT_SRC_MSK1 0x1c4
#define ENT_INT_SRC_MSK2 0x1c8
#define ENT_INT_SRC_MSK3 0x1cc
@@ -90,6 +123,28 @@
#define HGC_COM_INT_MSK 0x1d8
#define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF)
#define SAS_ECC_INTR 0x1e8
+#define SAS_ECC_INTR_DQE_ECC_1B_OFF 0
+#define SAS_ECC_INTR_DQE_ECC_MB_OFF 1
+#define SAS_ECC_INTR_IOST_ECC_1B_OFF 2
+#define SAS_ECC_INTR_IOST_ECC_MB_OFF 3
+#define SAS_ECC_INTR_ITCT_ECC_1B_OFF 4
+#define SAS_ECC_INTR_ITCT_ECC_MB_OFF 5
+#define SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF 6
+#define SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF 7
+#define SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF 8
+#define SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF 9
+#define SAS_ECC_INTR_CQE_ECC_1B_OFF 10
+#define SAS_ECC_INTR_CQE_ECC_MB_OFF 11
+#define SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF 12
+#define SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF 13
+#define SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF 14
+#define SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF 15
+#define SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF 16
+#define SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF 17
+#define SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF 18
+#define SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF 19
+#define SAS_ECC_INTR_OOO_RAM_ECC_1B_OFF 20
+#define SAS_ECC_INTR_OOO_RAM_ECC_MB_OFF 21
#define SAS_ECC_INTR_MSK 0x1ec
#define HGC_ERR_STAT_EN 0x238
#define CQE_SEND_CNT 0x248
@@ -105,6 +160,20 @@
#define COMPL_Q_0_DEPTH 0x4e8
#define COMPL_Q_0_WR_PTR 0x4ec
#define COMPL_Q_0_RD_PTR 0x4f0
+#define HGC_RXM_DFX_STATUS14 0xae8
+#define HGC_RXM_DFX_STATUS14_MEM0_OFF 0
+#define HGC_RXM_DFX_STATUS14_MEM0_MSK (0x1ff << \
+ HGC_RXM_DFX_STATUS14_MEM0_OFF)
+#define HGC_RXM_DFX_STATUS14_MEM1_OFF 9
+#define HGC_RXM_DFX_STATUS14_MEM1_MSK (0x1ff << \
+ HGC_RXM_DFX_STATUS14_MEM1_OFF)
+#define HGC_RXM_DFX_STATUS14_MEM2_OFF 18
+#define HGC_RXM_DFX_STATUS14_MEM2_MSK (0x1ff << \
+ HGC_RXM_DFX_STATUS14_MEM2_OFF)
+#define HGC_RXM_DFX_STATUS15 0xaec
+#define HGC_RXM_DFX_STATUS15_MEM3_OFF 0
+#define HGC_RXM_DFX_STATUS15_MEM3_MSK (0x1ff << \
+ HGC_RXM_DFX_STATUS15_MEM3_OFF)
#define AWQOS_AWCACHE_CFG 0xc84
#define ARQOS_ARCACHE_CFG 0xc88
#define HILINK_ERR_DFX 0xe04
@@ -172,14 +241,18 @@
#define CHL_INT0_PHY_RDY_OFF 5
#define CHL_INT0_PHY_RDY_MSK (0x1 << CHL_INT0_PHY_RDY_OFF)
#define CHL_INT1 (PORT_BASE + 0x1b8)
-#define CHL_INT1_DMAC_TX_ECC_ERR_OFF 15
-#define CHL_INT1_DMAC_TX_ECC_ERR_MSK (0x1 << CHL_INT1_DMAC_TX_ECC_ERR_OFF)
-#define CHL_INT1_DMAC_RX_ECC_ERR_OFF 17
-#define CHL_INT1_DMAC_RX_ECC_ERR_MSK (0x1 << CHL_INT1_DMAC_RX_ECC_ERR_OFF)
+#define CHL_INT1_DMAC_TX_ECC_MB_ERR_OFF 15
+#define CHL_INT1_DMAC_TX_ECC_1B_ERR_OFF 16
+#define CHL_INT1_DMAC_RX_ECC_MB_ERR_OFF 17
+#define CHL_INT1_DMAC_RX_ECC_1B_ERR_OFF 18
#define CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF 19
#define CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF 20
#define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF 21
#define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
+#define CHL_INT1_DMAC_TX_FIFO_ERR_OFF 23
+#define CHL_INT1_DMAC_RX_FIFO_ERR_OFF 24
+#define CHL_INT1_DMAC_TX_AXI_RUSER_ERR_OFF 26
+#define CHL_INT1_DMAC_RX_AXI_RUSER_ERR_OFF 27
#define CHL_INT2 (PORT_BASE + 0x1bc)
#define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0
#define CHL_INT2_RX_DISP_ERR_OFF 28
@@ -227,10 +300,8 @@
#define AM_CFG_SINGLE_PORT_MAX_TRANS (0x5014)
#define AXI_CFG (0x5100)
#define AM_ROB_ECC_ERR_ADDR (0x510c)
-#define AM_ROB_ECC_ONEBIT_ERR_ADDR_OFF 0
-#define AM_ROB_ECC_ONEBIT_ERR_ADDR_MSK (0xff << AM_ROB_ECC_ONEBIT_ERR_ADDR_OFF)
-#define AM_ROB_ECC_MULBIT_ERR_ADDR_OFF 8
-#define AM_ROB_ECC_MULBIT_ERR_ADDR_MSK (0xff << AM_ROB_ECC_MULBIT_ERR_ADDR_OFF)
+#define AM_ROB_ECC_ERR_ADDR_OFF 0
+#define AM_ROB_ECC_ERR_ADDR_MSK 0xffffffff
/* RAS registers need init */
#define RAS_BASE (0x6000)
@@ -408,6 +479,10 @@ struct hisi_sas_err_record_v3 {
#define BASE_VECTORS_V3_HW 16
#define MIN_AFFINE_VECTORS_V3_HW (BASE_VECTORS_V3_HW + 1)
+enum {
+ DSM_FUNC_ERR_HANDLE_MSI = 0,
+};
+
static bool hisi_sas_intr_conv;
MODULE_PARM_DESC(intr_conv, "interrupt converge enable (0-1)");
@@ -474,7 +549,6 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
{
- struct pci_dev *pdev = hisi_hba->pci_dev;
int i;
/* Global registers init */
@@ -494,14 +568,11 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, ENT_INT_SRC3, 0xffffffff);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe);
- if (pdev->revision >= 0x21)
- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffff7aff);
- else
- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xfffe20ff);
+ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffc220ff);
hisi_sas_write32(hisi_hba, CHNL_PHYUPDOWN_INT_MSK, 0x0);
hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0);
hisi_sas_write32(hisi_hba, HGC_COM_INT_MSK, 0x0);
- hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0x0);
+ hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0x155555);
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++)
@@ -532,12 +603,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
- if (pdev->revision >= 0x21)
- hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK,
- 0xffffffff);
- else
- hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK,
- 0xff87ffff);
+ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xf2057fff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0xffffbfe);
hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0);
@@ -804,6 +870,8 @@ 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;
+ union acpi_object *obj;
+ guid_t guid;
int rc;
rc = reset_hw_v3_hw(hisi_hba);
@@ -815,6 +883,19 @@ static int hw_init_v3_hw(struct hisi_hba *hisi_hba)
msleep(100);
init_reg_v3_hw(hisi_hba);
+ if (guid_parse("D5918B4B-37AE-4E10-A99F-E5E8A6EF4C1F", &guid)) {
+ dev_err(dev, "Parse GUID failed\n");
+ return -EINVAL;
+ }
+
+ /* Switch over to MSI handling , from PCI AER default */
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &guid, 0,
+ DSM_FUNC_ERR_HANDLE_MSI, NULL);
+ if (!obj)
+ dev_warn(dev, "Switch over to MSI handling failed\n");
+ else
+ ACPI_FREE(obj);
+
return 0;
}
@@ -856,14 +937,14 @@ static void phy_hard_reset_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
u32 txid_auto;
- disable_phy_v3_hw(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 0);
if (phy->identify.device_type == SAS_END_DEVICE) {
txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
txid_auto | TX_HARDRST_MSK);
}
msleep(100);
- start_phy_v3_hw(hisi_hba, phy_no);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 1);
}
static enum sas_linkrate phy_get_max_linkrate_v3_hw(void)
@@ -882,7 +963,7 @@ static void phys_init_v3_hw(struct hisi_hba *hisi_hba)
if (!sas_phy->phy->enabled)
continue;
- start_phy_v3_hw(hisi_hba, i);
+ hisi_sas_phy_enable(hisi_hba, i, 1);
}
}
@@ -929,7 +1010,7 @@ get_free_slot_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
DLVRY_Q_0_RD_PTR + (queue * 0x14));
if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
dev_warn(dev, "full queue=%d r=%d w=%d\n",
- queue, r, w);
+ queue, r, w);
return -EAGAIN;
}
@@ -1380,6 +1461,7 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
struct hisi_sas_initial_fis *initial_fis;
struct dev_to_host_fis *fis;
u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
+ struct Scsi_Host *shost = hisi_hba->shost;
dev_info(dev, "phyup: phy%d link_rate=%d(sata)\n", phy_no, link_rate);
initial_fis = &hisi_hba->initial_fis[phy_no];
@@ -1396,6 +1478,7 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
sas_phy->oob_mode = SATA_OOB_MODE;
attached_sas_addr[0] = 0x50;
+ attached_sas_addr[6] = shost->host_no;
attached_sas_addr[7] = phy_no;
memcpy(sas_phy->attached_sas_addr,
attached_sas_addr,
@@ -1540,6 +1623,14 @@ static irqreturn_t int_phy_up_down_bcast_v3_hw(int irq_no, void *p)
static const struct hisi_sas_hw_error port_axi_error[] = {
{
+ .irq_msk = BIT(CHL_INT1_DMAC_TX_ECC_MB_ERR_OFF),
+ .msg = "dmac_tx_ecc_bad_err",
+ },
+ {
+ .irq_msk = BIT(CHL_INT1_DMAC_RX_ECC_MB_ERR_OFF),
+ .msg = "dmac_rx_ecc_bad_err",
+ },
+ {
.irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF),
.msg = "dma_tx_axi_wr_err",
},
@@ -1555,6 +1646,22 @@ static const struct hisi_sas_hw_error port_axi_error[] = {
.irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF),
.msg = "dma_rx_axi_rd_err",
},
+ {
+ .irq_msk = BIT(CHL_INT1_DMAC_TX_FIFO_ERR_OFF),
+ .msg = "dma_tx_fifo_err",
+ },
+ {
+ .irq_msk = BIT(CHL_INT1_DMAC_RX_FIFO_ERR_OFF),
+ .msg = "dma_rx_fifo_err",
+ },
+ {
+ .irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_RUSER_ERR_OFF),
+ .msg = "dma_tx_axi_ruser_err",
+ },
+ {
+ .irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_RUSER_ERR_OFF),
+ .msg = "dma_rx_axi_ruser_err",
+ },
};
static void handle_chl_int1_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
@@ -1719,6 +1826,121 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
return IRQ_HANDLED;
}
+static const struct hisi_sas_hw_error multi_bit_ecc_errors[] = {
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_MB_OFF),
+ .msk = HGC_DQE_ECC_MB_ADDR_MSK,
+ .shift = HGC_DQE_ECC_MB_ADDR_OFF,
+ .msg = "hgc_dqe_eccbad_intr found: ram addr is 0x%08X\n",
+ .reg = HGC_DQE_ECC_ADDR,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_IOST_ECC_MB_OFF),
+ .msk = HGC_IOST_ECC_MB_ADDR_MSK,
+ .shift = HGC_IOST_ECC_MB_ADDR_OFF,
+ .msg = "hgc_iost_eccbad_intr found: ram addr is 0x%08X\n",
+ .reg = HGC_IOST_ECC_ADDR,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_ITCT_ECC_MB_OFF),
+ .msk = HGC_ITCT_ECC_MB_ADDR_MSK,
+ .shift = HGC_ITCT_ECC_MB_ADDR_OFF,
+ .msg = "hgc_itct_eccbad_intr found: ram addr is 0x%08X\n",
+ .reg = HGC_ITCT_ECC_ADDR,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF),
+ .msk = HGC_LM_DFX_STATUS2_IOSTLIST_MSK,
+ .shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
+ .msg = "hgc_iostl_eccbad_intr found: mem addr is 0x%08X\n",
+ .reg = HGC_LM_DFX_STATUS2,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF),
+ .msk = HGC_LM_DFX_STATUS2_ITCTLIST_MSK,
+ .shift = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
+ .msg = "hgc_itctl_eccbad_intr found: mem addr is 0x%08X\n",
+ .reg = HGC_LM_DFX_STATUS2,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_MB_OFF),
+ .msk = HGC_CQE_ECC_MB_ADDR_MSK,
+ .shift = HGC_CQE_ECC_MB_ADDR_OFF,
+ .msg = "hgc_cqe_eccbad_intr found: ram address is 0x%08X\n",
+ .reg = HGC_CQE_ECC_ADDR,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF),
+ .msk = HGC_RXM_DFX_STATUS14_MEM0_MSK,
+ .shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
+ .msg = "rxm_mem0_eccbad_intr found: mem addr is 0x%08X\n",
+ .reg = HGC_RXM_DFX_STATUS14,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF),
+ .msk = HGC_RXM_DFX_STATUS14_MEM1_MSK,
+ .shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
+ .msg = "rxm_mem1_eccbad_intr found: mem addr is 0x%08X\n",
+ .reg = HGC_RXM_DFX_STATUS14,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF),
+ .msk = HGC_RXM_DFX_STATUS14_MEM2_MSK,
+ .shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
+ .msg = "rxm_mem2_eccbad_intr found: mem addr is 0x%08X\n",
+ .reg = HGC_RXM_DFX_STATUS14,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF),
+ .msk = HGC_RXM_DFX_STATUS15_MEM3_MSK,
+ .shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
+ .msg = "rxm_mem3_eccbad_intr found: mem addr is 0x%08X\n",
+ .reg = HGC_RXM_DFX_STATUS15,
+ },
+ {
+ .irq_msk = BIT(SAS_ECC_INTR_OOO_RAM_ECC_MB_OFF),
+ .msk = AM_ROB_ECC_ERR_ADDR_MSK,
+ .shift = AM_ROB_ECC_ERR_ADDR_OFF,
+ .msg = "ooo_ram_eccbad_intr found: ROB_ECC_ERR_ADDR=0x%08X\n",
+ .reg = AM_ROB_ECC_ERR_ADDR,
+ },
+};
+
+static void multi_bit_ecc_error_process_v3_hw(struct hisi_hba *hisi_hba,
+ u32 irq_value)
+{
+ struct device *dev = hisi_hba->dev;
+ const struct hisi_sas_hw_error *ecc_error;
+ u32 val;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(multi_bit_ecc_errors); i++) {
+ ecc_error = &multi_bit_ecc_errors[i];
+ if (irq_value & ecc_error->irq_msk) {
+ val = hisi_sas_read32(hisi_hba, ecc_error->reg);
+ val &= ecc_error->msk;
+ val >>= ecc_error->shift;
+ dev_err(dev, ecc_error->msg, irq_value, val);
+ queue_work(hisi_hba->wq, &hisi_hba->rst_work);
+ }
+ }
+}
+
+static void fatal_ecc_int_v3_hw(struct hisi_hba *hisi_hba)
+{
+ u32 irq_value, irq_msk;
+
+ irq_msk = hisi_sas_read32(hisi_hba, SAS_ECC_INTR_MSK);
+ hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, irq_msk | 0xffffffff);
+
+ irq_value = hisi_sas_read32(hisi_hba, SAS_ECC_INTR);
+ if (irq_value)
+ multi_bit_ecc_error_process_v3_hw(hisi_hba, irq_value);
+
+ hisi_sas_write32(hisi_hba, SAS_ECC_INTR, irq_value);
+ hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, irq_msk);
+}
+
static const struct hisi_sas_hw_error axi_error[] = {
{ .msk = BIT(0), .msg = "IOST_AXI_W_ERR" },
{ .msk = BIT(1), .msg = "IOST_AXI_R_ERR" },
@@ -1728,7 +1950,7 @@ static const struct hisi_sas_hw_error axi_error[] = {
{ .msk = BIT(5), .msg = "SATA_AXI_R_ERR" },
{ .msk = BIT(6), .msg = "DQE_AXI_R_ERR" },
{ .msk = BIT(7), .msg = "CQE_AXI_W_ERR" },
- {},
+ {}
};
static const struct hisi_sas_hw_error fifo_error[] = {
@@ -1737,7 +1959,7 @@ static const struct hisi_sas_hw_error fifo_error[] = {
{ .msk = BIT(10), .msg = "GETDQE_FIFO" },
{ .msk = BIT(11), .msg = "CMDP_FIFO" },
{ .msk = BIT(12), .msg = "AWTCTRL_FIFO" },
- {},
+ {}
};
static const struct hisi_sas_hw_error fatal_axi_error[] = {
@@ -1771,6 +1993,23 @@ static const struct hisi_sas_hw_error fatal_axi_error[] = {
.irq_msk = BIT(ENT_INT_SRC3_ABT_OFF),
.msg = "SAS_HGC_ABT fetch LM list",
},
+ {
+ .irq_msk = BIT(ENT_INT_SRC3_DQE_POISON_OFF),
+ .msg = "read dqe poison",
+ },
+ {
+ .irq_msk = BIT(ENT_INT_SRC3_IOST_POISON_OFF),
+ .msg = "read iost poison",
+ },
+ {
+ .irq_msk = BIT(ENT_INT_SRC3_ITCT_POISON_OFF),
+ .msg = "read itct poison",
+ },
+ {
+ .irq_msk = BIT(ENT_INT_SRC3_ITCT_NCQ_POISON_OFF),
+ .msg = "read itct ncq poison",
+ },
+
};
static irqreturn_t fatal_axi_int_v3_hw(int irq_no, void *p)
@@ -1823,6 +2062,8 @@ static irqreturn_t fatal_axi_int_v3_hw(int irq_no, void *p)
}
}
+ fatal_ecc_int_v3_hw(hisi_hba);
+
if (irq_value & BIT(ENT_INT_SRC3_ITC_INT_OFF)) {
u32 reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
u32 dev_id = reg_val & ITCT_DEV_MSK;
@@ -1966,13 +2207,11 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
slot_err_v3_hw(hisi_hba, task, slot);
if (ts->stat != SAS_DATA_UNDERRUN)
- dev_info(dev, "erroneous completion iptt=%d task=%p dev id=%d "
- "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,
- dw0, dw1, complete_hdr->act, dw3,
- error_info[0], error_info[1],
- error_info[2], error_info[3]);
+ dev_info(dev, "erroneous completion iptt=%d task=%p dev id=%d 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,
+ dw0, dw1, complete_hdr->act, dw3,
+ error_info[0], error_info[1],
+ error_info[2], error_info[3]);
if (unlikely(slot->abort))
return ts->stat;
goto out;
@@ -2205,8 +2444,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
cq_interrupt_v3_hw, irqflags,
DRV_NAME " cq", cq);
if (rc) {
- dev_err(dev,
- "could not request cq%d interrupt, rc=%d\n",
+ dev_err(dev, "could not request cq%d interrupt, rc=%d\n",
i, rc);
rc = -ENOENT;
goto free_cq_irqs;
@@ -2362,7 +2600,7 @@ static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type,
break;
default:
dev_err(dev, "write gpio: unsupported or bad reg type %d\n",
- reg_type);
+ reg_type);
return -EINVAL;
}
@@ -2678,6 +2916,7 @@ static struct scsi_host_template sht_v3_hw = {
.ioctl = sas_ioctl,
.shost_attrs = host_attrs_v3_hw,
.tag_alloc_policy = BLK_TAG_ALLOC_RR,
+ .host_reset = hisi_sas_host_reset,
};
static const struct hisi_sas_hw hisi_sas_v3_hw = {
@@ -2800,7 +3039,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hisi_hba->regs = pcim_iomap(pdev, 5, 0);
if (!hisi_hba->regs) {
- dev_err(dev, "cannot map register.\n");
+ dev_err(dev, "cannot map register\n");
rc = -ENOMEM;
goto err_out_ha;
}
@@ -2921,161 +3160,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
scsi_host_put(shost);
}
-static const struct hisi_sas_hw_error sas_ras_intr0_nfe[] = {
- { .irq_msk = BIT(19), .msg = "HILINK_INT" },
- { .irq_msk = BIT(20), .msg = "HILINK_PLL0_OUT_OF_LOCK" },
- { .irq_msk = BIT(21), .msg = "HILINK_PLL1_OUT_OF_LOCK" },
- { .irq_msk = BIT(22), .msg = "HILINK_LOSS_OF_REFCLK0" },
- { .irq_msk = BIT(23), .msg = "HILINK_LOSS_OF_REFCLK1" },
- { .irq_msk = BIT(24), .msg = "DMAC0_TX_POISON" },
- { .irq_msk = BIT(25), .msg = "DMAC1_TX_POISON" },
- { .irq_msk = BIT(26), .msg = "DMAC2_TX_POISON" },
- { .irq_msk = BIT(27), .msg = "DMAC3_TX_POISON" },
- { .irq_msk = BIT(28), .msg = "DMAC4_TX_POISON" },
- { .irq_msk = BIT(29), .msg = "DMAC5_TX_POISON" },
- { .irq_msk = BIT(30), .msg = "DMAC6_TX_POISON" },
- { .irq_msk = BIT(31), .msg = "DMAC7_TX_POISON" },
-};
-
-static const struct hisi_sas_hw_error sas_ras_intr1_nfe[] = {
- { .irq_msk = BIT(0), .msg = "RXM_CFG_MEM3_ECC2B_INTR" },
- { .irq_msk = BIT(1), .msg = "RXM_CFG_MEM2_ECC2B_INTR" },
- { .irq_msk = BIT(2), .msg = "RXM_CFG_MEM1_ECC2B_INTR" },
- { .irq_msk = BIT(3), .msg = "RXM_CFG_MEM0_ECC2B_INTR" },
- { .irq_msk = BIT(4), .msg = "HGC_CQE_ECC2B_INTR" },
- { .irq_msk = BIT(5), .msg = "LM_CFG_IOSTL_ECC2B_INTR" },
- { .irq_msk = BIT(6), .msg = "LM_CFG_ITCTL_ECC2B_INTR" },
- { .irq_msk = BIT(7), .msg = "HGC_ITCT_ECC2B_INTR" },
- { .irq_msk = BIT(8), .msg = "HGC_IOST_ECC2B_INTR" },
- { .irq_msk = BIT(9), .msg = "HGC_DQE_ECC2B_INTR" },
- { .irq_msk = BIT(10), .msg = "DMAC0_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(11), .msg = "DMAC1_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(12), .msg = "DMAC2_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(13), .msg = "DMAC3_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(14), .msg = "DMAC4_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(15), .msg = "DMAC5_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(16), .msg = "DMAC6_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(17), .msg = "DMAC7_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(18), .msg = "OOO_RAM_ECC2B_INTR" },
- { .irq_msk = BIT(20), .msg = "HGC_DQE_POISON_INTR" },
- { .irq_msk = BIT(21), .msg = "HGC_IOST_POISON_INTR" },
- { .irq_msk = BIT(22), .msg = "HGC_ITCT_POISON_INTR" },
- { .irq_msk = BIT(23), .msg = "HGC_ITCT_NCQ_POISON_INTR" },
- { .irq_msk = BIT(24), .msg = "DMAC0_RX_POISON" },
- { .irq_msk = BIT(25), .msg = "DMAC1_RX_POISON" },
- { .irq_msk = BIT(26), .msg = "DMAC2_RX_POISON" },
- { .irq_msk = BIT(27), .msg = "DMAC3_RX_POISON" },
- { .irq_msk = BIT(28), .msg = "DMAC4_RX_POISON" },
- { .irq_msk = BIT(29), .msg = "DMAC5_RX_POISON" },
- { .irq_msk = BIT(30), .msg = "DMAC6_RX_POISON" },
- { .irq_msk = BIT(31), .msg = "DMAC7_RX_POISON" },
-};
-
-static const struct hisi_sas_hw_error sas_ras_intr2_nfe[] = {
- { .irq_msk = BIT(0), .msg = "DMAC0_AXI_BUS_ERR" },
- { .irq_msk = BIT(1), .msg = "DMAC1_AXI_BUS_ERR" },
- { .irq_msk = BIT(2), .msg = "DMAC2_AXI_BUS_ERR" },
- { .irq_msk = BIT(3), .msg = "DMAC3_AXI_BUS_ERR" },
- { .irq_msk = BIT(4), .msg = "DMAC4_AXI_BUS_ERR" },
- { .irq_msk = BIT(5), .msg = "DMAC5_AXI_BUS_ERR" },
- { .irq_msk = BIT(6), .msg = "DMAC6_AXI_BUS_ERR" },
- { .irq_msk = BIT(7), .msg = "DMAC7_AXI_BUS_ERR" },
- { .irq_msk = BIT(8), .msg = "DMAC0_FIFO_OMIT_ERR" },
- { .irq_msk = BIT(9), .msg = "DMAC1_FIFO_OMIT_ERR" },
- { .irq_msk = BIT(10), .msg = "DMAC2_FIFO_OMIT_ERR" },
- { .irq_msk = BIT(11), .msg = "DMAC3_FIFO_OMIT_ERR" },
- { .irq_msk = BIT(12), .msg = "DMAC4_FIFO_OMIT_ERR" },
- { .irq_msk = BIT(13), .msg = "DMAC5_FIFO_OMIT_ERR" },
- { .irq_msk = BIT(14), .msg = "DMAC6_FIFO_OMIT_ERR" },
- { .irq_msk = BIT(15), .msg = "DMAC7_FIFO_OMIT_ERR" },
- { .irq_msk = BIT(16), .msg = "HGC_RLSE_SLOT_UNMATCH" },
- { .irq_msk = BIT(17), .msg = "HGC_LM_ADD_FCH_LIST_ERR" },
- { .irq_msk = BIT(18), .msg = "HGC_AXI_BUS_ERR" },
- { .irq_msk = BIT(19), .msg = "HGC_FIFO_OMIT_ERR" },
-};
-
-static bool process_non_fatal_error_v3_hw(struct hisi_hba *hisi_hba)
-{
- struct device *dev = hisi_hba->dev;
- const struct hisi_sas_hw_error *ras_error;
- bool need_reset = false;
- u32 irq_value;
- int i;
-
- irq_value = hisi_sas_read32(hisi_hba, SAS_RAS_INTR0);
- for (i = 0; i < ARRAY_SIZE(sas_ras_intr0_nfe); i++) {
- ras_error = &sas_ras_intr0_nfe[i];
- if (ras_error->irq_msk & irq_value) {
- dev_warn(dev, "SAS_RAS_INTR0: %s(irq_value=0x%x) found.\n",
- ras_error->msg, irq_value);
- need_reset = true;
- }
- }
- hisi_sas_write32(hisi_hba, SAS_RAS_INTR0, irq_value);
-
- irq_value = hisi_sas_read32(hisi_hba, SAS_RAS_INTR1);
- for (i = 0; i < ARRAY_SIZE(sas_ras_intr1_nfe); i++) {
- ras_error = &sas_ras_intr1_nfe[i];
- if (ras_error->irq_msk & irq_value) {
- dev_warn(dev, "SAS_RAS_INTR1: %s(irq_value=0x%x) found.\n",
- ras_error->msg, irq_value);
- need_reset = true;
- }
- }
- hisi_sas_write32(hisi_hba, SAS_RAS_INTR1, irq_value);
-
- irq_value = hisi_sas_read32(hisi_hba, SAS_RAS_INTR2);
- for (i = 0; i < ARRAY_SIZE(sas_ras_intr2_nfe); i++) {
- ras_error = &sas_ras_intr2_nfe[i];
- if (ras_error->irq_msk & irq_value) {
- dev_warn(dev, "SAS_RAS_INTR2: %s(irq_value=0x%x) found.\n",
- ras_error->msg, irq_value);
- need_reset = true;
- }
- }
- hisi_sas_write32(hisi_hba, SAS_RAS_INTR2, irq_value);
-
- return need_reset;
-}
-
-static pci_ers_result_t hisi_sas_error_detected_v3_hw(struct pci_dev *pdev,
- pci_channel_state_t state)
-{
- struct sas_ha_struct *sha = pci_get_drvdata(pdev);
- struct hisi_hba *hisi_hba = sha->lldd_ha;
- struct device *dev = hisi_hba->dev;
-
- dev_info(dev, "PCI error: detected callback, state(%d)!!\n", state);
- if (state == pci_channel_io_perm_failure)
- return PCI_ERS_RESULT_DISCONNECT;
-
- if (process_non_fatal_error_v3_hw(hisi_hba))
- return PCI_ERS_RESULT_NEED_RESET;
-
- return PCI_ERS_RESULT_CAN_RECOVER;
-}
-
-static pci_ers_result_t hisi_sas_mmio_enabled_v3_hw(struct pci_dev *pdev)
-{
- return PCI_ERS_RESULT_RECOVERED;
-}
-
-static pci_ers_result_t hisi_sas_slot_reset_v3_hw(struct pci_dev *pdev)
-{
- struct sas_ha_struct *sha = pci_get_drvdata(pdev);
- struct hisi_hba *hisi_hba = sha->lldd_ha;
- struct device *dev = hisi_hba->dev;
- HISI_SAS_DECLARE_RST_WORK_ON_STACK(r);
-
- dev_info(dev, "PCI error: slot reset callback!!\n");
- queue_work(hisi_hba->wq, &r.work);
- wait_for_completion(r.completion);
- if (r.done)
- return PCI_ERS_RESULT_RECOVERED;
-
- return PCI_ERS_RESULT_DISCONNECT;
-}
-
static void hisi_sas_reset_prepare_v3_hw(struct pci_dev *pdev)
{
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
@@ -3171,7 +3255,7 @@ static int hisi_sas_v3_resume(struct pci_dev *pdev)
pci_power_t device_state = pdev->current_state;
dev_warn(dev, "resuming from operating state [D%d]\n",
- device_state);
+ device_state);
pci_set_power_state(pdev, PCI_D0);
pci_enable_wake(pdev, PCI_D0, 0);
pci_restore_state(pdev);
@@ -3199,9 +3283,6 @@ static const struct pci_device_id sas_v3_pci_table[] = {
MODULE_DEVICE_TABLE(pci, sas_v3_pci_table);
static const struct pci_error_handlers hisi_sas_err_handler = {
- .error_detected = hisi_sas_error_detected_v3_hw,
- .mmio_enabled = hisi_sas_mmio_enabled_v3_hw,
- .slot_reset = hisi_sas_slot_reset_v3_hw,
.reset_prepare = hisi_sas_reset_prepare_v3_hw,
.reset_done = hisi_sas_reset_done_v3_hw,
};