diff options
author | Xiang Chen <chenxiang66@hisilicon.com> | 2018-05-09 23:10:48 +0800 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-05-18 11:22:09 -0400 |
commit | fa222db0b036899cd4020a380568699ffb1de08d (patch) | |
tree | 60ddc348aa3d3b0aa5b49e97e79a592e138947a7 /drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | |
parent | 3de0026dad6b8e83d8a699aef92638c50ba966f7 (diff) |
scsi: hisi_sas: Don't lock DQ for complete task sending
Currently we lock the DQ to protect whole delivery process. So this
stops us building slots for the same queue in parallel, and can affect
performance.
To optimise it, only lock the DQ during special periods, specifically
when allocating a slot from the DQ and when delivering a slot to the HW.
This approach is now safe, thanks to the previous patches to ensure that
we always deliver a slot to the HW once allocated.
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>
Diffstat (limited to 'drivers/scsi/hisi_sas/hisi_sas_v3_hw.c')
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 8cd13744a090..56f1046b244c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -840,23 +840,37 @@ get_free_slot_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq) 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, "full queue=%d r=%d w=%d\n\n", + dev_warn(dev, "full queue=%d r=%d w=%d\n", queue, r, w); return -EAGAIN; } - return 0; + dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; + + return w; } static void start_delivery_v3_hw(struct hisi_sas_dq *dq) { struct hisi_hba *hisi_hba = dq->hisi_hba; - int dlvry_queue = dq->slot_prep->dlvry_queue; - int dlvry_queue_slot = dq->slot_prep->dlvry_queue_slot; + struct hisi_sas_slot *s, *s1; + struct list_head *dq_list; + int dlvry_queue = dq->id; + int wp, count = 0; + + dq_list = &dq->list; + list_for_each_entry_safe(s, s1, &dq->list, delivery) { + if (!s->ready) + break; + count++; + wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS; + list_del(&s->delivery); + } + + if (!count) + return; - dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS; - hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), - dq->wr_point); + hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp); } static void prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba, |