Skip to content

Commit d458d4b

Browse files
brettcreeleykuba-moo
authored andcommitted
ionic: Keep interrupt affinity up to date
Currently the driver either sets the initial interrupt affinity for its adminq and tx/rx queues on probe or resets it on various down/up/reconfigure flows. If any user and/or user process (i.e. irqbalance) changes IRQ affinity for any of the driver's interrupts that will be reset to driver defaults whenever any down/up/reconfigure operation happens. This is incorrect and is fixed by making 2 changes: 1. Allocate an array of cpumasks that's only allocated on probe and destroyed on remove. 2. Update the cpumask(s) for interrupts that are in use by registering for affinity notifiers. Signed-off-by: Brett Creeley <brett.creeley@amd.com> Signed-off-by: Shannon Nelson <shannon.nelson@amd.com> Link: https://lore.kernel.org/r/20240619003257.6138-3-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 4aaa49a commit d458d4b

File tree

3 files changed

+81
-9
lines changed

3 files changed

+81
-9
lines changed

drivers/net/ethernet/pensando/ionic/ionic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ struct ionic {
5454
unsigned int nrxqs_per_lif;
5555
unsigned int nintrs;
5656
DECLARE_BITMAP(intrs, IONIC_INTR_CTRL_REGS_MAX);
57+
cpumask_var_t *affinity_masks;
5758
struct work_struct nb_work;
5859
struct notifier_block nb;
5960
struct rw_semaphore vf_op_lock; /* lock for VF operations */

drivers/net/ethernet/pensando/ionic/ionic_dev.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,9 @@ struct ionic_intr_info {
280280
u64 rearm_count;
281281
unsigned int index;
282282
unsigned int vector;
283-
unsigned int cpu;
284283
u32 dim_coal_hw;
285-
cpumask_t affinity_mask;
284+
cpumask_var_t *affinity_mask;
285+
struct irq_affinity_notify aff_notify;
286286
};
287287

288288
struct ionic_cq {

drivers/net/ethernet/pensando/ionic/ionic_lif.c

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,18 @@ static void ionic_intr_free(struct ionic *ionic, int index)
265265
clear_bit(index, ionic->intrs);
266266
}
267267

268+
static void ionic_irq_aff_notify(struct irq_affinity_notify *notify,
269+
const cpumask_t *mask)
270+
{
271+
struct ionic_intr_info *intr = container_of(notify, struct ionic_intr_info, aff_notify);
272+
273+
cpumask_copy(*intr->affinity_mask, mask);
274+
}
275+
276+
static void ionic_irq_aff_release(struct kref __always_unused *ref)
277+
{
278+
}
279+
268280
static int ionic_qcq_enable(struct ionic_qcq *qcq)
269281
{
270282
struct ionic_queue *q = &qcq->q;
@@ -299,8 +311,10 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq)
299311

300312
if (qcq->flags & IONIC_QCQ_F_INTR) {
301313
napi_enable(&qcq->napi);
314+
irq_set_affinity_notifier(qcq->intr.vector,
315+
&qcq->intr.aff_notify);
302316
irq_set_affinity_hint(qcq->intr.vector,
303-
&qcq->intr.affinity_mask);
317+
*qcq->intr.affinity_mask);
304318
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
305319
IONIC_INTR_MASK_CLEAR);
306320
}
@@ -334,6 +348,7 @@ static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int f
334348
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
335349
IONIC_INTR_MASK_SET);
336350
synchronize_irq(qcq->intr.vector);
351+
irq_set_affinity_notifier(qcq->intr.vector, NULL);
337352
irq_set_affinity_hint(qcq->intr.vector, NULL);
338353
napi_disable(&qcq->napi);
339354
}
@@ -474,6 +489,7 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
474489

