Skip to content

Commit 8a8449c

Browse files
Karan Tilak Kumarmartinkpetersen
authored andcommitted
scsi: fnic: Modify ISRs to support multiqueue (MQ)
Modify interrupt service routines for INTx, MSI, and MSI-x to support multiqueue. Modify parameter list of fnic_wq_copy_cmpl_handler to take cq_index. Modify fnic_cleanup function to use the new function call of fnic_wq_copy_cmpl_handler. Refactor code to set interrupt mode to MSI-x to a new function. Add a new stat for intx_dummy. Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/ Reviewed-by: Sesidhar Baddela <[email protected]> Reviewed-by: Arulprabhu Ponnusamy <[email protected]> Signed-off-by: Karan Tilak Kumar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 554a148 commit 8a8449c

File tree

5 files changed

+144
-74
lines changed

5 files changed

+144
-74
lines changed

drivers/scsi/fnic/fnic.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,11 @@ do { \
160160
FNIC_CHECK_LOGGING(FNIC_SCSI_LOGGING, \
161161
shost_printk(kern_level, host, fmt, ##args);)
162162

163-
#define FNIC_ISR_DBG(kern_level, host, fmt, args...) \
163+
#define FNIC_ISR_DBG(kern_level, host, fnic_num, fmt, args...) \
164164
FNIC_CHECK_LOGGING(FNIC_ISR_LOGGING, \
165-
shost_printk(kern_level, host, fmt, ##args);)
165+
shost_printk(kern_level, host, \
166+
"fnic<%d>: %s: %d: " fmt, fnic_num,\
167+
__func__, __LINE__, ##args);)
166168

167169
#define FNIC_MAIN_NOTE(kern_level, host, fmt, args...) \
168170
shost_printk(kern_level, host, fmt, ##args)
@@ -349,6 +351,7 @@ extern const struct attribute_group *fnic_host_groups[];
349351

350352
void fnic_clear_intr_mode(struct fnic *fnic);
351353
int fnic_set_intr_mode(struct fnic *fnic);
354+
int fnic_set_intr_mode_msix(struct fnic *fnic);
352355
void fnic_free_intr(struct fnic *fnic);
353356
int fnic_request_intr(struct fnic *fnic);
354357

@@ -375,7 +378,7 @@ void fnic_scsi_cleanup(struct fc_lport *);
375378
void fnic_scsi_abort_io(struct fc_lport *);
376379
void fnic_empty_scsi_cleanup(struct fc_lport *);
377380
void fnic_exch_mgr_reset(struct fc_lport *, u32, u32);
378-
int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int);
381+
int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do, unsigned int cq_index);
379382
int fnic_wq_cmpl_handler(struct fnic *fnic, int);
380383
int fnic_flogi_reg_handler(struct fnic *fnic, u32);
381384
void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,

drivers/scsi/fnic/fnic_isr.c

Lines changed: 120 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,13 @@ static irqreturn_t fnic_isr_legacy(int irq, void *data)
3838
fnic_log_q_error(fnic);
3939
}
4040

41+
if (pba & (1 << FNIC_INTX_DUMMY)) {
42+
atomic64_inc(&fnic->fnic_stats.misc_stats.intx_dummy);
43+
vnic_intr_return_all_credits(&fnic->intr[FNIC_INTX_DUMMY]);
44+
}
45+
4146
if (pba & (1 << FNIC_INTX_WQ_RQ_COPYWQ)) {
42-
work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions);
47+
work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions, FNIC_MQ_CQ_INDEX);
4348
work_done += fnic_wq_cmpl_handler(fnic, -1);
4449
work_done += fnic_rq_cmpl_handler(fnic, -1);
4550

@@ -60,7 +65,7 @@ static irqreturn_t fnic_isr_msi(int irq, void *data)
6065
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
6166
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
6267

63-
work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions);
68+
work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions, FNIC_MQ_CQ_INDEX);
6469
work_done += fnic_wq_cmpl_handler(fnic, -1);
6570
work_done += fnic_rq_cmpl_handler(fnic, -1);
6671

@@ -109,12 +114,22 @@ static irqreturn_t fnic_isr_msix_wq_copy(int irq, void *data)
109114
{
110115
struct fnic *fnic = data;
111116
unsigned long wq_copy_work_done = 0;
117+
int i;
112118

113119
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
114120
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
115121

116-
wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, io_completions);
117-
vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ_COPY],
122+
i = irq - fnic->msix[0].irq_num;
123+
if (i >= fnic->wq_copy_count + fnic->copy_wq_base ||
124+
i < 0 || fnic->msix[i].irq_num != irq) {
125+
for (i = fnic->copy_wq_base; i < fnic->wq_copy_count + fnic->copy_wq_base ; i++) {
126+
if (fnic->msix[i].irq_num == irq)
127+
break;
128+
}
129+
}
130+
131+
wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, io_completions, i);
132+
vnic_intr_return_credits(&fnic->intr[i],
118133
wq_copy_work_done,
119134
1 /* unmask intr */,
120135
1 /* reset intr timer */);
@@ -128,7 +143,7 @@ static irqreturn_t fnic_isr_msix_err_notify(int irq, void *data)
128143
fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
129144
atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
130145

