231 lines
7.2 KiB
Diff
231 lines
7.2 KiB
Diff
From 99990c92d47d2a9485906a9bef7125269344a2b9 Mon Sep 17 00:00:00 2001
|
|
From: Xiang Chen <chenxiang66@hisilicon.com>
|
|
Date: Wed, 6 Feb 2019 18:52:55 +0800
|
|
Subject: [PATCH 004/108] scsi: hisi_sas: Use pci_irq_get_affinity() for v3 hw
|
|
as experimental
|
|
|
|
mainline inclusion
|
|
from mainline-v5.1-rc1
|
|
commit 4fefe5bbf599d6c6bee6b2ee376be789b33ca571
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EKNE
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4fefe5bbf599d6c6bee6b2ee376be789b33ca571
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
For auto-control irq affinity mode, choose the dq to deliver IO according
|
|
to the current CPU.
|
|
|
|
Then it decreases the performance regression that fio and CQ interrupts are
|
|
processed on different node.
|
|
|
|
For user control irq affinity mode, keep it as before.
|
|
|
|
To realize it, also need to distinguish the usage of dq lock and sas_dev
|
|
lock.
|
|
|
|
We mark as experimental due to ongoing discussion on managed MSI IRQ
|
|
during hotplug:
|
|
https://marc.info/?l=linux-scsi&m=154876335707751&w=2
|
|
|
|
We're almost at the point where we can expose multiple queues to the upper
|
|
layer for SCSI MQ, but we need to sort out the per-HBA tags performance
|
|
issue.
|
|
|
|
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>
|
|
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>
|
|
|
|
Conflicts:
|
|
drivers/scsi/hisi_sas/hisi_sas.h
|
|
drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
---
|
|
drivers/scsi/hisi_sas/hisi_sas.h | 4 +-
|
|
drivers/scsi/hisi_sas/hisi_sas_main.c | 20 ++++---
|
|
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 74 +++++++++++++++++++-------
|
|
3 files changed, 68 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
|
|
index daa64e5aff3e..06a8bf9f0f73 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas.h
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
|
|
@@ -192,6 +192,7 @@ struct hisi_sas_port {
|
|
|
|
struct hisi_sas_cq {
|
|
struct hisi_hba *hisi_hba;
|
|
+ const struct cpumask *pci_irq_mask;
|
|
struct tasklet_struct tasklet;
|
|
int rd_point;
|
|
int id;
|
|
@@ -214,8 +215,8 @@ struct hisi_sas_device {
|
|
enum sas_device_type dev_type;
|
|
unsigned int device_id;
|
|
int sata_idx;
|
|
- spinlock_t lock;
|
|
enum dev_status dev_status;
|
|
+ spinlock_t lock; /* For protecting slots */
|
|
};
|
|
|
|
struct hisi_sas_tmf_task {
|
|
@@ -420,6 +421,7 @@ struct hisi_hba {
|
|
int bist_loopback_enable;
|
|
|
|
int enable_dix_dif;
|
|
+ unsigned int *reply_map;
|
|
|
|
/* debugfs memories */
|
|
u32 *debugfs_global_reg;
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
index 852ece4af0f4..7ccdaaba311c 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
@@ -456,9 +456,6 @@ static int hisi_sas_task_prep(struct sas_task *task,
|
|
unsigned long flags;
|
|
int wr_q_index;
|
|
unsigned int curr_node_id = numa_node_id();
|
|
- unsigned int dq_index =
|
|
- (hisi_hba->dq_idx[curr_node_id] % hisi_hba->dq_num_per_node) +
|
|
- (hisi_hba->dq_num_per_node * curr_node_id);
|
|
|
|
if (DEV_IS_GONE(sas_dev)) {
|
|
if (sas_dev)
|
|
@@ -471,10 +468,14 @@ static int hisi_sas_task_prep(struct sas_task *task,
|
|
return -ECOMM;
|
|
}
|
|
|
|
- if (hisi_hba->user_ctl_irq)
|
|
- *dq_pointer = dq = sas_dev->dq;
|
|
- else
|
|
+ if (hisi_hba->reply_map) {
|
|
+ int cpu = raw_smp_processor_id();
|
|
+ unsigned int dq_index = hisi_hba->reply_map[cpu];
|
|
+
|
|
*dq_pointer = dq = &hisi_hba->dq[dq_index];
|
|
+ } else {
|
|
+ *dq_pointer = dq = sas_dev->dq;
|
|
+ }
|
|
|
|
port = to_hisi_sas_port(sas_port);
|
|
if (port && !port->port_attached) {
|
|
@@ -2207,11 +2208,8 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
|
|
abort_flag, tag, dq);
|
|
case HISI_SAS_INT_ABT_DEV:
|
|
for (i = 0; i < hisi_hba->nvecs; i++) {
|
|
- const struct cpumask *mask = NULL;
|
|
-
|
|
- if (hisi_hba->hw->get_managed_irq_aff)
|
|
- mask = hisi_hba->hw->get_managed_irq_aff(
|
|
- hisi_hba, i);
|
|
+ struct hisi_sas_cq *cq = &hisi_hba->cq[i];
|
|
+ const struct cpumask *mask = cq->pci_irq_mask;
|
|
/*
|
|
* The kernel will not permit unmanaged (MSI are
|
|
* managed) IRQ affinity to offline CPUs, so
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
index cfa9756fb995..4635c3b161db 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
@@ -556,6 +556,11 @@ module_param(user_ctl_irq, bool, 0444);
|
|
MODULE_PARM_DESC(user_ctl_irq, "Enable user control irq affinity:\n"
|
|
"default is auto-control irq affinity");
|
|
|
|
+static bool auto_affine_msi_experimental;
|
|
+module_param(auto_affine_msi_experimental, bool, 0444);
|
|
+MODULE_PARM_DESC(auto_affine_msi_experimental, "Enable auto-affinity of MSI IRQs as experimental:\n"
|
|
+ "default is off");
|
|
+
|
|
static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
|
|
{
|
|
void __iomem *regs = hisi_hba->regs + off;
|
|
@@ -2677,33 +2682,66 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
+static void setup_reply_map_v3_hw(struct hisi_hba *hisi_hba, int nvecs)
|
|
+{
|
|
+ const struct cpumask *mask;
|
|
+ int queue, cpu;
|
|
+
|
|
+ for (queue = 0; queue < nvecs; queue++) {
|
|
+ struct hisi_sas_cq *cq = &hisi_hba->cq[queue];
|
|
+
|
|
+ mask = pci_irq_get_affinity(hisi_hba->pci_dev, queue +
|
|
+ HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW);
|
|
+ if (!mask)
|
|
+ goto fallback;
|
|
+ cq->pci_irq_mask = mask;
|
|
+ for_each_cpu(cpu, mask)
|
|
+ hisi_hba->reply_map[cpu] = queue;
|
|
+ }
|
|
+ return;
|
|
+
|
|
+fallback:
|
|
+ for_each_possible_cpu(cpu)
|
|
+ hisi_hba->reply_map[cpu] = cpu % hisi_hba->queue_count;
|
|
+ /* Don't clean all CQ masks */
|
|
+}
|
|
+
|
|
static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
{
|
|
struct device *dev = hisi_hba->dev;
|
|
struct pci_dev *pdev = hisi_hba->pci_dev;
|
|
int vectors, rc;
|
|
int i, k;
|
|
- int max_msi = HISI_SAS_MSI_COUNT_V3_HW;
|
|
int max_dq_num, online_numa_num;
|
|
- struct irq_affinity desc = {
|
|
- .pre_vectors = HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW,
|
|
- };
|
|
+ int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;
|
|
|
|
- if (user_ctl_irq) {
|
|
- vectors = pci_alloc_irq_vectors(hisi_hba->pci_dev, 1,
|
|
- max_msi, PCI_IRQ_MSI);
|
|
- } else {
|
|
- vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
|
|
- HISI_SAS_MIN_VECTORS_V3_HW,
|
|
- max_msi,
|
|
- PCI_IRQ_MSI |
|
|
- PCI_IRQ_AFFINITY,
|
|
- &desc);
|
|
- }
|
|
+ if (auto_affine_msi_experimental) {
|
|
+ struct irq_affinity desc = {
|
|
+ .pre_vectors = HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW,
|
|
+ };
|
|
|
|
- if (vectors < HISI_SAS_MIN_VECTORS_V3_HW) {
|
|
- dev_err(dev, "allocate msi (%d) not enough\n", vectors);
|
|
- return -ENOENT;
|
|
+ min_msi = HISI_SAS_MIN_VECTORS_V3_HW;
|
|
+
|
|
+ hisi_hba->reply_map = devm_kcalloc(dev, nr_cpu_ids,
|
|
+ sizeof(unsigned int),
|
|
+ GFP_KERNEL);
|
|
+ if (!hisi_hba->reply_map)
|
|
+ return -ENOMEM;
|
|
+ vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
|
|
+ min_msi, max_msi,
|
|
+ PCI_IRQ_MSI |
|
|
+ PCI_IRQ_AFFINITY,
|
|
+ &desc);
|
|
+ if (vectors < 0)
|
|
+ return -ENOENT;
|
|
+ setup_reply_map_v3_hw(hisi_hba,
|
|
+ vectors - HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW);
|
|
+ } else {
|
|
+ min_msi = max_msi;
|
|
+ vectors = pci_alloc_irq_vectors(hisi_hba->pci_dev, min_msi,
|
|
+ max_msi, PCI_IRQ_MSI);
|
|
+ if (vectors < 0)
|
|
+ return vectors;
|
|
}
|
|
|
|
hisi_hba->nvecs = vectors - HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW;
|
|
--
|
|
2.27.0
|
|
|