From patchwork Wed May 9 15:10:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 135291 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp5760099lji; Wed, 9 May 2018 08:12:18 -0700 (PDT) X-Google-Smtp-Source: AB8JxZp5u823ZwE3X/uPR3Bd81F4IAVY8Z0+y6Zouw05Wodt6XVgoEd8c+QDwB4OT7hOzDSFIgyk X-Received: by 2002:a63:7f18:: with SMTP id a24-v6mr2550705pgd.312.1525878738183; Wed, 09 May 2018 08:12:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525878738; cv=none; d=google.com; s=arc-20160816; b=GokdJthnAkLkmW/DA0L9RZw/eI4ZBXxEwuzIRSxiAEGVL+HAS0y2hTuIXzirnDVI8V PdZWLmecXF1CDdslY5kYanLA7vjh+JstMGgZtZ/+OtXwBy7uYjKDPQJ99gOzgMZOIOIH D3hYArm7cysIQ2kzUyfppus2zu1R+VNExcxt/SXd+WHq+mA63sx3E9ttI8ntaYRWv9a1 MYDIr4YByUOVR8xZfBNgBCw/V1OrvGOMC//XIeN4+kwohatufeWiLU4Dz4xM0wO0pCsN KKIPzHeXGa10nDsMa1zU7B9ZclCXpEeI5kUQ4hEHxy3NS+i84TyWpwlM1FGtkbzFH2vF /zmQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=pP6+OA5YAzpqK2FwkaFHVpZzAbhIel3a7zCpaQbaqpg=; b=M1DILNBtgkGgSc3cyIX1bDxaRUojS+AjmoOMjZ9V3iIJhInF5vdLDhPTgYKpSZ919s TNKH0phlyECzwTgaK0ezb9FOZDP7SVrDEORdXM5ZZt9E5ANJbmUelfqjw2g3WR1vsvOv sqvESlCEtpZs/WiSGc9x9Kn4+PqV5ePkgO5nvLu8HVGFIUauc7HQXlCeWieR4N6E754C ttC7+Rt7dPw/1dH80sljinL9QYMMXnRhHlhGv5Tsvcc+6AET0rNfHnVvfKCV4s9y0f0Z iHQ9ggrx1FA/G6Sdd5qYkALdsGRweXfBvNg2Ph63SuCzqq56qcQpaPt1e+s1zqkQvSYG aLNA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-scsi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-scsi-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r25-v6si21949599pgu.219.2018.05.09.08.12.17; Wed, 09 May 2018 08:12:18 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-scsi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-scsi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-scsi-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964870AbeEIPMQ (ORCPT + 1 other); Wed, 9 May 2018 11:12:16 -0400 Received: from szxga06-in.huawei.com ([45.249.212.32]:47096 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S964817AbeEIPMN (ORCPT ); Wed, 9 May 2018 11:12:13 -0400 Received: from DGGEMS410-HUB.china.huawei.com (unknown [172.30.72.60]) by Forcepoint Email with ESMTP id 4D02A34D42A09; Wed, 9 May 2018 23:12:08 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS410-HUB.china.huawei.com (10.3.19.210) with Microsoft SMTP Server id 14.3.361.1; Wed, 9 May 2018 23:12:00 +0800 From: John Garry To: , CC: , , , Xiang Chen , "John Garry" Subject: [PATCH 4/6] scsi: hisi_sas: Don't lock DQ for complete task sending Date: Wed, 9 May 2018 23:10:48 +0800 Message-ID: <1525878650-213087-5-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1525878650-213087-1-git-send-email-john.garry@huawei.com> References: <1525878650-213087-1-git-send-email-john.garry@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.75] X-CFilter-Loop: Reflected Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Xiang Chen 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 Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas.h | 4 ++- drivers/scsi/hisi_sas/hisi_sas_main.c | 49 ++++++++++++++++++++-------------- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 27 ++++++++++++++----- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 29 +++++++++++++++----- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 28 ++++++++++++++----- 5 files changed, 96 insertions(+), 41 deletions(-) -- 1.9.1 diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 3a1caa04..52fc709 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -161,7 +161,7 @@ struct hisi_sas_cq { struct hisi_sas_dq { struct hisi_hba *hisi_hba; - struct hisi_sas_slot *slot_prep; + struct list_head list; spinlock_t lock; int wr_point; int id; @@ -181,6 +181,7 @@ struct hisi_sas_device { struct hisi_sas_slot { struct list_head entry; + struct list_head delivery; struct sas_task *task; struct hisi_sas_port *port; u64 n_elem; @@ -190,6 +191,7 @@ struct hisi_sas_slot { int cmplt_queue_slot; int idx; int abort; + int ready; void *buf; dma_addr_t buf_dma; void *cmd_hdr; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 58cbe1f..bf374a7 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -307,9 +307,9 @@ static void hisi_sas_slot_abort(struct work_struct *work) task->task_done(task); } -static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq - *dq, int is_tmf, struct hisi_sas_tmf_task *tmf, - int *pass) +static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq *dq, + int is_tmf, struct hisi_sas_tmf_task *tmf, + int *pass) { struct hisi_hba *hisi_hba = dq->hisi_hba; struct domain_device *device = task->dev; @@ -321,7 +321,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq struct device *dev = hisi_hba->dev; int dlvry_queue_slot, dlvry_queue, rc, slot_idx; int n_elem = 0, n_elem_req = 0, n_elem_resp = 0; - unsigned long flags; + unsigned long flags, flags_dq; + int wr_q_index; if (!sas_port) { struct task_status_struct *ts = &task->task_status; @@ -422,12 +423,18 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq goto err_out_tag; } - rc = hisi_hba->hw->get_free_slot(hisi_hba, dq); - if (rc) + spin_lock_irqsave(&dq->lock, flags_dq); + wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq); + if (wr_q_index < 0) { + spin_unlock_irqrestore(&dq->lock, flags_dq); goto err_out_buf; + } + + list_add_tail(&slot->delivery, &dq->list); + spin_unlock_irqrestore(&dq->lock, flags_dq); dlvry_queue = dq->id; - dlvry_queue_slot = dq->wr_point; + dlvry_queue_slot = wr_q_index; slot->idx = slot_idx; slot->n_elem = n_elem; @@ -471,8 +478,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); - dq->slot_prep = slot; ++(*pass); + slot->ready = 1; return 0; @@ -518,11 +525,11 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags, return -EINVAL; /* protect task_prep and start_delivery sequence */ - spin_lock_irqsave(&dq->lock, flags); rc = hisi_sas_task_prep(task, dq, is_tmf, tmf, &pass); if (rc) dev_err(dev, "task exec: failed[%d]!\n", rc); + spin_lock_irqsave(&dq->lock, flags); if (likely(pass)) hisi_hba->hw->start_delivery(dq); spin_unlock_irqrestore(&dq->lock, flags); @@ -1503,7 +1510,8 @@ static int hisi_sas_query_task(struct sas_task *task) struct hisi_sas_cmd_hdr *cmd_hdr_base; struct hisi_sas_dq *dq = sas_dev->dq; int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx; - unsigned long flags, flags_dq; + unsigned long flags, flags_dq = 0; + int wr_q_index; if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) return -EINVAL; @@ -1531,16 +1539,18 @@ static int hisi_sas_query_task(struct sas_task *task) rc = -ENOMEM; goto err_out_tag; } + spin_lock_irqsave(&dq->lock, flags_dq); - rc = hisi_hba->hw->get_free_slot(hisi_hba, dq); - if (rc) { - rc = -ENOMEM; + wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq); + if (wr_q_index < 0) { spin_unlock_irqrestore(&dq->lock, flags_dq); goto err_out_buf; } + list_add_tail(&slot->delivery, &dq->list); + spin_unlock_irqrestore(&dq->lock, flags_dq); dlvry_queue = dq->id; - dlvry_queue_slot = dq->wr_point; + dlvry_queue_slot = wr_q_index; slot->idx = slot_idx; slot->n_elem = n_elem; @@ -1560,18 +1570,16 @@ static int hisi_sas_query_task(struct sas_task *task) hisi_sas_task_prep_abort(hisi_hba, slot, device_id, abort_flag, task_tag); - spin_lock_irqsave(&hisi_hba->lock, flags); - list_add_tail(&slot->entry, &sas_dev->list); - spin_unlock_irqrestore(&hisi_hba->lock, flags); spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); - dq->slot_prep = slot; - + slot->ready = 1; /* send abort command to the chip */ + spin_lock_irqsave(&dq->lock, flags); + list_add_tail(&slot->entry, &sas_dev->list); hisi_hba->hw->start_delivery(dq); - spin_unlock_irqrestore(&dq->lock, flags_dq); + spin_unlock_irqrestore(&dq->lock, flags); return 0; @@ -1856,6 +1864,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost) /* Delivery queue structure */ spin_lock_init(&dq->lock); + INIT_LIST_HEAD(&dq->list); dq->id = i; dq->hisi_hba = hisi_hba; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 7781a01..abe175f 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -921,18 +921,33 @@ static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id) return -EAGAIN; } - return 0; + dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; + + return w; } +/* DQ lock must be taken here */ static void start_delivery_v1_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_v1_hw(struct hisi_hba *hisi_hba, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 9f77fd8..911bb76 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1663,23 +1663,38 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id) 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; } +/* DQ lock must be taken here */ static void start_delivery_v2_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_v2_hw(struct hisi_hba *hisi_hba, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 8cd1374..56f1046 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 @@ static int get_wideport_bitmap_v3_hw(struct hisi_hba *hisi_hba, int port_id) 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,