blob: 9238a0ab73a8293514962dd40a3db7d48a817bb0 [file] [log] [blame]
Joel Stanleya9726d12019-10-15 13:24:18 +10301From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: James Smart <jsmart2021@gmail.com>
3Date: Wed, 14 Aug 2019 16:56:43 -0700
Joel Stanleyd7fd58d2019-10-23 12:30:37 +11004Subject: [PATCH 6/8] scsi: lpfc: Fix oops when fewer hdwqs than cpus
Joel Stanleya9726d12019-10-15 13:24:18 +10305
6When tearing down the adapter for a reset, online/offline, or driver
7unload, the queue free routine would hit a GPF oops. This only occurs on
8conditions where the number of hardware queues created is fewer than the
9number of cpus in the system. In this condition cpus share a hardware
10queue. And of course, it's the 2nd cpu that shares a hardware that
11attempted to free it a second time and hit the oops.
12
13Fix by reworking the cpu to hardware queue mapping such that:
14Assignment of hardware queues to cpus occur in two passes:
15first pass: is first time assignment of a hardware queue to a cpu.
16 This will set the LPFC_CPU_FIRST_IRQ flag for the cpu.
17second pass: for cpus that did not get a hardware queue they will
18 be assigned one from a primary cpu (one set in first pass).
19
20Deletion of hardware queues is driven by cpu itteration, and queues
21will only be deleted if the LPFC_CPU_FIRST_IRQ flag is set.
22
23Also contains a few small cleanup fixes and a little better logging.
24
25Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
26Signed-off-by: James Smart <jsmart2021@gmail.com>
27Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
28(cherry picked from commit 3ad348d94452d6ab3aa0316105fb9f34f8ed3140)
29Signed-off-by: Joel Stanley <joel@jms.id.au>
30---
31 drivers/scsi/lpfc/lpfc_init.c | 144 +++++++++++++++++++++-------------
32 1 file changed, 89 insertions(+), 55 deletions(-)
33
34diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
35index 1ac98becb5ba..a5b515fdda2e 100644
36--- a/drivers/scsi/lpfc/lpfc_init.c
37+++ b/drivers/scsi/lpfc/lpfc_init.c
38@@ -8864,7 +8864,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
39 }
40 qdesc->qe_valid = 1;
41 qdesc->hdwq = cpup->hdwq;
42- qdesc->chann = cpu; /* First CPU this EQ is affinitised to */
43+ qdesc->chann = cpu; /* First CPU this EQ is affinitized to */
44 qdesc->last_cpu = qdesc->chann;
45
46 /* Save the allocated EQ in the Hardware Queue */
47@@ -10711,7 +10711,7 @@ lpfc_find_hyper(struct lpfc_hba *phba, int cpu,
48 static void
49 lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors)
50 {
51- int i, cpu, idx, new_cpu, start_cpu, first_cpu;
52+ int i, cpu, idx, next_idx, new_cpu, start_cpu, first_cpu;
53 int max_phys_id, min_phys_id;
54 int max_core_id, min_core_id;
55 struct lpfc_vector_map_info *cpup;
56@@ -10753,8 +10753,8 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors)
57 #endif
58
59 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
60- "3328 CPU physid %d coreid %d\n",
61- cpup->phys_id, cpup->core_id);
62+ "3328 CPU %d physid %d coreid %d flag x%x\n",
63+ cpu, cpup->phys_id, cpup->core_id, cpup->flag);
64
65 if (cpup->phys_id > max_phys_id)
66 max_phys_id = cpup->phys_id;
67@@ -10812,17 +10812,17 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors)
68 cpup->eq = idx;
69 cpup->irq = pci_irq_vector(phba->pcidev, idx);
70
71- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
72- "3336 Set Affinity: CPU %d "
73- "irq %d eq %d\n",
74- cpu, cpup->irq, cpup->eq);
75-
76 /* If this is the first CPU thats assigned to this
77 * vector, set LPFC_CPU_FIRST_IRQ.
78 */
79 if (!i)
80 cpup->flag |= LPFC_CPU_FIRST_IRQ;
81 i++;
82+
83+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
84+ "3336 Set Affinity: CPU %d "
85+ "irq %d eq %d flag x%x\n",
86+ cpu, cpup->irq, cpup->eq, cpup->flag);
87 }
88 }
89
90@@ -10936,69 +10936,103 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors)
91 }
92 }
93
94+ /* Assign hdwq indices that are unique across all cpus in the map
95+ * that are also FIRST_CPUs.
96+ */
97+ idx = 0;
98+ for_each_present_cpu(cpu) {
99+ cpup = &phba->sli4_hba.cpu_map[cpu];
100+
101+ /* Only FIRST IRQs get a hdwq index assignment. */
102+ if (!(cpup->flag & LPFC_CPU_FIRST_IRQ))
103+ continue;
104+
105+ /* 1 to 1, the first LPFC_CPU_FIRST_IRQ cpus to a unique hdwq */
106+ cpup->hdwq = idx;
107+ idx++;
108+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
109+ "3333 Set Affinity: CPU %d (phys %d core %d): "
110+ "hdwq %d eq %d irq %d flg x%x\n",
111+ cpu, cpup->phys_id, cpup->core_id,
112+ cpup->hdwq, cpup->eq, cpup->irq, cpup->flag);
113+ }
114 /* Finally we need to associate a hdwq with each cpu_map entry
115 * This will be 1 to 1 - hdwq to cpu, unless there are less
116 * hardware queues then CPUs. For that case we will just round-robin
117 * the available hardware queues as they get assigned to CPUs.
118+ * The next_idx is the idx from the FIRST_CPU loop above to account
119+ * for irq_chann < hdwq. The idx is used for round-robin assignments
120+ * and needs to start at 0.
121 */
122- idx = 0;
123+ next_idx = idx;
124 start_cpu = 0;
125+ idx = 0;
126 for_each_present_cpu(cpu) {
127 cpup = &phba->sli4_hba.cpu_map[cpu];
128- if (idx >= phba->cfg_hdw_queue) {
129- /* We need to reuse a Hardware Queue for another CPU,
130- * so be smart about it and pick one that has its
131- * IRQ/EQ mapped to the same phys_id (CPU package).
132- * and core_id.
133- */
134- new_cpu = start_cpu;
135- for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
136- new_cpup = &phba->sli4_hba.cpu_map[new_cpu];
137- if ((new_cpup->hdwq != LPFC_VECTOR_MAP_EMPTY) &&
138- (new_cpup->phys_id == cpup->phys_id) &&
139- (new_cpup->core_id == cpup->core_id))
140- goto found_hdwq;
141- new_cpu = cpumask_next(
142- new_cpu, cpu_present_mask);
143- if (new_cpu == nr_cpumask_bits)
144- new_cpu = first_cpu;
145- }
146
147- /* If we can't match both phys_id and core_id,
148- * settle for just a phys_id match.
149- */
150- new_cpu = start_cpu;
151- for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
152- new_cpup = &phba->sli4_hba.cpu_map[new_cpu];
153- if ((new_cpup->hdwq != LPFC_VECTOR_MAP_EMPTY) &&
154- (new_cpup->phys_id == cpup->phys_id))
155- goto found_hdwq;
156- new_cpu = cpumask_next(
157- new_cpu, cpu_present_mask);
158- if (new_cpu == nr_cpumask_bits)
159- new_cpu = first_cpu;
160+ /* FIRST cpus are already mapped. */
161+ if (cpup->flag & LPFC_CPU_FIRST_IRQ)
162+ continue;
163+
164+ /* If the cfg_irq_chann < cfg_hdw_queue, set the hdwq
165+ * of the unassigned cpus to the next idx so that all
166+ * hdw queues are fully utilized.
167+ */
168+ if (next_idx < phba->cfg_hdw_queue) {
169+ cpup->hdwq = next_idx;
170+ next_idx++;
171+ continue;
172+ }
173+
174+ /* Not a First CPU and all hdw_queues are used. Reuse a
175+ * Hardware Queue for another CPU, so be smart about it
176+ * and pick one that has its IRQ/EQ mapped to the same phys_id
177+ * (CPU package) and core_id.
178+ */
179+ new_cpu = start_cpu;
180+ for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
181+ new_cpup = &phba->sli4_hba.cpu_map[new_cpu];
182+ if (new_cpup->hdwq != LPFC_VECTOR_MAP_EMPTY &&
183+ new_cpup->phys_id == cpup->phys_id &&
184+ new_cpup->core_id == cpup->core_id) {
185+ goto found_hdwq;
186 }
187+ new_cpu = cpumask_next(new_cpu, cpu_present_mask);
188+ if (new_cpu == nr_cpumask_bits)
189+ new_cpu = first_cpu;
190+ }
191
192- /* Otherwise just round robin on cfg_hdw_queue */
193- cpup->hdwq = idx % phba->cfg_hdw_queue;
194- goto logit;
195-found_hdwq:
196- /* We found an available entry, copy the IRQ info */
197- start_cpu = cpumask_next(new_cpu, cpu_present_mask);
198- if (start_cpu == nr_cpumask_bits)
199- start_cpu = first_cpu;
200- cpup->hdwq = new_cpup->hdwq;
201- } else {
202- /* 1 to 1, CPU to hdwq */
203- cpup->hdwq = idx;
204+ /* If we can't match both phys_id and core_id,
205+ * settle for just a phys_id match.
206+ */
207+ new_cpu = start_cpu;
208+ for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
209+ new_cpup = &phba->sli4_hba.cpu_map[new_cpu];
210+ if (new_cpup->hdwq != LPFC_VECTOR_MAP_EMPTY &&
211+ new_cpup->phys_id == cpup->phys_id)
212+ goto found_hdwq;
213+
214+ new_cpu = cpumask_next(new_cpu, cpu_present_mask);
215+ if (new_cpu == nr_cpumask_bits)
216+ new_cpu = first_cpu;
217 }
218-logit:
219+
220+ /* Otherwise just round robin on cfg_hdw_queue */
221+ cpup->hdwq = idx % phba->cfg_hdw_queue;
222+ idx++;
223+ goto logit;
224+ found_hdwq:
225+ /* We found an available entry, copy the IRQ info */
226+ start_cpu = cpumask_next(new_cpu, cpu_present_mask);
227+ if (start_cpu == nr_cpumask_bits)
228+ start_cpu = first_cpu;
229+ cpup->hdwq = new_cpup->hdwq;
230+ logit:
231 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
232 "3335 Set Affinity: CPU %d (phys %d core %d): "
233 "hdwq %d eq %d irq %d flg x%x\n",
234 cpu, cpup->phys_id, cpup->core_id,
235 cpup->hdwq, cpup->eq, cpup->irq, cpup->flag);
236- idx++;
237 }
238
239 /* The cpu_map array will be used later during initialization