aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4/eq.c
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2007-07-12 10:50:45 -0400
committerRoland Dreier <rolandd@cisco.com>2007-07-17 21:37:42 -0400
commitee49bd9397cd2b8fe7a1962505d81c1d0a1366fc (patch)
tree064800f1ebcf6c2586f6727aa03c85e875b96289 /drivers/net/mlx4/eq.c
parent41179e2de6962b46d1d9f2b4437243ac740efdec (diff)
mlx4_core: Reset device when internal error is detected
Reset the device when an internal error is detected. Also, detect errors by polling the error buffer rather than using interrupts. This is more robust and doesn't depend on MSI-X. Remove the old interrupt handler entirely, since we don't want to support two mechanisms for detecting internal errors. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/net/mlx4/eq.c')
-rw-r--r--drivers/net/mlx4/eq.c56
1 files changed, 7 insertions, 49 deletions
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 27a82cecd693..2095c843fa15 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -89,14 +89,12 @@ struct mlx4_eq_context {
89 (1ull << MLX4_EVENT_TYPE_PATH_MIG_FAILED) | \ 89 (1ull << MLX4_EVENT_TYPE_PATH_MIG_FAILED) | \
90 (1ull << MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \ 90 (1ull << MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \
91 (1ull << MLX4_EVENT_TYPE_WQ_ACCESS_ERROR) | \ 91 (1ull << MLX4_EVENT_TYPE_WQ_ACCESS_ERROR) | \
92 (1ull << MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR) | \
93 (1ull << MLX4_EVENT_TYPE_PORT_CHANGE) | \ 92 (1ull << MLX4_EVENT_TYPE_PORT_CHANGE) | \
94 (1ull << MLX4_EVENT_TYPE_ECC_DETECT) | \ 93 (1ull << MLX4_EVENT_TYPE_ECC_DETECT) | \
95 (1ull << MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) | \ 94 (1ull << MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) | \
96 (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \ 95 (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \
97 (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \ 96 (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \
98 (1ull << MLX4_EVENT_TYPE_CMD)) 97 (1ull << MLX4_EVENT_TYPE_CMD))
99#define MLX4_CATAS_EVENT_MASK (1ull << MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR)
100 98
101struct mlx4_eqe { 99struct mlx4_eqe {
102 u8 reserved1; 100 u8 reserved1;
@@ -264,7 +262,7 @@ static irqreturn_t mlx4_interrupt(int irq, void *dev_ptr)
264 262
265 writel(priv->eq_table.clr_mask, priv->eq_table.clr_int); 263 writel(priv->eq_table.clr_mask, priv->eq_table.clr_int);
266 264
267 for (i = 0; i < MLX4_EQ_CATAS; ++i) 265 for (i = 0; i < MLX4_NUM_EQ; ++i)
268 work |= mlx4_eq_int(dev, &priv->eq_table.eq[i]); 266 work |= mlx4_eq_int(dev, &priv->eq_table.eq[i]);
269 267
270 return IRQ_RETVAL(work); 268 return IRQ_RETVAL(work);
@@ -281,14 +279,6 @@ static irqreturn_t mlx4_msi_x_interrupt(int irq, void *eq_ptr)
281 return IRQ_HANDLED; 279 return IRQ_HANDLED;
282} 280}
283 281
284static irqreturn_t mlx4_catas_interrupt(int irq, void *dev_ptr)
285{
286 mlx4_handle_catas_err(dev_ptr);
287
288 /* MSI-X vectors always belong to us */
289 return IRQ_HANDLED;
290}
291
292static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap, 282static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap,
293 int eq_num) 283 int eq_num)
294{ 284{
@@ -490,11 +480,9 @@ static void mlx4_free_irqs(struct mlx4_dev *dev)
490 480
491 if (eq_table->have_irq) 481 if (eq_table->have_irq)
492 free_irq(dev->pdev->irq, dev); 482 free_irq(dev->pdev->irq, dev);
493 for (i = 0; i < MLX4_EQ_CATAS; ++i) 483 for (i = 0; i < MLX4_NUM_EQ; ++i)
494 if (eq_table->eq[i].have_irq) 484 if (eq_table->eq[i].have_irq)
495 free_irq(eq_table->eq[i].irq, eq_table->eq + i); 485 free_irq(eq_table->eq[i].irq, eq_table->eq + i);
496 if (eq_table->eq[MLX4_EQ_CATAS].have_irq)
497 free_irq(eq_table->eq[MLX4_EQ_CATAS].irq, dev);
498} 486}
499 487
500static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev) 488static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev)
@@ -598,32 +586,19 @@ int __devinit mlx4_init_eq_table(struct mlx4_dev *dev)
598 if (dev->flags & MLX4_FLAG_MSI_X) { 586 if (dev->flags & MLX4_FLAG_MSI_X) {
599 static const char *eq_name[] = { 587 static const char *eq_name[] = {
600 [MLX4_EQ_COMP] = DRV_NAME " (comp)", 588 [MLX4_EQ_COMP] = DRV_NAME " (comp)",
601 [MLX4_EQ_ASYNC] = DRV_NAME " (async)", 589 [MLX4_EQ_ASYNC] = DRV_NAME " (async)"
602 [MLX4_EQ_CATAS] = DRV_NAME " (catas)"
603 }; 590 };
604 591
605 err = mlx4_create_eq(dev, 1, MLX4_EQ_CATAS, 592 for (i = 0; i < MLX4_NUM_EQ; ++i) {
606 &priv->eq_table.eq[MLX4_EQ_CATAS]);
607 if (err)
608 goto err_out_async;
609
610 for (i = 0; i < MLX4_EQ_CATAS; ++i) {
611 err = request_irq(priv->eq_table.eq[i].irq, 593 err = request_irq(priv->eq_table.eq[i].irq,
612 mlx4_msi_x_interrupt, 594 mlx4_msi_x_interrupt,
613 0, eq_name[i], priv->eq_table.eq + i); 595 0, eq_name[i], priv->eq_table.eq + i);
614 if (err) 596 if (err)
615 goto err_out_catas; 597 goto err_out_async;
616 598
617 priv->eq_table.eq[i].have_irq = 1; 599 priv->eq_table.eq[i].have_irq = 1;
618 } 600 }
619 601
620 err = request_irq(priv->eq_table.eq[MLX4_EQ_CATAS].irq,
621 mlx4_catas_interrupt, 0,
622 eq_name[MLX4_EQ_CATAS], dev);
623 if (err)
624 goto err_out_catas;
625
626 priv->eq_table.eq[MLX4_EQ_CATAS].have_irq = 1;
627 } else { 602 } else {
628 err = request_irq(dev->pdev->irq, mlx4_interrupt, 603 err = request_irq(dev->pdev->irq, mlx4_interrupt,
629 IRQF_SHARED, DRV_NAME, dev); 604 IRQF_SHARED, DRV_NAME, dev);
@@ -639,22 +614,11 @@ int __devinit mlx4_init_eq_table(struct mlx4_dev *dev)
639 mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n", 614 mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
640 priv->eq_table.eq[MLX4_EQ_ASYNC].eqn, err); 615 priv->eq_table.eq[MLX4_EQ_ASYNC].eqn, err);
641 616
642 for (i = 0; i < MLX4_EQ_CATAS; ++i) 617 for (i = 0; i < MLX4_NUM_EQ; ++i)
643 eq_set_ci(&priv->eq_table.eq[i], 1); 618 eq_set_ci(&priv->eq_table.eq[i], 1);
644 619
645 if (dev->flags & MLX4_FLAG_MSI_X) {
646 err = mlx4_MAP_EQ(dev, MLX4_CATAS_EVENT_MASK, 0,
647 priv->eq_table.eq[MLX4_EQ_CATAS].eqn);
648 if (err)
649 mlx4_warn(dev, "MAP_EQ for catas EQ %d failed (%d)\n",
650 priv->eq_table.eq[MLX4_EQ_CATAS].eqn, err);
651 }
652
653 return 0; 620 return 0;
654 621
655err_out_catas:
656 mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_CATAS]);
657
658err_out_async: 622err_out_async:
659 mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_ASYNC]); 623 mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_ASYNC]);
660 624
@@ -675,19 +639,13 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
675 struct mlx4_priv *priv = mlx4_priv(dev); 639 struct mlx4_priv *priv = mlx4_priv(dev);
676 int i; 640 int i;
677 641
678 if (dev->flags & MLX4_FLAG_MSI_X)
679 mlx4_MAP_EQ(dev, MLX4_CATAS_EVENT_MASK, 1,
680 priv->eq_table.eq[MLX4_EQ_CATAS].eqn);
681
682 mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1, 642 mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1,
683 priv->eq_table.eq[MLX4_EQ_ASYNC].eqn); 643 priv->eq_table.eq[MLX4_EQ_ASYNC].eqn);
684 644
685 mlx4_free_irqs(dev); 645 mlx4_free_irqs(dev);
686 646
687 for (i = 0; i < MLX4_EQ_CATAS; ++i) 647 for (i = 0; i < MLX4_NUM_EQ; ++i)
688 mlx4_free_eq(dev, &priv->eq_table.eq[i]); 648 mlx4_free_eq(dev, &priv->eq_table.eq[i]);
689 if (dev->flags & MLX4_FLAG_MSI_X)
690 mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_CATAS]);
691 649
692 mlx4_unmap_clr_int(dev); 650 mlx4_unmap_clr_int(dev);
693 651