summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
diff options
context:
space:
mode:
authorXiang Chen <chenxiang66@hisilicon.com>2016-11-07 20:48:31 +0800
committerMartin K. Petersen <martin.petersen@oracle.com>2016-11-25 09:54:39 -0500
commitc70f1fb7558f0b3c8f63c3e8a2caeb08eb1f8274 (patch)
tree63a86c798860d72ad9bbc80a5cc4d3a22b187302 /drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
parentd3b688d3c69d318177c104f451b9064831da42b9 (diff)
scsi: hisi_sas: alloc queue id of slot according to device id
Currently slots are allocated from queues in a round-robin fashion. This causes a problem for internal commands in device mode. For this mode, we should ensure that the internal abort command is the last command seen in the host for that device. We can only ensure this when we place the internal abort command after the preceding commands for device that in the same queue, as there is no order in which the host will select a queue to execute the next command. This queue restriction makes supporting scsi mq more tricky in the future, but should not be a blocker. Note: Even though v1 hw does not support internal abort, the allocation method is chosen to be the same for consistency. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: John Garry <john.garry@huawei.com> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/hisi_sas/hisi_sas_v1_hw.c')
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v1_hw.c30
1 files changed, 12 insertions, 18 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index c0ac49d8bc8d..bbc5760dfaf4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -862,29 +862,23 @@ static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id)
* The callpath to this function and upto writing the write
* queue pointer should be safe from interruption.
*/
-static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, int *q, int *s)
+static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, u32 dev_id,
+ int *q, int *s)
{
struct device *dev = &hisi_hba->pdev->dev;
struct hisi_sas_dq *dq;
u32 r, w;
- int queue = hisi_hba->queue;
-
- while (1) {
- dq = &hisi_hba->dq[queue];
- w = dq->wr_point;
- r = hisi_sas_read32_relaxed(hisi_hba,
- DLVRY_Q_0_RD_PTR + (queue * 0x14));
- if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
- queue = (queue + 1) % hisi_hba->queue_count;
- if (queue == hisi_hba->queue) {
- dev_warn(dev, "could not find free slot\n");
- return -EAGAIN;
- }
- continue;
- }
- break;
+ int queue = dev_id % hisi_hba->queue_count;
+
+ dq = &hisi_hba->dq[queue];
+ w = dq->wr_point;
+ r = hisi_sas_read32_relaxed(hisi_hba,
+ DLVRY_Q_0_RD_PTR + (queue * 0x14));
+ if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
+ dev_warn(dev, "could not find free slot\n");
+ return -EAGAIN;
}
- hisi_hba->queue = (queue + 1) % hisi_hba->queue_count;
+
*q = queue;
*s = w;
return 0;