aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4/eq.c
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2011-03-22 18:37:47 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-23 15:24:18 -0400
commit0b7ca5a928e2271bbc225e9e1ac1f22e9fbee54f (patch)
tree8a24efdb4ceb6f28a8d49e942f80d397c06f4a5f /drivers/net/mlx4/eq.c
parent908222655b38005483d64385e06341a38647fdf1 (diff)
mlx4: Changing interrupt scheme
Adding a pool of MSI-X vectors and EQs that can be used explicitly by mlx4_core customers (mlx4_ib, mlx4_en). The consumers will assign their own names to the interrupt vectors. Those vectors are not opened at mlx4 device initialization, opened by demand. Changed the max number of possible EQs according to the new scheme, no longer relies on on number of cores. The new functionality is exposed through mlx4_assign_eq() and mlx4_release_eq(). Customers that do not use the new API will get completion vectors as before. Signed-off-by: Markuze Alex <markuze@mellanox.co.il> Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/mlx4/eq.c')
-rw-r--r--drivers/net/mlx4/eq.c107
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
44enum { 44enum {
45 MLX4_IRQNAME_SIZE = 64 45 MLX4_IRQNAME_SIZE = 32
46}; 46};
47 47
48enum { 48enum {
@@ -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
324static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq) 324static 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,
496static void mlx4_free_irqs(struct mlx4_dev *dev) 496static 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}
745EXPORT_SYMBOL(mlx4_test_interrupts); 778EXPORT_SYMBOL(mlx4_test_interrupts);
779
780int 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}
818EXPORT_SYMBOL(mlx4_assign_eq);
819
820void 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}
839EXPORT_SYMBOL(mlx4_release_eq);
840