History

net/mlx5: Change interrupt handler to call chain notifier

Multiple EQs may share the same IRQ in subsequent patches. Instead of calling the IRQ handler directly, the EQ will register to an atomic chain notfier. The Linux built-in shared IRQ is not used because it forces the caller to disable the IRQ and clear affinity before free_irq() can be called. This patch is the first step in the separation of IRQ and EQ logic.

Yuval Avnery committed 7 years ago

Commit ca390791 parent 081cc2d5 files · +105 −56Browse files

Unified · Split

5 files
  1. drivers/infiniband/hw/mlx5/mlx5_ib.h +1 −0
  2. drivers/infiniband/hw/mlx5/odp.c +6 −4
  3. drivers/net/ethernet/mellanox/mlx5/core/eq.c +89 −49
  4. drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h +8 −1
  5. include/linux/mlx5/eq.h +1 −2
drivers/infiniband/hw/mlx5/mlx5_ib.h+1−0
@@ -920,6 +920,7 @@ struct mlx5_ib_lb_state { · 919 unmodified lines
920};920};
921 921
922struct mlx5_ib_pf_eq {922struct mlx5_ib_pf_eq {
923 struct notifier_block irq_nb;
923 struct mlx5_ib_dev *dev;924 struct mlx5_ib_dev *dev;
924 struct mlx5_eq *core;925 struct mlx5_eq *core;
925 struct work_struct work;926 struct work_struct work;
drivers/infiniband/hw/mlx5/odp.c+6−4
@@ -1488,9 +1488,11 @@ static void mlx5_ib_eq_pf_process(struct mlx5_ib_pf_eq *eq) · 1487 unmodified lines
1488 mlx5_eq_update_ci(eq->core, cc, 1);1488 mlx5_eq_update_ci(eq->core, cc, 1);
1489}1489}
1490 1490
1491static irqreturn_t mlx5_ib_eq_pf_int(int irq, void *eq_ptr)1491static int mlx5_ib_eq_pf_int(struct notifier_block *nb, unsigned long type,
1492 void *data)
1492{1493{
1493 struct mlx5_ib_pf_eq *eq = eq_ptr;1494 struct mlx5_ib_pf_eq *eq =
1495 container_of(nb, struct mlx5_ib_pf_eq, irq_nb);
1494 unsigned long flags;1496 unsigned long flags;
1495 1497
1496 if (spin_trylock_irqsave(&eq->lock, flags)) {1498 if (spin_trylock_irqsave(&eq->lock, flags)) {
@@ -1553,12 +1555,12 @@ mlx5_ib_create_pf_eq(struct mlx5_ib_dev *dev, struct mlx5_ib_pf_eq *eq) · 56 unmodified lines
1553 goto err_mempool;1555 goto err_mempool;
1554 }1556 }
1555 1557
1558 eq->irq_nb.notifier_call = mlx5_ib_eq_pf_int;
1556 param = (struct mlx5_eq_param) {1559 param = (struct mlx5_eq_param) {
1557 .index = MLX5_EQ_PFAULT_IDX,1560 .index = MLX5_EQ_PFAULT_IDX,
1558 .mask = 1 << MLX5_EVENT_TYPE_PAGE_FAULT,1561 .mask = 1 << MLX5_EVENT_TYPE_PAGE_FAULT,
1559 .nent = MLX5_IB_NUM_PF_EQE,1562 .nent = MLX5_IB_NUM_PF_EQE,
1560 .context = eq,1563 .nb = &eq->irq_nb,
1561 .handler = mlx5_ib_eq_pf_int
1562 };1564 };
1563 eq->core = mlx5_eq_create_generic(dev->mdev, "mlx5_ib_page_fault_eq", &param);1565 eq->core = mlx5_eq_create_generic(dev->mdev, "mlx5_ib_page_fault_eq", &param);
1564 if (IS_ERR(eq->core)) {1566 if (IS_ERR(eq->core)) {
drivers/net/ethernet/mellanox/mlx5/core/eq.c+89−49
@@ -72,16 +72,16 @@ enum { · 71 unmodified lines
72static_assert(MLX5_EQ_POLLING_BUDGET <= MLX5_NUM_SPARE_EQE);72static_assert(MLX5_EQ_POLLING_BUDGET <= MLX5_NUM_SPARE_EQE);
73 73
74struct mlx5_irq_info {74struct mlx5_irq_info {
75 struct atomic_notifier_head nh;
75 cpumask_var_t mask;76 cpumask_var_t mask;
76 char name[MLX5_MAX_IRQ_NAME];77 char name[MLX5_MAX_IRQ_NAME];
77 void *context; /* dev_id provided to request_irq */
78};78};
79 79
80struct mlx5_eq_table {80struct mlx5_eq_table {
81 struct list_head comp_eqs_list;81 struct list_head comp_eqs_list;
82 struct mlx5_eq pages_eq;82 struct mlx5_eq_async pages_eq;
83 struct mlx5_eq cmd_eq;83 struct mlx5_eq_async cmd_eq;
84 struct mlx5_eq async_eq;84 struct mlx5_eq_async async_eq;
85 85
86 struct atomic_notifier_head nh[MLX5_EVENT_TYPE_MAX];86 struct atomic_notifier_head nh[MLX5_EVENT_TYPE_MAX];
87 87
@@ -109,6 +109,31 @@ struct mlx5_eq_table { · 21 unmodified lines
109 (1ull << MLX5_EVENT_TYPE_SRQ_LAST_WQE) | \109 (1ull << MLX5_EVENT_TYPE_SRQ_LAST_WQE) | \
110 (1ull << MLX5_EVENT_TYPE_SRQ_RQ_LIMIT))110 (1ull << MLX5_EVENT_TYPE_SRQ_RQ_LIMIT))
111 111
112static struct mlx5_irq_info *mlx5_irq_get(struct mlx5_core_dev *dev, int vecidx)
113{
114 struct mlx5_eq_table *eq_table = dev->priv.eq_table;
115
116 return &eq_table->irq_info[vecidx];
117}
118
119static int mlx5_irq_attach_nb(struct mlx5_irq_info *irq,
120 struct notifier_block *nb)
121{
122 return atomic_notifier_chain_register(&irq->nh, nb);
123}
124
125static int mlx5_irq_detach_nb(struct mlx5_irq_info *irq,
126 struct notifier_block *nb)
127{
128 return atomic_notifier_chain_unregister(&irq->nh, nb);
129}
130
131static irqreturn_t mlx5_irq_int_handler(int irq, void *nh)
132{
133 atomic_notifier_call_chain(nh, 0, NULL);
134 return IRQ_HANDLED;
135}
136
112static int mlx5_cmd_destroy_eq(struct mlx5_core_dev *dev, u8 eqn)137static int mlx5_cmd_destroy_eq(struct mlx5_core_dev *dev, u8 eqn)
113{138{
114 u32 out[MLX5_ST_SZ_DW(destroy_eq_out)] = {0};139 u32 out[MLX5_ST_SZ_DW(destroy_eq_out)] = {0};
@@ -134,10 +159,13 @@ static struct mlx5_core_cq *mlx5_eq_cq_get(struct mlx5_eq *eq, u32 cqn) · 19 unmodified lines
134 return cq;159 return cq;
135}160}
136 161
137static irqreturn_t mlx5_eq_comp_int(int irq, void *eq_ptr)162static int mlx5_eq_comp_int(struct notifier_block *nb,
163 __always_unused unsigned long action,
164 __always_unused void *data)
138{165{
139 struct mlx5_eq_comp *eq_comp = eq_ptr;166 struct mlx5_eq_comp *eq_comp =
140 struct mlx5_eq *eq = eq_ptr;167 container_of(nb, struct mlx5_eq_comp, irq_nb);
168 struct mlx5_eq *eq = &eq_comp->core;
141 struct mlx5_eqe *eqe;169 struct mlx5_eqe *eqe;
142 int num_eqes = 0;170 int num_eqes = 0;
143 u32 cqn = -1;171 u32 cqn = -1;
@@ -175,7 +203,7 @@ out: · 31 unmodified lines
175 if (cqn != -1)203 if (cqn != -1)
176 tasklet_schedule(&eq_comp->tasklet_ctx.task);204 tasklet_schedule(&eq_comp->tasklet_ctx.task);
177 205
178 return IRQ_HANDLED;206 return 0;
179}207}
180 208
181/* Some architectures don't latch interrupts when they are disabled, so using209/* Some architectures don't latch interrupts when they are disabled, so using
@@ -189,16 +217,19 @@ u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq_comp *eq) · 7 unmodified lines
189 217
190 disable_irq(eq->core.irqn);218 disable_irq(eq->core.irqn);
191 count_eqe = eq->core.cons_index;219 count_eqe = eq->core.cons_index;
192 mlx5_eq_comp_int(eq->core.irqn, eq);220 mlx5_eq_comp_int(&eq->irq_nb, 0, NULL);
193 count_eqe = eq->core.cons_index - count_eqe;221 count_eqe = eq->core.cons_index - count_eqe;
194 enable_irq(eq->core.irqn);222 enable_irq(eq->core.irqn);
195 223
196 return count_eqe;224 return count_eqe;
197}225}
198 226
199static irqreturn_t mlx5_eq_async_int(int irq, void *eq_ptr)227static int mlx5_eq_async_int(struct notifier_block *nb,
228 unsigned long action, void *data)
200{229{
201 struct mlx5_eq *eq = eq_ptr;230 struct mlx5_eq_async *eq_async =
231 container_of(nb, struct mlx5_eq_async, irq_nb);
232 struct mlx5_eq *eq = &eq_async->core;
202 struct mlx5_eq_table *eqt;233 struct mlx5_eq_table *eqt;
203 struct mlx5_core_dev *dev;234 struct mlx5_core_dev *dev;
204 struct mlx5_eqe *eqe;235 struct mlx5_eqe *eqe;
@@ -232,7 +263,7 @@ static irqreturn_t mlx5_eq_async_int(int irq, void *eq_ptr) · 27 unmodified lines
232out:263out:
233 eq_update_ci(eq, 1);264 eq_update_ci(eq, 1);
234 265
235 return IRQ_HANDLED;266 return 0;
236}267}
237 268
238static void init_eq_buf(struct mlx5_eq *eq)269static void init_eq_buf(struct mlx5_eq *eq)
@@ -254,6 +285,7 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, const char *name, · 15 unmodified lines
254 struct mlx5_cq_table *cq_table = &eq->cq_table;285 struct mlx5_cq_table *cq_table = &eq->cq_table;
255 u32 out[MLX5_ST_SZ_DW(create_eq_out)] = {0};286 u32 out[MLX5_ST_SZ_DW(create_eq_out)] = {0};
256 struct mlx5_priv *priv = &dev->priv;287 struct mlx5_priv *priv = &dev->priv;
288 struct mlx5_irq_info *irq_info;
257 u8 vecidx = param->index;289 u8 vecidx = param->index;
258 __be64 *pas;290 __be64 *pas;
259 void *eqc;291 void *eqc;
@@ -261,9 +293,6 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, const char *name, · 1 unmodified line
261 u32 *in;293 u32 *in;
262 int err;294 int err;
263 295
264 if (eq_table->irq_info[vecidx].context)
265 return -EEXIST;
266
267 /* Init CQ table */296 /* Init CQ table */
268 memset(cq_table, 0, sizeof(*cq_table));297 memset(cq_table, 0, sizeof(*cq_table));
269 spin_lock_init(&cq_table->lock);298 spin_lock_init(&cq_table->lock);
@@ -306,24 +335,31 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, const char *name, · 36 unmodified lines
306 if (err)335 if (err)
307 goto err_in;336 goto err_in;
308 337
309 snprintf(eq_table->irq_info[vecidx].name, MLX5_MAX_IRQ_NAME, "%s@pci:%s",338 irq_info = mlx5_irq_get(dev, vecidx);
310 name, pci_name(dev->pdev));339 ATOMIC_INIT_NOTIFIER_HEAD(&irq_info->nh);
311 eq_table->irq_info[vecidx].context = param->context;340 snprintf(irq_info->name, MLX5_MAX_IRQ_NAME,
341 "%s@pci:%s", name, pci_name(dev->pdev));
312 342
313 eq->vecidx = vecidx;343 eq->vecidx = vecidx;
314 eq->eqn = MLX5_GET(create_eq_out, out, eq_number);344 eq->eqn = MLX5_GET(create_eq_out, out, eq_number);
315 eq->irqn = pci_irq_vector(dev->pdev, vecidx);345 eq->irqn = pci_irq_vector(dev->pdev, vecidx);
316 eq->dev = dev;346 eq->dev = dev;
317 eq->doorbell = priv->uar->map + MLX5_EQ_DOORBEL_OFFSET;347 eq->doorbell = priv->uar->map + MLX5_EQ_DOORBEL_OFFSET;
318 err = request_irq(eq->irqn, param->handler, 0,348 eq->irq_nb = param->nb;
319 eq_table->irq_info[vecidx].name, param->context);349
350 err = request_irq(eq->irqn, mlx5_irq_int_handler, 0, irq_info->name,
351 &irq_info->nh);
320 if (err)352 if (err)
321 goto err_eq;353 goto err_eq;
322 354
323 err = mlx5_debug_eq_add(dev, eq);355 err = mlx5_irq_attach_nb(irq_info, param->nb);
324 if (err)356 if (err)
325 goto err_irq;357 goto err_irq;
326 358
359 err = mlx5_debug_eq_add(dev, eq);
360 if (err)
361 goto err_detach;
362
327 /* EQs are created in ARMED state363 /* EQs are created in ARMED state
328 */364 */
329 eq_update_ci(eq, 1);365 eq_update_ci(eq, 1);
@@ -331,8 +367,11 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, const char *name, · 1 unmodified line
331 kvfree(in);367 kvfree(in);
332 return 0;368 return 0;
333 369
370err_detach:
371 mlx5_irq_detach_nb(irq_info, param->nb);
372
334err_irq:373err_irq:
335 free_irq(eq->irqn, eq);374 free_irq(eq->irqn, &eq_table->irq_info[vecidx].nh);
336 375
337err_eq:376err_eq:
338 mlx5_cmd_destroy_eq(dev, eq->eqn);377 mlx5_cmd_destroy_eq(dev, eq->eqn);
@@ -355,9 +394,11 @@ static int destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq) · 16 unmodified lines
355 394
356 mlx5_debug_eq_remove(dev, eq);395 mlx5_debug_eq_remove(dev, eq);
357 396
358 free_irq(eq->irqn, irq_info->context);397 err = mlx5_irq_detach_nb(irq_info, eq->irq_nb);
359 irq_info->context = NULL;398 if (err)
360 399 mlx5_core_warn(eq->dev, "eq failed to detach from irq. err %d",
400 err);
401 free_irq(eq->irqn, &eq_table->irq_info[eq->vecidx].nh);
361 err = mlx5_cmd_destroy_eq(dev, eq->eqn);402 err = mlx5_cmd_destroy_eq(dev, eq->eqn);
362 if (err)403 if (err)
363 mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n",404 mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n",
@@ -479,7 +520,7 @@ static int cq_err_event_notifier(struct notifier_block *nb, · 115 unmodified lines
479 /* type == MLX5_EVENT_TYPE_CQ_ERROR */520 /* type == MLX5_EVENT_TYPE_CQ_ERROR */
480 521
481 eqt = mlx5_nb_cof(nb, struct mlx5_eq_table, cq_err_nb);522 eqt = mlx5_nb_cof(nb, struct mlx5_eq_table, cq_err_nb);
482 eq = &eqt->async_eq;523 eq = &eqt->async_eq.core;
483 eqe = data;524 eqe = data;
484 525
485 cqn = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff;526 cqn = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff;
@@ -548,14 +589,14 @@ static int create_async_eqs(struct mlx5_core_dev *dev) · 62 unmodified lines
548 MLX5_NB_INIT(&table->cq_err_nb, cq_err_event_notifier, CQ_ERROR);589 MLX5_NB_INIT(&table->cq_err_nb, cq_err_event_notifier, CQ_ERROR);
549 mlx5_eq_notifier_register(dev, &table->cq_err_nb);590 mlx5_eq_notifier_register(dev, &table->cq_err_nb);
550 591
592 table->cmd_eq.irq_nb.notifier_call = mlx5_eq_async_int;
551 param = (struct mlx5_eq_param) {593 param = (struct mlx5_eq_param) {
552 .index = MLX5_EQ_CMD_IDX,594 .index = MLX5_EQ_CMD_IDX,
553 .mask = 1ull << MLX5_EVENT_TYPE_CMD,595 .mask = 1ull << MLX5_EVENT_TYPE_CMD,
554 .nent = MLX5_NUM_CMD_EQE,596 .nent = MLX5_NUM_CMD_EQE,
555 .context = &table->cmd_eq,597 .nb = &table->cmd_eq.irq_nb,
556 .handler = mlx5_eq_async_int,
557 };598 };
558 err = create_async_eq(dev, "mlx5_cmd_eq", &table->cmd_eq, &param);599 err = create_async_eq(dev, "mlx5_cmd_eq", &table->cmd_eq.core, &param);
559 if (err) {600 if (err) {
560 mlx5_core_warn(dev, "failed to create cmd EQ %d\n", err);601 mlx5_core_warn(dev, "failed to create cmd EQ %d\n", err);
561 goto err0;602 goto err0;
@@ -563,27 +604,29 @@ static int create_async_eqs(struct mlx5_core_dev *dev) · 1 unmodified line
563 604
564 mlx5_cmd_use_events(dev);605 mlx5_cmd_use_events(dev);
565 606
607 table->async_eq.irq_nb.notifier_call = mlx5_eq_async_int;
566 param = (struct mlx5_eq_param) {608 param = (struct mlx5_eq_param) {
567 .index = MLX5_EQ_ASYNC_IDX,609 .index = MLX5_EQ_ASYNC_IDX,
568 .mask = gather_async_events_mask(dev),610 .mask = gather_async_events_mask(dev),
569 .nent = MLX5_NUM_ASYNC_EQE,611 .nent = MLX5_NUM_ASYNC_EQE,
570 .context = &table->async_eq,612 .nb = &table->async_eq.irq_nb,
571 .handler = mlx5_eq_async_int,
572 };613 };
573 err = create_async_eq(dev, "mlx5_async_eq", &table->async_eq, &param);614 err = create_async_eq(dev, "mlx5_async_eq",
615 &table->async_eq.core, &param);
574 if (err) {616 if (err) {
575 mlx5_core_warn(dev, "failed to create async EQ %d\n", err);617 mlx5_core_warn(dev, "failed to create async EQ %d\n", err);
576 goto err1;618 goto err1;
577 }619 }
578 620
621 table->pages_eq.irq_nb.notifier_call = mlx5_eq_async_int;
579 param = (struct mlx5_eq_param) {622 param = (struct mlx5_eq_param) {
580 .index = MLX5_EQ_PAGEREQ_IDX,623 .index = MLX5_EQ_PAGEREQ_IDX,
581 .mask = 1 << MLX5_EVENT_TYPE_PAGE_REQUEST,624 .mask = 1 << MLX5_EVENT_TYPE_PAGE_REQUEST,
582 .nent = /* TODO: sriov max_vf + */ 1,625 .nent = /* TODO: sriov max_vf + */ 1,
583 .context = &table->pages_eq,626 .nb = &table->pages_eq.irq_nb,
584 .handler = mlx5_eq_async_int,
585 };627 };
586 err = create_async_eq(dev, "mlx5_pages_eq", &table->pages_eq, &param);628 err = create_async_eq(dev, "mlx5_pages_eq",
629 &table->pages_eq.core, &param);
587 if (err) {630 if (err) {
588 mlx5_core_warn(dev, "failed to create pages EQ %d\n", err);631 mlx5_core_warn(dev, "failed to create pages EQ %d\n", err);
589 goto err2;632 goto err2;
@@ -592,11 +635,11 @@ static int create_async_eqs(struct mlx5_core_dev *dev) · 2 unmodified lines
592 return err;635 return err;
593 636
594err2:637err2:
595 destroy_async_eq(dev, &table->async_eq);638 destroy_async_eq(dev, &table->async_eq.core);
596 639
597err1:640err1:
598 mlx5_cmd_use_polling(dev);641 mlx5_cmd_use_polling(dev);
599 destroy_async_eq(dev, &table->cmd_eq);642 destroy_async_eq(dev, &table->cmd_eq.core);
600err0:643err0:
601 mlx5_eq_notifier_unregister(dev, &table->cq_err_nb);644 mlx5_eq_notifier_unregister(dev, &table->cq_err_nb);
602 return err;645 return err;
@@ -607,19 +650,19 @@ static void destroy_async_eqs(struct mlx5_core_dev *dev) · 4 unmodified lines
607 struct mlx5_eq_table *table = dev->priv.eq_table;650 struct mlx5_eq_table *table = dev->priv.eq_table;
608 int err;651 int err;
609 652
610 err = destroy_async_eq(dev, &table->pages_eq);653 err = destroy_async_eq(dev, &table->pages_eq.core);
611 if (err)654 if (err)
612 mlx5_core_err(dev, "failed to destroy pages eq, err(%d)\n",655 mlx5_core_err(dev, "failed to destroy pages eq, err(%d)\n",
613 err);656 err);
614 657
615 err = destroy_async_eq(dev, &table->async_eq);658 err = destroy_async_eq(dev, &table->async_eq.core);
616 if (err)659 if (err)
617 mlx5_core_err(dev, "failed to destroy async eq, err(%d)\n",660 mlx5_core_err(dev, "failed to destroy async eq, err(%d)\n",
618 err);661 err);
619 662
620 mlx5_cmd_use_polling(dev);663 mlx5_cmd_use_polling(dev);
621 664
622 err = destroy_async_eq(dev, &table->cmd_eq);665 err = destroy_async_eq(dev, &table->cmd_eq.core);
623 if (err)666 if (err)
624 mlx5_core_err(dev, "failed to destroy command eq, err(%d)\n",667 mlx5_core_err(dev, "failed to destroy command eq, err(%d)\n",
625 err);668 err);
@@ -629,17 +672,17 @@ static void destroy_async_eqs(struct mlx5_core_dev *dev) · 3 unmodified lines
629 672
630struct mlx5_eq *mlx5_get_async_eq(struct mlx5_core_dev *dev)673struct mlx5_eq *mlx5_get_async_eq(struct mlx5_core_dev *dev)
631{674{
632 return &dev->priv.eq_table->async_eq;675 return &dev->priv.eq_table->async_eq.core;
633}676}
634 677
635void mlx5_eq_synchronize_async_irq(struct mlx5_core_dev *dev)678void mlx5_eq_synchronize_async_irq(struct mlx5_core_dev *dev)
636{679{
637 synchronize_irq(dev->priv.eq_table->async_eq.irqn);680 synchronize_irq(dev->priv.eq_table->async_eq.core.irqn);
638}681}
639 682
640void mlx5_eq_synchronize_cmd_irq(struct mlx5_core_dev *dev)683void mlx5_eq_synchronize_cmd_irq(struct mlx5_core_dev *dev)
641{684{
642 synchronize_irq(dev->priv.eq_table->cmd_eq.irqn);685 synchronize_irq(dev->priv.eq_table->cmd_eq.core.irqn);
643}686}
644 687
645/* Generic EQ API for mlx5_core consumers688/* Generic EQ API for mlx5_core consumers
@@ -837,12 +880,12 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) · 191 unmodified lines
837 irq_cpu_rmap_add(table->rmap, pci_irq_vector(dev->pdev, vecidx));880 irq_cpu_rmap_add(table->rmap, pci_irq_vector(dev->pdev, vecidx));
838#endif881#endif
839 snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", i);882 snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", i);
883 eq->irq_nb.notifier_call = mlx5_eq_comp_int;
840 param = (struct mlx5_eq_param) {884 param = (struct mlx5_eq_param) {
841 .index = vecidx,885 .index = vecidx,
842 .mask = 0,886 .mask = 0,
843 .nent = nent,887 .nent = nent,
844 .context = &eq->core,888 .nb = &eq->irq_nb,
845 .handler = mlx5_eq_comp_int
846 };889 };
847 err = create_map_eq(dev, &eq->core, name, &param);890 err = create_map_eq(dev, &eq->core, name, &param);
848 if (err) {891 if (err) {
@@ -940,10 +983,7 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev) · 91 unmodified lines
940 mutex_lock(&table->lock); /* sync with create/destroy_async_eq */983 mutex_lock(&table->lock); /* sync with create/destroy_async_eq */
941 max_eqs = table->num_comp_vectors + MLX5_EQ_VEC_COMP_BASE;984 max_eqs = table->num_comp_vectors + MLX5_EQ_VEC_COMP_BASE;
942 for (i = max_eqs - 1; i >= 0; i--) {985 for (i = max_eqs - 1; i >= 0; i--) {
943 if (!table->irq_info[i].context)986 free_irq(pci_irq_vector(dev->pdev, i), &table->irq_info[i].nh);
944 continue;
945 free_irq(pci_irq_vector(dev->pdev, i), table->irq_info[i].context);
946 table->irq_info[i].context = NULL;
947 }987 }
948 mutex_unlock(&table->lock);988 mutex_unlock(&table->lock);
949 pci_free_irq_vectors(dev->pdev);989 pci_free_irq_vectors(dev->pdev);
drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h+8−1
@@ -34,10 +34,17 @@ struct mlx5_eq { · 33 unmodified lines
34 u8 eqn;34 u8 eqn;
35 int nent;35 int nent;
36 struct mlx5_rsc_debug *dbg;36 struct mlx5_rsc_debug *dbg;
37 struct notifier_block *irq_nb; /* For destroy only */
38};
39
40struct mlx5_eq_async {
41 struct mlx5_eq core;
42 struct notifier_block irq_nb;
37};43};
38 44
39struct mlx5_eq_comp {45struct mlx5_eq_comp {
40 struct mlx5_eq core; /* Must be first */46 struct mlx5_eq core;
47 struct notifier_block irq_nb;
41 struct mlx5_eq_tasklet tasklet_ctx;48 struct mlx5_eq_tasklet tasklet_ctx;
42 struct list_head list;49 struct list_head list;
43};50};
include/linux/mlx5/eq.h+1−2
@@ -26,8 +26,7 @@ struct mlx5_eq_param { · 25 unmodified lines
26 u8 index;26 u8 index;
27 int nent;27 int nent;
28 u64 mask;28 u64 mask;
29 void *context;29 struct notifier_block *nb;
30 irq_handler_t handler;
31};30};
32 31
33struct mlx5_eq *32struct mlx5_eq *

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t