]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/mlx4/main.c
Merge commit 'kumar/kumar-next' into next
[linux-2.6-omap-h63xx.git] / drivers / net / mlx4 / main.c
index 468921b8f4b68a047abdf2f247e4a1c3e0ed5d41..710c79e7a2db244b567b485db51abf0978f04253 100644 (file)
@@ -421,9 +421,7 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base,
                                  ((u64) (MLX4_CMPT_TYPE_EQ *
                                          cmpt_entry_sz) << MLX4_CMPT_SHIFT),
                                  cmpt_entry_sz,
-                                 roundup_pow_of_two(MLX4_NUM_EQ +
-                                                    dev->caps.reserved_eqs),
-                                 MLX4_NUM_EQ + dev->caps.reserved_eqs, 0, 0);
+                                 dev->caps.num_eqs, dev->caps.num_eqs, 0, 0);
        if (err)
                goto err_cq;
 
@@ -753,6 +751,7 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
        struct mlx4_priv *priv = mlx4_priv(dev);
        int err;
        int port;
+       __be32 ib_port_default_caps;
 
        err = mlx4_init_uar_table(dev);
        if (err) {
@@ -809,12 +808,12 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
                if (dev->flags & MLX4_FLAG_MSI_X) {
                        mlx4_warn(dev, "NOP command failed to generate MSI-X "
                                  "interrupt IRQ %d).\n",
-                                 priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
+                                 priv->eq_table.eq[dev->caps.num_comp_vectors].irq);
                        mlx4_warn(dev, "Trying again without MSI-X.\n");
                } else {
                        mlx4_err(dev, "NOP command failed to generate interrupt "
                                 "(IRQ %d), aborting.\n",
-                                priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
+                                priv->eq_table.eq[dev->caps.num_comp_vectors].irq);
                        mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n");
                }
 
@@ -852,6 +851,13 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
        }
 
        for (port = 1; port <= dev->caps.num_ports; port++) {
+               ib_port_default_caps = 0;
+               err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps);
+               if (err)
+                       mlx4_warn(dev, "failed to get port %d default "
+                                 "ib capabilities (%d). Continuing with "
+                                 "caps = 0\n", port, err);
+               dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
                err = mlx4_SET_PORT(dev, port);
                if (err) {
                        mlx4_err(dev, "Failed to set port %d, aborting\n",
@@ -900,31 +906,50 @@ err_uar_table_free:
 static void mlx4_enable_msi_x(struct mlx4_dev *dev)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
-       struct msix_entry entries[MLX4_NUM_EQ];
+       struct msix_entry *entries;
+       int nreq;
        int err;
        int i;
 
        if (msi_x) {
-               for (i = 0; i < MLX4_NUM_EQ; ++i)
+               nreq = min(dev->caps.num_eqs - dev->caps.reserved_eqs,
+                          num_possible_cpus() + 1);
+               entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
+               if (!entries)
+                       goto no_msi;
+
+               for (i = 0; i < nreq; ++i)
                        entries[i].entry = i;
 
-               err = pci_enable_msix(dev->pdev, entries, ARRAY_SIZE(entries));
+       retry:
+               err = pci_enable_msix(dev->pdev, entries, nreq);
                if (err) {
-                       if (err > 0)
-                               mlx4_info(dev, "Only %d MSI-X vectors available, "
-                                         "not using MSI-X\n", err);
+                       /* Try again if at least 2 vectors are available */
+                       if (err > 1) {
+                               mlx4_info(dev, "Requested %d vectors, "
+                                         "but only %d MSI-X vectors available, "
+                                         "trying again\n", nreq, err);
+                               nreq = err;
+                               goto retry;
+                       }
+
                        goto no_msi;
                }
 
-               for (i = 0; i < MLX4_NUM_EQ; ++i)
+               dev->caps.num_comp_vectors = nreq - 1;
+               for (i = 0; i < nreq; ++i)
                        priv->eq_table.eq[i].irq = entries[i].vector;
 
                dev->flags |= MLX4_FLAG_MSI_X;
+
+               kfree(entries);
                return;
        }
 
 no_msi:
-       for (i = 0; i < MLX4_NUM_EQ; ++i)
+       dev->caps.num_comp_vectors = 1;
+
+       for (i = 0; i < 2; ++i)
                priv->eq_table.eq[i].irq = dev->pdev->irq;
 }
 
@@ -1066,6 +1091,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        if (err)
                goto err_cmd;
 
+       err = mlx4_alloc_eq_table(dev);
+       if (err)
+               goto err_close;
+
        mlx4_enable_msi_x(dev);
 
        err = mlx4_setup_hca(dev);
@@ -1076,7 +1105,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        if (err)
-               goto err_close;
+               goto err_free_eq;
 
        for (port = 1; port <= dev->caps.num_ports; port++) {
                err = mlx4_init_port_info(dev, port);
@@ -1106,6 +1135,9 @@ err_port:
        mlx4_cleanup_pd_table(dev);
        mlx4_cleanup_uar_table(dev);
 
+err_free_eq:
+       mlx4_free_eq_table(dev);
+
 err_close:
        if (dev->flags & MLX4_FLAG_MSI_X)
                pci_disable_msix(pdev);
@@ -1169,6 +1201,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
                iounmap(priv->kar);
                mlx4_uar_free(dev, &priv->driver_uar);
                mlx4_cleanup_uar_table(dev);
+               mlx4_free_eq_table(dev);
                mlx4_close_hca(dev);
                mlx4_cmd_cleanup(dev);