diff options
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas.h | 3 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_main.c | 89 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 9 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 8 |
5 files changed, 70 insertions, 40 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 6c7d2e201abe..0ddb53c8a2e2 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -34,6 +34,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_RESERVED_IPTT_CNT 96 #define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer)) #define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table)) @@ -217,7 +218,7 @@ struct hisi_sas_hw { int (*hw_init)(struct hisi_hba *hisi_hba); void (*setup_itct)(struct hisi_hba *hisi_hba, struct hisi_sas_device *device); - int (*slot_index_alloc)(struct hisi_hba *hisi_hba, int *slot_idx, + int (*slot_index_alloc)(struct hisi_hba *hisi_hba, struct domain_device *device); struct hisi_sas_device *(*alloc_dev)(struct domain_device *device); void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index a20bd6048e98..2e5eaf1a73a0 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -183,7 +183,14 @@ static void hisi_sas_slot_index_clear(struct hisi_hba *hisi_hba, int slot_idx) static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx) { - hisi_sas_slot_index_clear(hisi_hba, slot_idx); + unsigned long flags; + + if (hisi_hba->hw->slot_index_alloc || (slot_idx >= + hisi_hba->hw->max_command_entries - HISI_SAS_RESERVED_IPTT_CNT)) { + spin_lock_irqsave(&hisi_hba->lock, flags); + hisi_sas_slot_index_clear(hisi_hba, slot_idx); + spin_unlock_irqrestore(&hisi_hba->lock, flags); + } } static void hisi_sas_slot_index_set(struct hisi_hba *hisi_hba, int slot_idx) @@ -193,24 +200,34 @@ static void hisi_sas_slot_index_set(struct hisi_hba *hisi_hba, int slot_idx) set_bit(slot_idx, bitmap); } -static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, int *slot_idx) +static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, + struct scsi_cmnd *scsi_cmnd) { - unsigned int index; + int index; void *bitmap = hisi_hba->slot_index_tags; + unsigned long flags; + if (scsi_cmnd) + return scsi_cmnd->request->tag; + + spin_lock_irqsave(&hisi_hba->lock, flags); index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, - hisi_hba->last_slot_index + 1); + hisi_hba->last_slot_index + 1); if (index >= hisi_hba->slot_index_count) { - index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, - 0); - if (index >= hisi_hba->slot_index_count) + index = find_next_zero_bit(bitmap, + hisi_hba->slot_index_count, + hisi_hba->hw->max_command_entries - + HISI_SAS_RESERVED_IPTT_CNT); + if (index >= hisi_hba->slot_index_count) { + spin_unlock_irqrestore(&hisi_hba->lock, flags); return -SAS_QUEUE_FULL; + } } hisi_sas_slot_index_set(hisi_hba, index); - *slot_idx = index; hisi_hba->last_slot_index = index; + spin_unlock_irqrestore(&hisi_hba->lock, flags); - return 0; + return index; } static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba) @@ -249,9 +266,7 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, memset(slot, 0, offsetof(struct hisi_sas_slot, buf)); - spin_lock_irqsave(&hisi_hba->lock, flags); hisi_sas_slot_index_free(hisi_hba, slot->idx); - spin_unlock_irqrestore(&hisi_hba->lock, flags); } EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free); @@ -384,16 +399,27 @@ static int hisi_sas_task_prep(struct sas_task *task, goto err_out_dma_unmap; } - spin_lock_irqsave(&hisi_hba->lock, flags); if (hisi_hba->hw->slot_index_alloc) - rc = hisi_hba->hw->slot_index_alloc(hisi_hba, &slot_idx, - device); - else - rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); - spin_unlock_irqrestore(&hisi_hba->lock, flags); - if (rc) + rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device); + else { + struct scsi_cmnd *scsi_cmnd = NULL; + + if (task->uldd_task) { + struct ata_queued_cmd *qc; + + if (dev_is_sata(device)) { + qc = task->uldd_task; + scsi_cmnd = qc->scsicmd; + } else { + scsi_cmnd = task->uldd_task; + } + } + rc = hisi_sas_slot_index_alloc(hisi_hba, scsi_cmnd); + } + if (rc < 0) goto err_out_dma_unmap; + slot_idx = rc; slot = &hisi_hba->slot_info[slot_idx]; spin_lock_irqsave(&dq->lock, flags); @@ -454,9 +480,7 @@ static int hisi_sas_task_prep(struct sas_task *task, return 0; err_out_tag: - spin_lock_irqsave(&hisi_hba->lock, flags); hisi_sas_slot_index_free(hisi_hba, slot_idx); - spin_unlock_irqrestore(&hisi_hba->lock, flags); err_out_dma_unmap: if (!sas_protocol_ata(task->task_proto)) { if (task->num_scatter) { @@ -1740,14 +1764,11 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, port = to_hisi_sas_port(sas_port); /* simply get a slot and send abort command */ - spin_lock_irqsave(&hisi_hba->lock, flags); - rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); - if (rc) { - spin_unlock_irqrestore(&hisi_hba->lock, flags); + rc = hisi_sas_slot_index_alloc(hisi_hba, NULL); + if (rc < 0) goto err_out; - } - spin_unlock_irqrestore(&hisi_hba->lock, flags); + slot_idx = rc; slot = &hisi_hba->slot_info[slot_idx]; spin_lock_irqsave(&dq->lock, flags_dq); @@ -1783,7 +1804,6 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); - WRITE_ONCE(slot->ready, 1); /* send abort command to the chip */ spin_lock_irqsave(&dq->lock, flags); @@ -1794,9 +1814,7 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, return 0; err_out_tag: - spin_lock_irqsave(&hisi_hba->lock, flags); hisi_sas_slot_index_free(hisi_hba, slot_idx); - spin_unlock_irqrestore(&hisi_hba->lock, flags); err_out: dev_err(dev, "internal abort task prep: failed[%d]!\n", rc); @@ -2158,6 +2176,8 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost) hisi_sas_init_mem(hisi_hba); hisi_sas_slot_index_init(hisi_hba); + hisi_hba->last_slot_index = hisi_hba->hw->max_command_entries - + HISI_SAS_RESERVED_IPTT_CNT; hisi_hba->wq = create_singlethread_workqueue(dev_name(dev)); if (!hisi_hba->wq) { @@ -2361,8 +2381,15 @@ int hisi_sas_probe(struct platform_device *pdev, shost->max_channel = 1; shost->max_cmd_len = 16; shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT); - shost->can_queue = hisi_hba->hw->max_command_entries; - shost->cmd_per_lun = hisi_hba->hw->max_command_entries; + if (hisi_hba->hw->slot_index_alloc) { + shost->can_queue = hisi_hba->hw->max_command_entries; + shost->cmd_per_lun = hisi_hba->hw->max_command_entries; + } else { + shost->can_queue = hisi_hba->hw->max_command_entries - + HISI_SAS_RESERVED_IPTT_CNT; + shost->cmd_per_lun = hisi_hba->hw->max_command_entries - + HISI_SAS_RESERVED_IPTT_CNT; + } sha->sas_ha_name = DRV_NAME; sha->dev = hisi_hba->dev; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 8f60f0e04599..f0e457e6884e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1809,7 +1809,6 @@ static struct scsi_host_template sht_v1_hw = { .scan_start = hisi_sas_scan_start, .change_queue_depth = sas_change_queue_depth, .bios_param = sas_bios_param, - .can_queue = 1, .this_id = -1, .sg_tablesize = SG_ALL, .max_sectors = SCSI_DEFAULT_MAX_SECTORS, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 67134b49a9b9..70d6b28f390a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -770,7 +770,7 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba, /* This function needs to be protected from pre-emption. */ static int -slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, +slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, struct domain_device *device) { int sata_dev = dev_is_sata(device); @@ -778,6 +778,7 @@ slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, struct hisi_sas_device *sas_dev = device->lldd_dev; int sata_idx = sas_dev->sata_idx; int start, end; + unsigned long flags; if (!sata_dev) { /* @@ -801,6 +802,7 @@ slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, end = 64 * (sata_idx + 2); } + spin_lock_irqsave(&hisi_hba->lock, flags); while (1) { start = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, start); @@ -815,8 +817,8 @@ slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, } set_bit(start, bitmap); - *slot_idx = start; - return 0; + spin_unlock_irqrestore(&hisi_hba->lock, flags); + return start; } static bool sata_index_alloc_v2_hw(struct hisi_hba *hisi_hba, int *idx) @@ -3560,7 +3562,6 @@ static struct scsi_host_template sht_v2_hw = { .scan_start = hisi_sas_scan_start, .change_queue_depth = sas_change_queue_depth, .bios_param = sas_bios_param, - .can_queue = 1, .this_id = -1, .sg_tablesize = SG_ALL, .max_sectors = SCSI_DEFAULT_MAX_SECTORS, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 34c8f30483c6..f30c4e4ff24d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2098,7 +2098,6 @@ static struct scsi_host_template sht_v3_hw = { .scan_start = hisi_sas_scan_start, .change_queue_depth = sas_change_queue_depth, .bios_param = sas_bios_param, - .can_queue = 1, .this_id = -1, .sg_tablesize = SG_ALL, .max_sectors = SCSI_DEFAULT_MAX_SECTORS, @@ -2108,6 +2107,7 @@ static struct scsi_host_template sht_v3_hw = { .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, .shost_attrs = host_attrs, + .tag_alloc_policy = BLK_TAG_ALLOC_RR, }; static const struct hisi_sas_hw hisi_sas_v3_hw = { @@ -2245,8 +2245,10 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) shost->max_channel = 1; shost->max_cmd_len = 16; shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT); - shost->can_queue = hisi_hba->hw->max_command_entries; - shost->cmd_per_lun = hisi_hba->hw->max_command_entries; + shost->can_queue = hisi_hba->hw->max_command_entries - + HISI_SAS_RESERVED_IPTT_CNT; + shost->cmd_per_lun = hisi_hba->hw->max_command_entries - + HISI_SAS_RESERVED_IPTT_CNT; sha->sas_ha_name = DRV_NAME; sha->dev = dev; |