diff options
Diffstat (limited to 'drivers/scsi/hisi_sas')
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas.h | 9 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_main.c | 67 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 6 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 33 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 38 |
5 files changed, 102 insertions, 51 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index a44768bceb9a..e17f5d8226bf 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -9,7 +9,6 @@ #include <linux/acpi.h> #include <linux/blk-mq.h> -#include <linux/blk-mq-pci.h> #include <linux/clk.h> #include <linux/debugfs.h> #include <linux/dmapool.h> @@ -634,8 +633,7 @@ extern struct dentry *hisi_sas_debugfs_dir; extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba); extern int hisi_sas_alloc(struct hisi_hba *hisi_hba); extern void hisi_sas_free(struct hisi_hba *hisi_hba); -extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, - int direction); +extern u8 hisi_sas_get_ata_protocol(struct sas_task *task); extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port); extern void hisi_sas_sata_done(struct sas_task *task, struct hisi_sas_slot *slot); @@ -644,9 +642,8 @@ extern int hisi_sas_probe(struct platform_device *pdev, const struct hisi_sas_hw *ops); extern void hisi_sas_remove(struct platform_device *pdev); -int hisi_sas_device_configure(struct scsi_device *sdev, - struct queue_limits *lim); -extern int hisi_sas_slave_alloc(struct scsi_device *sdev); +int hisi_sas_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim); +extern int hisi_sas_sdev_init(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); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 53cb15f6714b..944cf2fb0561 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -21,8 +21,32 @@ struct hisi_sas_internal_abort_data { bool rst_ha_timeout; /* reset the HA for timeout */ }; -u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) +static u8 hisi_sas_get_ata_protocol_from_tf(struct ata_queued_cmd *qc) { + if (!qc) + return HISI_SAS_SATA_PROTOCOL_PIO; + + switch (qc->tf.protocol) { + case ATA_PROT_NODATA: + return HISI_SAS_SATA_PROTOCOL_NONDATA; + case ATA_PROT_PIO: + return HISI_SAS_SATA_PROTOCOL_PIO; + case ATA_PROT_DMA: + return HISI_SAS_SATA_PROTOCOL_DMA; + case ATA_PROT_NCQ_NODATA: + case ATA_PROT_NCQ: + return HISI_SAS_SATA_PROTOCOL_FPDMA; + default: + return HISI_SAS_SATA_PROTOCOL_PIO; + } +} + +u8 hisi_sas_get_ata_protocol(struct sas_task *task) +{ + struct host_to_dev_fis *fis = &task->ata_task.fis; + struct ata_queued_cmd *qc = task->uldd_task; + int direction = task->data_dir; + switch (fis->command) { case ATA_CMD_FPDMA_WRITE: case ATA_CMD_FPDMA_READ: @@ -93,7 +117,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) { if (direction == DMA_NONE) return HISI_SAS_SATA_PROTOCOL_NONDATA; - return HISI_SAS_SATA_PROTOCOL_PIO; + return hisi_sas_get_ata_protocol_from_tf(qc); } } } @@ -805,13 +829,13 @@ static int hisi_sas_init_device(struct domain_device *device) return rc; } -int hisi_sas_slave_alloc(struct scsi_device *sdev) +int hisi_sas_sdev_init(struct scsi_device *sdev) { struct domain_device *ddev = sdev_to_domain_dev(sdev); struct hisi_sas_device *sas_dev = ddev->lldd_dev; int rc; - rc = sas_slave_alloc(sdev); + rc = sas_sdev_init(sdev); if (rc) return rc; @@ -821,7 +845,7 @@ int hisi_sas_slave_alloc(struct scsi_device *sdev) sas_dev->dev_status = HISI_SAS_DEV_NORMAL; return 0; } -EXPORT_SYMBOL_GPL(hisi_sas_slave_alloc); +EXPORT_SYMBOL_GPL(hisi_sas_sdev_init); static int hisi_sas_dev_found(struct domain_device *device) { @@ -868,11 +892,10 @@ err_out: return rc; } -int hisi_sas_device_configure(struct scsi_device *sdev, - struct queue_limits *lim) +int hisi_sas_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim) { struct domain_device *dev = sdev_to_domain_dev(sdev); - int ret = sas_device_configure(sdev, lim); + int ret = sas_sdev_configure(sdev, lim); if (ret) return ret; @@ -881,7 +904,7 @@ int hisi_sas_device_configure(struct scsi_device *sdev, return 0; } -EXPORT_SYMBOL_GPL(hisi_sas_device_configure); +EXPORT_SYMBOL_GPL(hisi_sas_sdev_configure); void hisi_sas_scan_start(struct Scsi_Host *shost) { @@ -912,8 +935,28 @@ static void hisi_sas_phyup_work_common(struct work_struct *work, container_of(work, typeof(*phy), works[event]); struct hisi_hba *hisi_hba = phy->hisi_hba; struct asd_sas_phy *sas_phy = &phy->sas_phy; + struct asd_sas_port *sas_port = sas_phy->port; + struct hisi_sas_port *port = phy->port; + struct device *dev = hisi_hba->dev; + struct domain_device *port_dev; int phy_no = sas_phy->id; + if (!test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags) && + sas_port && port && (port->id != phy->port_id)) { + dev_info(dev, "phy%d's hw port id changed from %d to %llu\n", + phy_no, port->id, phy->port_id); + port_dev = sas_port->port_dev; + if (port_dev && !dev_is_expander(port_dev->dev_type)) { + /* + * Set the device state to gone to block + * sending IO to the device. + */ + set_bit(SAS_DEV_GONE, &port_dev->state); + hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET); + return; + } + } + phy->wait_phyup_cnt = 0; if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP) hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no); @@ -1525,7 +1568,7 @@ void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba) * which is also only used for v1/v2 hw to skip it for v3 hw */ if (hisi_hba->hw->sht) - del_timer_sync(&hisi_hba->timer); + timer_delete_sync(&hisi_hba->timer); set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); } @@ -2340,7 +2383,7 @@ void hisi_sas_free(struct hisi_hba *hisi_hba) for (i = 0; i < hisi_hba->n_phy; i++) { struct hisi_sas_phy *phy = &hisi_hba->phy[i]; - del_timer_sync(&phy->timer); + timer_delete_sync(&phy->timer); } if (hisi_hba->wq) @@ -2602,7 +2645,7 @@ void hisi_sas_remove(struct platform_device *pdev) struct hisi_hba *hisi_hba = sha->lldd_ha; struct Scsi_Host *shost = sha->shost; - del_timer_sync(&hisi_hba->timer); + timer_delete_sync(&hisi_hba->timer); sas_unregister_ha(sha); sas_remove_host(shost); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index c3e571be2222..6621d633b2cc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1753,11 +1753,11 @@ static int check_fw_info_v1_hw(struct hisi_hba *hisi_hba) static const struct scsi_host_template sht_v1_hw = { LIBSAS_SHT_BASE_NO_SLAVE_INIT - .device_configure = hisi_sas_device_configure, + .sdev_configure = hisi_sas_sdev_configure, .scan_finished = hisi_sas_scan_finished, .scan_start = hisi_sas_scan_start, .sg_tablesize = HISI_SAS_SGE_PAGE_CNT, - .slave_alloc = hisi_sas_slave_alloc, + .sdev_init = hisi_sas_sdev_init, .shost_groups = host_v1_hw_groups, .host_reset = hisi_sas_host_reset, }; @@ -1806,7 +1806,7 @@ static struct platform_driver hisi_sas_v1_driver = { .driver = { .name = DRV_NAME, .of_match_table = sas_v1_of_match, - .acpi_match_table = ACPI_PTR(sas_v1_acpi_match), + .acpi_match_table = sas_v1_acpi_match, }, }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 1a62b5d15eca..1e9830940f84 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2372,18 +2372,18 @@ static void slot_complete_v2_hw(struct hisi_hba *hisi_hba, case STAT_IO_COMPLETE: /* internal abort command complete */ ts->stat = TMF_RESP_FUNC_SUCC; - del_timer_sync(&slot->internal_abort_timer); + timer_delete_sync(&slot->internal_abort_timer); goto out; case STAT_IO_NO_DEVICE: ts->stat = TMF_RESP_FUNC_COMPLETE; - del_timer_sync(&slot->internal_abort_timer); + timer_delete_sync(&slot->internal_abort_timer); goto out; case STAT_IO_NOT_VALID: /* abort single io, controller don't find * the io need to abort */ ts->stat = TMF_RESP_FUNC_FAILED; - del_timer_sync(&slot->internal_abort_timer); + timer_delete_sync(&slot->internal_abort_timer); goto out; default: break; @@ -2501,6 +2501,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_port *port = to_hisi_sas_port(sas_port); struct sas_ata_task *ata_task = &task->ata_task; struct sas_tmf_task *tmf = slot->tmf; + int phy_id; u8 *buf_cmd; int has_data = 0, hdr_tag = 0; u32 dw0, dw1 = 0, dw2 = 0; @@ -2508,10 +2509,14 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, /* create header */ /* dw0 */ dw0 = port->id << CMD_HDR_PORT_OFF; - if (parent_dev && dev_is_expander(parent_dev->dev_type)) + if (parent_dev && dev_is_expander(parent_dev->dev_type)) { dw0 |= 3 << CMD_HDR_CMD_OFF; - else + } else { + phy_id = device->phy->identify.phy_identifier; + dw0 |= (1U << phy_id) << CMD_HDR_PHY_ID_OFF; + dw0 |= CMD_HDR_FORCE_PHY_MSK; dw0 |= 4 << CMD_HDR_CMD_OFF; + } if (tmf && ata_task->force_phy) { dw0 |= CMD_HDR_FORCE_PHY_MSK; @@ -2538,9 +2543,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, (task->ata_task.fis.control & ATA_SRST)) dw1 |= 1 << CMD_HDR_RESET_OFF; - dw1 |= (hisi_sas_get_ata_protocol( - &task->ata_task.fis, task->data_dir)) - << CMD_HDR_FRAME_TYPE_OFF; + dw1 |= (hisi_sas_get_ata_protocol(task)) << CMD_HDR_FRAME_TYPE_OFF; dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF; hdr->dw1 = cpu_to_le32(dw1); @@ -2656,7 +2659,7 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) if (is_sata_phy_v2_hw(hisi_hba, phy_no)) goto end; - del_timer(&phy->timer); + timer_delete(&phy->timer); if (phy_no == 8) { u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE); @@ -2732,7 +2735,7 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) struct hisi_sas_port *port = phy->port; struct device *dev = hisi_hba->dev; - del_timer(&phy->timer); + timer_delete(&phy->timer); hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); @@ -2746,7 +2749,7 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) if (port && !get_wideport_bitmap_v2_hw(hisi_hba, port->id)) if (!check_any_wideports_v2_hw(hisi_hba) && timer_pending(&hisi_hba->timer)) - del_timer(&hisi_hba->timer); + timer_delete(&hisi_hba->timer); txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO); hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO, @@ -3206,7 +3209,7 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) u8 attached_sas_addr[SAS_ADDR_SIZE] = {0}; int phy_no, offset; - del_timer(&phy->timer); + timer_delete(&phy->timer); phy_no = sas_phy->id; initial_fis = &hisi_hba->initial_fis[phy_no]; @@ -3585,11 +3588,11 @@ static int check_fw_info_v2_hw(struct hisi_hba *hisi_hba) static const struct scsi_host_template sht_v2_hw = { LIBSAS_SHT_BASE_NO_SLAVE_INIT - .device_configure = hisi_sas_device_configure, + .sdev_configure = hisi_sas_sdev_configure, .scan_finished = hisi_sas_scan_finished, .scan_start = hisi_sas_scan_start, .sg_tablesize = HISI_SAS_SGE_PAGE_CNT, - .slave_alloc = hisi_sas_slave_alloc, + .sdev_init = hisi_sas_sdev_init, .shost_groups = host_v2_hw_groups, .sdev_groups = sdev_groups_v2_hw, .host_reset = hisi_sas_host_reset, @@ -3653,7 +3656,7 @@ static struct platform_driver hisi_sas_v2_driver = { .driver = { .name = DRV_NAME, .of_match_table = sas_v2_of_match, - .acpi_match_table = ACPI_PTR(sas_v2_acpi_match), + .acpi_match_table = sas_v2_acpi_match, }, }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 5db931663ae4..08dac9ae2f10 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -359,6 +359,10 @@ #define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF) #define CMD_HDR_TLR_CTRL_OFF 6 #define CMD_HDR_TLR_CTRL_MSK (0x3 << CMD_HDR_TLR_CTRL_OFF) +#define CMD_HDR_PHY_ID_OFF 8 +#define CMD_HDR_PHY_ID_MSK (0x1ff << CMD_HDR_PHY_ID_OFF) +#define CMD_HDR_FORCE_PHY_OFF 17 +#define CMD_HDR_FORCE_PHY_MSK (0x1U << CMD_HDR_FORCE_PHY_OFF) #define CMD_HDR_PORT_OFF 18 #define CMD_HDR_PORT_MSK (0xf << CMD_HDR_PORT_OFF) #define CMD_HDR_PRIORITY_OFF 27 @@ -1429,15 +1433,21 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr; struct asd_sas_port *sas_port = device->port; struct hisi_sas_port *port = to_hisi_sas_port(sas_port); + int phy_id; u8 *buf_cmd; int has_data = 0, hdr_tag = 0; u32 dw1 = 0, dw2 = 0; hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF); - if (parent_dev && dev_is_expander(parent_dev->dev_type)) + if (parent_dev && dev_is_expander(parent_dev->dev_type)) { hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF); - else + } else { + phy_id = device->phy->identify.phy_identifier; + hdr->dw0 |= cpu_to_le32((1U << phy_id) + << CMD_HDR_PHY_ID_OFF); + hdr->dw0 |= CMD_HDR_FORCE_PHY_MSK; hdr->dw0 |= cpu_to_le32(4U << CMD_HDR_CMD_OFF); + } switch (task->data_dir) { case DMA_TO_DEVICE: @@ -1456,9 +1466,7 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, (task->ata_task.fis.control & ATA_SRST)) dw1 |= 1 << CMD_HDR_RESET_OFF; - dw1 |= (hisi_sas_get_ata_protocol( - &task->ata_task.fis, task->data_dir)) - << CMD_HDR_FRAME_TYPE_OFF; + dw1 |= (hisi_sas_get_ata_protocol(task)) << CMD_HDR_FRAME_TYPE_OFF; dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF; if (FIS_CMD_IS_UNCONSTRAINED(task->ata_task.fis)) @@ -1611,7 +1619,7 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) phy->port_id = port_id; spin_lock(&phy->lock); /* Delete timer and set phy_attached atomically */ - del_timer(&phy->timer); + timer_delete(&phy->timer); phy->phy_attached = 1; spin_unlock(&phy->lock); @@ -1645,7 +1653,7 @@ static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba) atomic_inc(&phy->down_cnt); - del_timer(&phy->timer); + timer_delete(&phy->timer); hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); @@ -2908,12 +2916,12 @@ static ssize_t iopoll_q_cnt_v3_hw_show(struct device *dev, } static DEVICE_ATTR_RO(iopoll_q_cnt_v3_hw); -static int device_configure_v3_hw(struct scsi_device *sdev, - struct queue_limits *lim) +static int sdev_configure_v3_hw(struct scsi_device *sdev, + struct queue_limits *lim) { struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev); struct hisi_hba *hisi_hba = shost_priv(shost); - int ret = hisi_sas_device_configure(sdev, lim); + int ret = hisi_sas_sdev_configure(sdev, lim); struct device *dev = hisi_hba->dev; if (ret) @@ -3328,24 +3336,24 @@ static void hisi_sas_map_queues(struct Scsi_Host *shost) if (i == HCTX_TYPE_POLL) blk_mq_map_queues(qmap); else - blk_mq_pci_map_queues(qmap, hisi_hba->pci_dev, - BASE_VECTORS_V3_HW); + blk_mq_map_hw_queues(qmap, hisi_hba->dev, + BASE_VECTORS_V3_HW); qoff += qmap->nr_queues; } } static const struct scsi_host_template sht_v3_hw = { LIBSAS_SHT_BASE_NO_SLAVE_INIT - .device_configure = device_configure_v3_hw, + .sdev_configure = sdev_configure_v3_hw, .scan_finished = hisi_sas_scan_finished, .scan_start = hisi_sas_scan_start, .map_queues = hisi_sas_map_queues, .sg_tablesize = HISI_SAS_SGE_PAGE_CNT, .sg_prot_tablesize = HISI_SAS_SGE_PAGE_CNT, - .slave_alloc = hisi_sas_slave_alloc, + .sdev_init = hisi_sas_sdev_init, .shost_groups = host_v3_hw_groups, .sdev_groups = sdev_groups_v3_hw, - .tag_alloc_policy = BLK_TAG_ALLOC_RR, + .tag_alloc_policy_rr = true, .host_reset = hisi_sas_host_reset, .host_tagset = 1, .mq_poll = queue_complete_v3_hw, |