131-
vnic_intr_return_all_credits(&fnic->intr[FNIC_MSIX_ERR_NOTIFY]);
146+
vnic_intr_return_all_credits(&fnic->intr[fnic->err_intr_offset]);
132147
fnic_log_q_error(fnic);
133148
fnic_handle_link_event(fnic);
134149

@@ -186,26 +201,30 @@ int fnic_request_intr(struct fnic *fnic)
186201
fnic->msix[FNIC_MSIX_WQ].isr = fnic_isr_msix_wq;
187202
fnic->msix[FNIC_MSIX_WQ].devid = fnic;
188203

189-
sprintf(fnic->msix[FNIC_MSIX_WQ_COPY].devname,
190-
"%.11s-scsi-wq", fnic->name);
191-
fnic->msix[FNIC_MSIX_WQ_COPY].isr = fnic_isr_msix_wq_copy;
192-
fnic->msix[FNIC_MSIX_WQ_COPY].devid = fnic;
204+
for (i = fnic->copy_wq_base; i < fnic->wq_copy_count + fnic->copy_wq_base; i++) {
205+
sprintf(fnic->msix[i].devname,
206+
"%.11s-scsi-wq-%d", fnic->name, i-FNIC_MSIX_WQ_COPY);
207+
fnic->msix[i].isr = fnic_isr_msix_wq_copy;
208+
fnic->msix[i].devid = fnic;
209+
}
193210