475490
static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qcq)
476491
{
492+
cpumask_var_t *affinity_mask;
477493
int err;
478494

479495
if (!(qcq->flags & IONIC_QCQ_F_INTR)) {
@@ -505,10 +521,19 @@ static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qc
505521
}
506522

507523
/* try to get the irq on the local numa node first */
508-
qcq->intr.cpu = cpumask_local_spread(qcq->intr.index,
509-
dev_to_node(lif->ionic->dev));
510-
if (qcq->intr.cpu != -1)
511-
cpumask_set_cpu(qcq->intr.cpu, &qcq->intr.affinity_mask);
524+
affinity_mask = &lif->ionic->affinity_masks[qcq->intr.index];
525+
if (cpumask_empty(*affinity_mask)) {
526+
unsigned int cpu;
527+
528+
cpu = cpumask_local_spread(qcq->intr.index,
529+
dev_to_node(lif->ionic->dev));
530+
if (cpu != -1)
531+
cpumask_set_cpu(cpu, *affinity_mask);
532+
}
533+
534+
qcq->intr.affinity_mask = affinity_mask;
535+
qcq->intr.aff_notify.notify = ionic_irq_aff_notify;
536+
qcq->intr.aff_notify.release = ionic_irq_aff_release;
512537

513538
netdev_dbg(lif->netdev, "%s: Interrupt index %d\n", qcq->q.name, qcq->intr.index);
514539
return 0;
@@ -3120,6 +3145,44 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
31203145
return err;
31213146
}
31223147

3148+
static int ionic_affinity_masks_alloc(struct ionic *ionic)
3149+
{
3150+
cpumask_var_t *affinity_masks;
3151+
int nintrs = ionic->nintrs;
3152+
int i;
3153+
3154+
affinity_masks = kcalloc(nintrs, sizeof(cpumask_var_t), GFP_KERNEL);
3155+
if (!affinity_masks)
3156+
return -ENOMEM;
3157+
3158+
for (i = 0; i < nintrs; i++) {
3159+
if (!zalloc_cpumask_var_node(&affinity_masks[i], GFP_KERNEL,
3160+
dev_to_node(ionic->dev)))
3161+
goto err_out;
3162+
}
3163+
3164+
ionic->affinity_masks = affinity_masks;
3165+
3166+
return 0;
3167+
3168+
err_out:
3169+
for (--i; i >= 0; i--)
3170+
free_cpumask_var(affinity_masks[i]);
3171+
kfree(affinity_masks);
3172+
3173+
return -ENOMEM;
3174+
}
3175+
3176+
static void ionic_affinity_masks_free(struct ionic *ionic)
3177+
{
3178+
int i;
3179+
3180+
for (i = 0; i < ionic->nintrs; i++)
3181+
free_cpumask_var(ionic->affinity_masks[i]);
3182+
kfree(ionic->affinity_masks);
3183+
ionic->affinity_masks = NULL;
3184+
}
3185+
31233186
int ionic_lif_alloc(struct ionic *ionic)
31243187
{
31253188
struct device *dev = ionic->dev;
@@ -3211,11 +3274,15 @@ int ionic_lif_alloc(struct ionic *ionic)
32113274

32123275
ionic_debugfs_add_lif(lif);
32133276

3277+
err = ionic_affinity_masks_alloc(ionic);
3278+
if (err)
3279+
goto err_out_free_lif_info;
3280+
32143281
/* allocate control queues and txrx queue arrays */
32153282
ionic_lif_queue_identify(lif);
32163283
err = ionic_qcqs_alloc(lif);
32173284
if (err)
3218-
goto err_out_free_lif_info;
3285+
goto err_out_free_affinity_masks;
32193286

32203287
/* allocate rss indirection table */
32213288
tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
@@ -3237,6 +3304,8 @@ int ionic_lif_alloc(struct ionic *ionic)
32373304

32383305
err_out_free_qcqs:
32393306
ionic_qcqs_free(lif);
3307+
err_out_free_affinity_masks:
3308+
ionic_affinity_masks_free(lif->ionic);
32403309
err_out_free_lif_info:
32413310
dma_free_coherent(dev, lif->info_sz, lif->info, lif->info_pa);
32423311
lif->info = NULL;
@@ -3410,6 +3479,8 @@ void ionic_lif_free(struct ionic_lif *lif)
34103479
if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state))
34113480
ionic_lif_reset(lif);
34123481

3482+
ionic_affinity_masks_free(lif->ionic);
3483+
34133484
/* free lif info */
34143485
kfree(lif->identity);
34153486
dma_free_coherent(dev, lif->info_sz, lif->info, lif->info_pa);
@@ -3487,7 +3558,7 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif)
34873558

34883559
if (qcq->flags & IONIC_QCQ_F_INTR) {
34893560
irq_set_affinity_hint(qcq->intr.vector,
3490-
&qcq->intr.affinity_mask);
3561+
*qcq->intr.affinity_mask);
34913562
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
34923563
IONIC_INTR_MASK_CLEAR);
34933564
}

0 commit comments

Comments
 (0)