diff options
Diffstat (limited to 'drivers/net/mlx4/eq.c')
-rw-r--r-- | drivers/net/mlx4/eq.c | 107 |
1 files changed, 101 insertions, 6 deletions
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index 552d0fce6f67..506cfd0372ec 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "fw.h" | 42 | #include "fw.h" |
43 | 43 | ||
44 | enum { | 44 | enum { |
45 | MLX4_IRQNAME_SIZE = 64 | 45 | MLX4_IRQNAME_SIZE = 32 |
46 | }; | 46 | }; |
47 | 47 | ||
48 | enum { | 48 | enum { |
@@ -317,8 +317,8 @@ static int mlx4_num_eq_uar(struct mlx4_dev *dev) | |||
317 | * we need to map, take the difference of highest index and | 317 | * we need to map, take the difference of highest index and |
318 | * the lowest index we'll use and add 1. | 318 | * the lowest index we'll use and add 1. |
319 | */ | 319 | */ |
320 | return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs) / 4 - | 320 | return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs + |
321 | dev->caps.reserved_eqs / 4 + 1; | 321 | dev->caps.comp_pool)/4 - dev->caps.reserved_eqs/4 + 1; |
322 | } | 322 | } |
323 | 323 | ||
324 | static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq) | 324 | static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq) |
@@ -496,16 +496,32 @@ static void mlx4_free_eq(struct mlx4_dev *dev, | |||
496 | static void mlx4_free_irqs(struct mlx4_dev *dev) | 496 | static void mlx4_free_irqs(struct mlx4_dev *dev) |
497 | { | 497 | { |
498 | struct mlx4_eq_table *eq_table = &mlx4_priv(dev)->eq_table; | 498 | struct mlx4_eq_table *eq_table = &mlx4_priv(dev)->eq_table; |
499 | int i; | 499 | struct mlx4_priv *priv = mlx4_priv(dev); |
500 | int i, vec; | ||
500 | 501 | ||
501 | if (eq_table->have_irq) | 502 | if (eq_table->have_irq) |
502 | free_irq(dev->pdev->irq, dev); | 503 | free_irq(dev->pdev->irq, dev); |
504 | |||
503 | for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i) | 505 | for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i) |
504 | if (eq_table->eq[i].have_irq) { | 506 | if (eq_table->eq[i].have_irq) { |
505 | free_irq(eq_table->eq[i].irq, eq_table->eq + i); | 507 | free_irq(eq_table->eq[i].irq, eq_table->eq + i); |
506 | eq_table->eq[i].have_irq = 0; | 508 | eq_table->eq[i].have_irq = 0; |
507 | } | 509 | } |
508 | 510 | ||
511 | for (i = 0; i < dev->caps.comp_pool; i++) { | ||
512 | /* | ||
513 | * Freeing the assigned irq's | ||
514 | * all bits should be 0, but we need to validate | ||
515 | */ | ||
516 | if (priv->msix_ctl.pool_bm & 1ULL << i) { | ||
517 | /* NO need protecting*/ | ||
518 | vec = dev->caps.num_comp_vectors + 1 + i; | ||
519 | free_irq(priv->eq_table.eq[vec].irq, | ||
520 | &priv->eq_table.eq[vec]); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | |||
509 | kfree(eq_table->irq_names); | 525 | kfree(eq_table->irq_names); |
510 | } | 526 | } |
511 | 527 | ||
@@ -578,7 +594,8 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) | |||
578 | (priv->eq_table.inta_pin < 32 ? 4 : 0); | 594 | (priv->eq_table.inta_pin < 32 ? 4 : 0); |
579 | 595 | ||
580 | priv->eq_table.irq_names = | 596 | priv->eq_table.irq_names = |
581 | kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1), | 597 | kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1 + |
598 | dev->caps.comp_pool), | ||
582 | GFP_KERNEL); | 599 | GFP_KERNEL); |
583 | if (!priv->eq_table.irq_names) { | 600 | if (!priv->eq_table.irq_names) { |
584 | err = -ENOMEM; | 601 | err = -ENOMEM; |
@@ -601,6 +618,22 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) | |||
601 | if (err) | 618 | if (err) |
602 | goto err_out_comp; | 619 | goto err_out_comp; |
603 | 620 | ||
621 | /*if additional completion vectors poolsize is 0 this loop will not run*/ | ||
622 | for (i = dev->caps.num_comp_vectors + 1; | ||
623 | i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i) { | ||
624 | |||
625 | err = mlx4_create_eq(dev, dev->caps.num_cqs - | ||
626 | dev->caps.reserved_cqs + | ||
627 | MLX4_NUM_SPARE_EQE, | ||
628 | (dev->flags & MLX4_FLAG_MSI_X) ? i : 0, | ||
629 | &priv->eq_table.eq[i]); | ||
630 | if (err) { | ||
631 | --i; | ||
632 | goto err_out_unmap; | ||
633 | } | ||
634 | } | ||
635 | |||
636 | |||
604 | if (dev->flags & MLX4_FLAG_MSI_X) { | 637 | if (dev->flags & MLX4_FLAG_MSI_X) { |
605 | const char *eq_name; | 638 | const char *eq_name; |
606 | 639 | ||
@@ -686,7 +719,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev) | |||
686 | 719 | ||
687 | mlx4_free_irqs(dev); | 720 | mlx4_free_irqs(dev); |
688 | 721 | ||
689 | for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i) | 722 | for (i = 0; i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i) |
690 | mlx4_free_eq(dev, &priv->eq_table.eq[i]); | 723 | mlx4_free_eq(dev, &priv->eq_table.eq[i]); |
691 | 724 | ||
692 | mlx4_unmap_clr_int(dev); | 725 | mlx4_unmap_clr_int(dev); |
@@ -743,3 +776,65 @@ int mlx4_test_interrupts(struct mlx4_dev *dev) | |||
743 | return err; | 776 | return err; |
744 | } | 777 | } |
745 | EXPORT_SYMBOL(mlx4_test_interrupts); | 778 | EXPORT_SYMBOL(mlx4_test_interrupts); |
779 | |||
780 | int mlx4_assign_eq(struct mlx4_dev *dev, char* name, int * vector) | ||
781 | { | ||
782 | |||
783 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
784 | int vec = 0, err = 0, i; | ||
785 | |||
786 | spin_lock(&priv->msix_ctl.pool_lock); | ||
787 | for (i = 0; !vec && i < dev->caps.comp_pool; i++) { | ||
788 | if (~priv->msix_ctl.pool_bm & 1ULL << i) { | ||
789 | priv->msix_ctl.pool_bm |= 1ULL << i; | ||
790 | vec = dev->caps.num_comp_vectors + 1 + i; | ||
791 | snprintf(priv->eq_table.irq_names + | ||
792 | vec * MLX4_IRQNAME_SIZE, | ||
793 | MLX4_IRQNAME_SIZE, "%s", name); | ||
794 | err = request_irq(priv->eq_table.eq[vec].irq, | ||
795 | mlx4_msi_x_interrupt, 0, | ||
796 | &priv->eq_table.irq_names[vec<<5], | ||
797 | priv->eq_table.eq + vec); | ||
798 | if (err) { | ||
799 | /*zero out bit by fliping it*/ | ||
800 | priv->msix_ctl.pool_bm ^= 1 << i; | ||
801 | vec = 0; | ||
802 | continue; | ||
803 | /*we dont want to break here*/ | ||
804 | } | ||
805 | eq_set_ci(&priv->eq_table.eq[vec], 1); | ||
806 | } | ||
807 | } | ||
808 | spin_unlock(&priv->msix_ctl.pool_lock); | ||
809 | |||
810 | if (vec) { | ||
811 | *vector = vec; | ||
812 | } else { | ||
813 | *vector = 0; | ||
814 | err = (i == dev->caps.comp_pool) ? -ENOSPC : err; | ||
815 | } | ||
816 | return err; | ||
817 | } | ||
818 | EXPORT_SYMBOL(mlx4_assign_eq); | ||
819 | |||
820 | void mlx4_release_eq(struct mlx4_dev *dev, int vec) | ||
821 | { | ||
822 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
823 | /*bm index*/ | ||
824 | int i = vec - dev->caps.num_comp_vectors - 1; | ||
825 | |||
826 | if (likely(i >= 0)) { | ||
827 | /*sanity check , making sure were not trying to free irq's | ||
828 | Belonging to a legacy EQ*/ | ||
829 | spin_lock(&priv->msix_ctl.pool_lock); | ||
830 | if (priv->msix_ctl.pool_bm & 1ULL << i) { | ||
831 | free_irq(priv->eq_table.eq[vec].irq, | ||
832 | &priv->eq_table.eq[vec]); | ||
833 | priv->msix_ctl.pool_bm &= ~(1ULL << i); | ||
834 | } | ||
835 | spin_unlock(&priv->msix_ctl.pool_lock); | ||
836 | } | ||
837 | |||
838 | } | ||
839 | EXPORT_SYMBOL(mlx4_release_eq); | ||
840 | |||