194-
sprintf(fnic->msix[FNIC_MSIX_ERR_NOTIFY].devname,
211+
sprintf(fnic->msix[fnic->err_intr_offset].devname,
195212
"%.11s-err-notify", fnic->name);
196-
fnic->msix[FNIC_MSIX_ERR_NOTIFY].isr =
213+
fnic->msix[fnic->err_intr_offset].isr =
197214
fnic_isr_msix_err_notify;
198-
fnic->msix[FNIC_MSIX_ERR_NOTIFY].devid = fnic;
215+
fnic->msix[fnic->err_intr_offset].devid = fnic;
199216

200-
for (i = 0; i < ARRAY_SIZE(fnic->msix); i++) {
201-
err = request_irq(pci_irq_vector(fnic->pdev, i),
202-
fnic->msix[i].isr, 0,
203-
fnic->msix[i].devname,
204-
fnic->msix[i].devid);
217+
for (i = 0; i < fnic->intr_count; i++) {
218+
fnic->msix[i].irq_num = pci_irq_vector(fnic->pdev, i);
219+
220+
err = request_irq(fnic->msix[i].irq_num,
221+
fnic->msix[i].isr, 0,
222+
fnic->msix[i].devname,
223+
fnic->msix[i].devid);
205224
if (err) {
206-
shost_printk(KERN_ERR, fnic->lport->host,
207-
"MSIX: request_irq"
208-
" failed %d\n", err);
225+
FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
226+
"request_irq failed with error: %d\n",
227+
err);
209228
fnic_free_intr(fnic);
210229
break;
211230
}
@@ -220,44 +239,99 @@ int fnic_request_intr(struct fnic *fnic)
220239
return err;
221240
}
222241

223-
int fnic_set_intr_mode(struct fnic *fnic)
242+
int fnic_set_intr_mode_msix(struct fnic *fnic)
224243
{
225244
unsigned int n = ARRAY_SIZE(fnic->rq);
226245
unsigned int m = ARRAY_SIZE(fnic->wq);
227246
unsigned int o = ARRAY_SIZE(fnic->hw_copy_wq);
247+
unsigned int min_irqs = n + m + 1 + 1; /*rq, raw wq, wq, err*/
228248

229249
/*
230-
* Set interrupt mode (INTx, MSI, MSI-X) depending
231-
* system capabilities.
232-
*
233-
* Try MSI-X first
234-
*
235250
* We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
236251
* (last INTR is used for WQ/RQ errors and notification area)
237252
*/
238-
if (fnic->rq_count >= n &&
239-
fnic->raw_wq_count >= m &&
240-
fnic->wq_copy_count >= o &&
241-
fnic->cq_count >= n + m + o) {
242-
int vecs = n + m + o + 1;
243-
244-
if (pci_alloc_irq_vectors(fnic->pdev, vecs, vecs,
245-
PCI_IRQ_MSIX) == vecs) {
253+
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
254+
"rq-array size: %d wq-array size: %d copy-wq array size: %d\n",
255+
n, m, o);
256+
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
257+
"rq_count: %d raw_wq_count: %d wq_copy_count: %d cq_count: %d\n",
258+
fnic->rq_count, fnic->raw_wq_count,
259+
fnic->wq_copy_count, fnic->cq_count);
260+
261+
if (fnic->rq_count <= n && fnic->raw_wq_count <= m &&
262+
fnic->wq_copy_count <= o) {
263+
int vec_count = 0;
264+
int vecs = fnic->rq_count + fnic->raw_wq_count + fnic->wq_copy_count + 1;
265+
266+
vec_count = pci_alloc_irq_vectors(fnic->pdev, min_irqs, vecs,
267+
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY);
268+
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
269+
"allocated %d MSI-X vectors\n",
270+
vec_count);
271+
272+
if (vec_count > 0) {
273+
if (vec_count < vecs) {
274+
FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
275+
"interrupts number mismatch: vec_count: %d vecs: %d\n",
276+
vec_count, vecs);
277+
if (vec_count < min_irqs) {
278+
FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
279+
"no interrupts for copy wq\n");
280+
return 1;
281+
}
282+
}
283+
246284
fnic->rq_count = n;
247285
fnic->raw_wq_count = m;
248-
fnic->wq_copy_count = o;
249-
fnic->wq_count = m + o;
250-
fnic->cq_count = n + m + o;
251-
fnic->intr_count = vecs;
252-
fnic->err_intr_offset = FNIC_MSIX_ERR_NOTIFY;
253-
254-
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
255-
"Using MSI-X Interrupts\n");
256-
vnic_dev_set_intr_mode(fnic->vdev,
257-
VNIC_DEV_INTR_MODE_MSIX);
286+
fnic->copy_wq_base = fnic->rq_count + fnic->raw_wq_count;
287+
fnic->wq_copy_count = vec_count - n - m - 1;
288+
fnic->wq_count = fnic->raw_wq_count + fnic->wq_copy_count;
289+
if (fnic->cq_count != vec_count - 1) {
290+
FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
291+
"CQ count: %d does not match MSI-X vector count: %d\n",
292+
fnic->cq_count, vec_count);
293+
fnic->cq_count = vec_count - 1;
294+
}
295+
fnic->intr_count = vec_count;
296+
fnic->err_intr_offset = fnic->rq_count + fnic->wq_count;
297+
298+
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
299+
"rq_count: %d raw_wq_count: %d copy_wq_base: %d\n",
300+
fnic->rq_count,
301+
fnic->raw_wq_count, fnic->copy_wq_base);
302+
303+
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
304+
"wq_copy_count: %d wq_count: %d cq_count: %d\n",
305+
fnic->wq_copy_count,
306+
fnic->wq_count, fnic->cq_count);
307+
308+
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
309+
"intr_count: %d err_intr_offset: %u",
310+
fnic->intr_count,
311+
fnic->err_intr_offset);
312+
313+
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSIX);
314+
FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
315+
"fnic using MSI-X\n");
258316
return 0;
259317
}
260318
}
319+
return 1;
320+
}
321+
322+
int fnic_set_intr_mode(struct fnic *fnic)
323+
{
324+
int ret_status = 0;
325+
326+
/*
327+
* Set interrupt mode (INTx, MSI, MSI-X) depending
328+
* system capabilities.
329+
*
330+
* Try MSI-X first
331+
*/
332+
ret_status = fnic_set_intr_mode_msix(fnic);
333+
if (ret_status == 0)
334+
return ret_status;
261335

262336
/*
263337
* Next try MSI
@@ -277,7 +351,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
277351
fnic->intr_count = 1;
278352
fnic->err_intr_offset = 0;
279353

280-
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
354+
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
281355
"Using MSI Interrupts\n");
282356
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSI);
283357

@@ -303,7 +377,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
303377
fnic->cq_count = 3;
304378
fnic->intr_count = 3;
305379

306-
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
380+
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
307381
"Using Legacy Interrupts\n");
308382
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_INTX);
309383

drivers/scsi/fnic/fnic_main.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ static int fnic_cleanup(struct fnic *fnic)
476476
{
477477
unsigned int i;
478478
int err;
479+
int raw_wq_rq_counts;
479480

480481
vnic_dev_disable(fnic->vdev);
481482
for (i = 0; i < fnic->intr_count; i++)
@@ -495,10 +496,11 @@ static int fnic_cleanup(struct fnic *fnic)
495496
err = vnic_wq_copy_disable(&fnic->hw_copy_wq[i]);
496497
if (err)
497498
return err;
499+
raw_wq_rq_counts = fnic->raw_wq_count + fnic->rq_count;
500+
fnic_wq_copy_cmpl_handler(fnic, -1, i + raw_wq_rq_counts);
498501
}
499502

500503
/* Clean up completed IOs and FCS frames */
501-
fnic_wq_copy_cmpl_handler(fnic, io_completions);
502504
fnic_wq_cmpl_handler(fnic, -1);
503505
fnic_rq_cmpl_handler(fnic, -1);
504506

drivers/scsi/fnic/fnic_scsi.c

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,39 +1319,29 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
13191319
* fnic_wq_copy_cmpl_handler
13201320
* Routine to process wq copy
13211321
*/
1322-
int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do)
1322+
int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do, unsigned int cq_index)
13231323
{
1324-
unsigned int wq_work_done = 0;
1325-
unsigned int i, cq_index;
13261324
unsigned int cur_work_done;
13271325
struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
13281326
u64 start_jiffies = 0;
13291327
u64 end_jiffies = 0;
13301328
u64 delta_jiffies = 0;
13311329
u64 delta_ms = 0;
13321330

1333-
for (i = 0; i < fnic->wq_copy_count; i++) {
1334-
cq_index = i + fnic->raw_wq_count + fnic->rq_count;
1335-
1336-
start_jiffies = jiffies;
1337-
cur_work_done = vnic_cq_copy_service(&fnic->cq[cq_index],
1338-
fnic_fcpio_cmpl_handler,
1339-
copy_work_to_do);
1340-
end_jiffies = jiffies;
1341-
1342-
wq_work_done += cur_work_done;
1343-
delta_jiffies = end_jiffies - start_jiffies;
1344-
if (delta_jiffies >
1345-
(u64) atomic64_read(&misc_stats->max_isr_jiffies)) {
1346-
atomic64_set(&misc_stats->max_isr_jiffies,
1347-
delta_jiffies);
1348-
delta_ms = jiffies_to_msecs(delta_jiffies);
1349-
atomic64_set(&misc_stats->max_isr_time_ms, delta_ms);
1350-
atomic64_set(&misc_stats->corr_work_done,
1351-
cur_work_done);
1352-
}
1331+
start_jiffies = jiffies;
1332+
cur_work_done = vnic_cq_copy_service(&fnic->cq[cq_index],
1333+
fnic_fcpio_cmpl_handler,
1334+
copy_work_to_do);
1335+
end_jiffies = jiffies;
1336+
delta_jiffies = end_jiffies - start_jiffies;
1337+
if (delta_jiffies > (u64) atomic64_read(&misc_stats->max_isr_jiffies)) {
1338+
atomic64_set(&misc_stats->max_isr_jiffies, delta_jiffies);
1339+
delta_ms = jiffies_to_msecs(delta_jiffies);
1340+
atomic64_set(&misc_stats->max_isr_time_ms, delta_ms);
1341+
atomic64_set(&misc_stats->corr_work_done, cur_work_done);
13531342
}
1354-
return wq_work_done;
1343+
1344+
return cur_work_done;
13551345
}
13561346

13571347
static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)

drivers/scsi/fnic/fnic_stats.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ struct misc_stats {
103103
atomic64_t rport_not_ready;
104104
atomic64_t frame_errors;
105105
atomic64_t current_port_speed;
106+
atomic64_t intx_dummy;
106107
};
107108

108109
struct fnic_stats {

0 commit comments

Comments
 (0)