]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
scsi: hisi_sas: Use block layer tag instead for IPTT
authorXiang Chen <chenxiang66@hisilicon.com>
Mon, 24 Sep 2018 15:06:33 +0000 (23:06 +0800)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Mon, 14 Jan 2019 09:28:55 +0000 (09:28 +0000)
BugLink: https://bugs.launchpad.net/bugs/1810457
Currently we use the IPTT defined in LLDD to identify IOs. Actually for
IOs which are from the block layer, they have tags to identify them. So
for those IOs, use tag of the block layer directly, and for IOs which is
not from the block layer (such as internal IOs from libsas/LLDD), reserve
96 IPTTs for them.

Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
(cherry picked from commit 784b46b7cba0ae914dd293f23848c5057c6ba017)
Signed-off-by: dann frazier <dann.frazier@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
drivers/scsi/hisi_sas/hisi_sas.h
drivers/scsi/hisi_sas/hisi_sas_main.c
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

index 6c7d2e201abed7ec29e96bea97852ad8f3812a23..0ddb53c8a2e29fe5b83fa8eb0319ce9fb8c5ea9f 100644 (file)
@@ -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);
index 416f2c0d4d200e4d0d17f3d4847794bdbd2f2ce4..8fcd1ab5fc539682a92777cd058859ab0f272163 100644 (file)
@@ -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);
 
@@ -2163,6 +2181,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) {
@@ -2366,8 +2386,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;
index 8f60f0e0459960616faf1849739632ad2e7c01b2..f0e457e6884e5ca9c92d84c12c1db2cf6906104b 100644 (file)
@@ -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,
index 67134b49a9b9c3a0b0b08513c57fd5a69d361754..70d6b28f390a8f4fe6fa4d32c5c28f6923c4ee9d 100644 (file)
@@ -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,
index 34c8f30483c6c1a3a53db23aca72e7c27acda20c..f30c4e4ff24d90cdf2ef496e3a915c469918315b 100644 (file)
@@ -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;