diff options
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_main.c')
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_main.c | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 014369626f6..a1fa326dceb 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -103,7 +103,7 @@ static int __devinit mthca_tune_pci(struct mthca_dev *mdev) "aborting.\n"); return -ENODEV; } - } else if (mdev->hca_type == TAVOR) + } else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE)) mthca_info(mdev, "No PCI-X capability, not setting RBC.\n"); cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP); @@ -119,8 +119,7 @@ static int __devinit mthca_tune_pci(struct mthca_dev *mdev) "register, aborting.\n"); return -ENODEV; } - } else if (mdev->hca_type == ARBEL_NATIVE || - mdev->hca_type == ARBEL_COMPAT) + } else if (mdev->mthca_flags & MTHCA_FLAG_PCIE) mthca_info(mdev, "No PCI Express capability, " "not setting Max Read Request Size.\n"); @@ -438,7 +437,7 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev, if (!mdev->qp_table.rdb_table) { mthca_err(mdev, "Failed to map RDB context memory, aborting\n"); err = -ENOMEM; - goto err_unmap_eqp; + goto err_unmap_rdb; } mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base, @@ -593,6 +592,7 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev) err_free_icm: mthca_free_icm_table(mdev, mdev->cq_table.table); + mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); mthca_free_icm_table(mdev, mdev->qp_table.qp_table); mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); @@ -851,6 +851,7 @@ static void mthca_close_hca(struct mthca_dev *mdev) if (mthca_is_memfree(mdev)) { mthca_free_icm_table(mdev, mdev->cq_table.table); + mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); mthca_free_icm_table(mdev, mdev->qp_table.qp_table); mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); @@ -869,11 +870,32 @@ static void mthca_close_hca(struct mthca_dev *mdev) mthca_SYS_DIS(mdev, &status); } +/* Types of supported HCA */ +enum { + TAVOR, /* MT23108 */ + ARBEL_COMPAT, /* MT25208 in Tavor compat mode */ + ARBEL_NATIVE, /* MT25208 with extended features */ + SINAI /* MT25204 */ +}; + +#define MTHCA_FW_VER(major, minor, subminor) \ + (((u64) (major) << 32) | ((u64) (minor) << 16) | (u64) (subminor)) + +static struct { + u64 latest_fw; + int is_memfree; + int is_pcie; +} mthca_hca_table[] = { + [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 2), .is_memfree = 0, .is_pcie = 0 }, + [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 6, 2), .is_memfree = 0, .is_pcie = 1 }, + [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 0, 1), .is_memfree = 1, .is_pcie = 1 }, + [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), .is_memfree = 1, .is_pcie = 1 } +}; + static int __devinit mthca_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static int mthca_version_printed = 0; - static int mthca_memfree_warned = 0; int ddr_hidden = 0; int err; struct mthca_dev *mdev; @@ -886,6 +908,12 @@ static int __devinit mthca_init_one(struct pci_dev *pdev, printk(KERN_INFO PFX "Initializing %s (%s)\n", pci_pretty_name(pdev), pci_name(pdev)); + if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) { + printk(KERN_ERR PFX "%s (%s) has invalid driver data %lx\n", + pci_pretty_name(pdev), pci_name(pdev), id->driver_data); + return -ENODEV; + } + err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "Cannot enable PCI device, " @@ -950,15 +978,14 @@ static int __devinit mthca_init_one(struct pci_dev *pdev, goto err_free_res; } - mdev->pdev = pdev; - mdev->hca_type = id->driver_data; - - if (mthca_is_memfree(mdev) && !mthca_memfree_warned++) - mthca_warn(mdev, "Warning: native MT25208 mode support is incomplete. " - "Your HCA may not work properly.\n"); + mdev->pdev = pdev; if (ddr_hidden) mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN; + if (mthca_hca_table[id->driver_data].is_memfree) + mdev->mthca_flags |= MTHCA_FLAG_MEMFREE; + if (mthca_hca_table[id->driver_data].is_pcie) + mdev->mthca_flags |= MTHCA_FLAG_PCIE; /* * Now reset the HCA before we touch the PCI capabilities or @@ -997,6 +1024,16 @@ static int __devinit mthca_init_one(struct pci_dev *pdev, if (err) goto err_iounmap; + if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) { + mthca_warn(mdev, "HCA FW version %x.%x.%x is old (%x.%x.%x is current).\n", + (int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff, + (int) (mdev->fw_ver & 0xffff), + (int) (mthca_hca_table[id->driver_data].latest_fw >> 32), + (int) (mthca_hca_table[id->driver_data].latest_fw >> 16) & 0xffff, + (int) (mthca_hca_table[id->driver_data].latest_fw & 0xffff)); + mthca_warn(mdev, "If you have problems, try updating your HCA FW.\n"); + } + err = mthca_setup_hca(mdev); if (err) goto err_close; @@ -1112,6 +1149,14 @@ static struct pci_device_id mthca_pci_table[] = { .driver_data = ARBEL_NATIVE }, { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_ARBEL), .driver_data = ARBEL_NATIVE }, + { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_SINAI), + .driver_data = SINAI }, + { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_SINAI), + .driver_data = SINAI }, + { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_SINAI_OLD), + .driver_data = SINAI }, + { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_SINAI_OLD), + .driver_data = SINAI }, { 0, } }; |