aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2009-09-05 23:24:49 -0400
committerRoland Dreier <rolandd@cisco.com>2009-09-05 23:24:49 -0400
commitfa0681d2129732027355d6b7083dd8932b9b799d (patch)
tree0730a4ccab5f7c5b4da772b76e6e709839ffe643
parent338a8fad27908f64a0d249cc9f5c7d4ddb7e5684 (diff)
mlx4_core: Allocate and map sufficient ICM memory for EQ context
The current implementation allocates a single host page for EQ context memory, which was OK when we only allocated a few EQs. However, since we now allocate an EQ for each CPU core, this patch removes the hard-coded limit (which we exceed with 4 KB pages and 128 byte EQ context entries with 32 CPUs) and uses the same ICM table code as all other context tables, which ends up simplifying the code quite a bit while fixing the problem. This problem was actually hit in practice on a dual-socket Nehalem box with 16 real hardware threads and sufficiently odd ACPI tables that it shows on boot SMP: Allowing 32 CPUs, 16 hotplug CPUs so num_possible_cpus() ends up 32, and mlx4 ends up creating 33 MSI-X interrupts and 33 EQs. This mlx4 bug means that mlx4 can't even initialize at all on this quite mainstream system. Cc: <stable@kernel.org> Reported-by: Eli Cohen <eli@mellanox.co.il> Tested-by: Christoph Lameter <cl@linux-foundation.org> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/net/mlx4/eq.c42
-rw-r--r--drivers/net/mlx4/main.c9
-rw-r--r--drivers/net/mlx4/mlx4.h7
3 files changed, 7 insertions, 51 deletions
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index c11a0525c40e..d7974a60b961 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -525,48 +525,6 @@ static void mlx4_unmap_clr_int(struct mlx4_dev *dev)
525 iounmap(priv->clr_base); 525 iounmap(priv->clr_base);
526} 526}
527 527
528int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt)
529{
530 struct mlx4_priv *priv = mlx4_priv(dev);
531 int ret;
532
533 /*
534 * We assume that mapping one page is enough for the whole EQ
535 * context table. This is fine with all current HCAs, because
536 * we only use 32 EQs and each EQ uses 64 bytes of context
537 * memory, or 1 KB total.
538 */
539 priv->eq_table.icm_virt = icm_virt;
540 priv->eq_table.icm_page = alloc_page(GFP_HIGHUSER);
541 if (!priv->eq_table.icm_page)
542 return -ENOMEM;
543 priv->eq_table.icm_dma = pci_map_page(dev->pdev, priv->eq_table.icm_page, 0,
544 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
545 if (pci_dma_mapping_error(dev->pdev, priv->eq_table.icm_dma)) {
546 __free_page(priv->eq_table.icm_page);
547 return -ENOMEM;
548 }
549
550 ret = mlx4_MAP_ICM_page(dev, priv->eq_table.icm_dma, icm_virt);
551 if (ret) {
552 pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE,
553 PCI_DMA_BIDIRECTIONAL);
554 __free_page(priv->eq_table.icm_page);
555 }
556
557 return ret;
558}
559
560void mlx4_unmap_eq_icm(struct mlx4_dev *dev)
561{
562 struct mlx4_priv *priv = mlx4_priv(dev);
563
564 mlx4_UNMAP_ICM(dev, priv->eq_table.icm_virt, 1);
565 pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE,
566 PCI_DMA_BIDIRECTIONAL);
567 __free_page(priv->eq_table.icm_page);
568}
569
570int mlx4_alloc_eq_table(struct mlx4_dev *dev) 528int mlx4_alloc_eq_table(struct mlx4_dev *dev)
571{ 529{
572 struct mlx4_priv *priv = mlx4_priv(dev); 530 struct mlx4_priv *priv = mlx4_priv(dev);
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 5c1afe0d73e8..528f89b2cde3 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -525,7 +525,10 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
525 goto err_unmap_aux; 525 goto err_unmap_aux;
526 } 526 }
527 527
528 err = mlx4_map_eq_icm(dev, init_hca->eqc_base); 528 err = mlx4_init_icm_table(dev, &priv->eq_table.table,
529 init_hca->eqc_base, dev_cap->eqc_entry_sz,
530 dev->caps.num_eqs, dev->caps.num_eqs,
531 0, 0);
529 if (err) { 532 if (err) {
530 mlx4_err(dev, "Failed to map EQ context memory, aborting.\n"); 533 mlx4_err(dev, "Failed to map EQ context memory, aborting.\n");
531 goto err_unmap_cmpt; 534 goto err_unmap_cmpt;
@@ -668,7 +671,7 @@ err_unmap_mtt:
668 mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); 671 mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table);
669 672
670err_unmap_eq: 673err_unmap_eq:
671 mlx4_unmap_eq_icm(dev); 674 mlx4_cleanup_icm_table(dev, &priv->eq_table.table);
672 675
673err_unmap_cmpt: 676err_unmap_cmpt:
674 mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); 677 mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table);
@@ -698,11 +701,11 @@ static void mlx4_free_icms(struct mlx4_dev *dev)
698 mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table); 701 mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table);
699 mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table); 702 mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table);
700 mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); 703 mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table);
704 mlx4_cleanup_icm_table(dev, &priv->eq_table.table);
701 mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); 705 mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table);
702 mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); 706 mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table);
703 mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); 707 mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table);
704 mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); 708 mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table);
705 mlx4_unmap_eq_icm(dev);
706 709
707 mlx4_UNMAP_ICM_AUX(dev); 710 mlx4_UNMAP_ICM_AUX(dev);
708 mlx4_free_icm(dev, priv->fw.aux_icm, 0); 711 mlx4_free_icm(dev, priv->fw.aux_icm, 0);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 5bd79c2b184f..bc72d6e4919b 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -205,9 +205,7 @@ struct mlx4_eq_table {
205 void __iomem **uar_map; 205 void __iomem **uar_map;
206 u32 clr_mask; 206 u32 clr_mask;
207 struct mlx4_eq *eq; 207 struct mlx4_eq *eq;
208 u64 icm_virt; 208 struct mlx4_icm_table table;
209 struct page *icm_page;
210 dma_addr_t icm_dma;
211 struct mlx4_icm_table cmpt_table; 209 struct mlx4_icm_table cmpt_table;
212 int have_irq; 210 int have_irq;
213 u8 inta_pin; 211 u8 inta_pin;
@@ -373,9 +371,6 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
373 struct mlx4_dev_cap *dev_cap, 371 struct mlx4_dev_cap *dev_cap,
374 struct mlx4_init_hca_param *init_hca); 372 struct mlx4_init_hca_param *init_hca);
375 373
376int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt);
377void mlx4_unmap_eq_icm(struct mlx4_dev *dev);
378
379int mlx4_cmd_init(struct mlx4_dev *dev); 374int mlx4_cmd_init(struct mlx4_dev *dev);
380void mlx4_cmd_cleanup(struct mlx4_dev *dev); 375void mlx4_cmd_cleanup(struct mlx4_dev *dev);
381void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param); 376void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param);