322 lines
12 KiB
Diff
322 lines
12 KiB
Diff
From d35bf6fccf7d4064065c078d3d369ffeaad6c731 Mon Sep 17 00:00:00 2001
|
|
From: Xiang Chen <chenxiang66@hisilicon.com>
|
|
Date: Mon, 24 Sep 2018 23:06:33 +0800
|
|
Subject: [PATCH 06/31] scsi: hisi_sas: Use block layer tag instead for IPTT
|
|
Origin: https://git.kernel.org/linus/784b46b7cba0ae914dd293f23848c5057c6ba017
|
|
|
|
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>
|
|
---
|
|
drivers/scsi/hisi_sas/hisi_sas.h | 3 +-
|
|
drivers/scsi/hisi_sas/hisi_sas_main.c | 89 +++++++++++++++++---------
|
|
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 -
|
|
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 9 +--
|
|
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 2f57a318a71b..c2998d3ac37f 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
@@ -184,7 +184,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)
|
|
@@ -194,24 +201,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)
|
|
@@ -250,9 +267,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);
|
|
|
|
@@ -385,16 +400,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);
|
|
@@ -455,9 +481,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) {
|
|
@@ -1742,14 +1766,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);
|
|
@@ -1785,7 +1806,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);
|
|
@@ -1796,9 +1816,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);
|
|
|
|
@@ -2174,6 +2192,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) {
|
|
@@ -2377,8 +2397,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 410eccf0bc5e..8df822a4a1bd 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
|
|
@@ -1807,7 +1807,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 c4774d63d5d0..58a564c75a35 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)
|
|
@@ -3558,7 +3560,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 06824bde9c8d..a0fc2d5de787 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
@@ -2096,7 +2096,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,
|
|
@@ -2106,6 +2105,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 = {
|
|
@@ -2243,8 +2243,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;
|
|
--
|
|
2.20.1
|
|
|