⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mthca_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	mthca_cleanup_eq_table(dev);err_pd_free:	mthca_pd_free(dev, &dev->driver_pd);err_mr_table_free:	mthca_cleanup_mr_table(dev);err_pd_table_free:	mthca_cleanup_pd_table(dev);err_kar_unmap:	iounmap(dev->kar);err_uar_free:	mthca_uar_free(dev, &dev->driver_uar);err_uar_table_free:	mthca_cleanup_uar_table(dev);	return err;}static int __devinit mthca_request_regions(struct pci_dev *pdev,					   int ddr_hidden){	int err;	/*	 * We can't just use pci_request_regions() because the MSI-X	 * table is right in the middle of the first BAR.  If we did	 * pci_request_region and grab all of the first BAR, then	 * setting up MSI-X would fail, since the PCI core wants to do	 * request_mem_region on the MSI-X vector table.	 *	 * So just request what we need right now, and request any	 * other regions we need when setting up EQs.	 */	if (!request_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,				MTHCA_HCR_SIZE, DRV_NAME))		return -EBUSY;	err = pci_request_region(pdev, 2, DRV_NAME);	if (err)		goto err_bar2_failed;	if (!ddr_hidden) {		err = pci_request_region(pdev, 4, DRV_NAME);		if (err)			goto err_bar4_failed;	}	return 0;err_bar4_failed:	pci_release_region(pdev, 2);err_bar2_failed:	release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,			   MTHCA_HCR_SIZE);	return err;}static void mthca_release_regions(struct pci_dev *pdev,				  int ddr_hidden){	if (!ddr_hidden)		pci_release_region(pdev, 4);	pci_release_region(pdev, 2);	release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,			   MTHCA_HCR_SIZE);}static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev){	struct msix_entry entries[3];	int err;	entries[0].entry = 0;	entries[1].entry = 1;	entries[2].entry = 2;	err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries));	if (err) {		if (err > 0)			mthca_info(mdev, "Only %d MSI-X vectors available, "				   "not using MSI-X\n", err);		return err;	}	mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector = entries[0].vector;	mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector = entries[1].vector;	mdev->eq_table.eq[MTHCA_EQ_CMD  ].msi_x_vector = entries[2].vector;	return 0;}/* 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, 3), .is_memfree = 0, .is_pcie = 0 },	[ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), .is_memfree = 0, .is_pcie = 1 },	[ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .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;	int ddr_hidden = 0;	int err;	struct mthca_dev *mdev;	if (!mthca_version_printed) {		printk(KERN_INFO "%s", mthca_version);		++mthca_version_printed;	}	printk(KERN_INFO PFX "Initializing %s\n",	       pci_name(pdev));	if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) {		printk(KERN_ERR PFX "%s has invalid driver data %lx\n",		       pci_name(pdev), id->driver_data);		return -ENODEV;	}	err = pci_enable_device(pdev);	if (err) {		dev_err(&pdev->dev, "Cannot enable PCI device, "			"aborting.\n");		return err;	}	/*	 * Check for BARs.  We expect 0: 1MB, 2: 8MB, 4: DDR (may not	 * be present)	 */	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||	    pci_resource_len(pdev, 0) != 1 << 20) {		dev_err(&pdev->dev, "Missing DCS, aborting.\n");		err = -ENODEV;		goto err_disable_pdev;	}	if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) ||	    pci_resource_len(pdev, 2) != 1 << 23) {		dev_err(&pdev->dev, "Missing UAR, aborting.\n");		err = -ENODEV;		goto err_disable_pdev;	}	if (!(pci_resource_flags(pdev, 4) & IORESOURCE_MEM))		ddr_hidden = 1;	err = mthca_request_regions(pdev, ddr_hidden);	if (err) {		dev_err(&pdev->dev, "Cannot obtain PCI resources, "			"aborting.\n");		goto err_disable_pdev;	}	pci_set_master(pdev);	err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);	if (err) {		dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n");		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);		if (err) {			dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n");			goto err_free_res;		}	}	err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);	if (err) {		dev_warn(&pdev->dev, "Warning: couldn't set 64-bit "			 "consistent PCI DMA mask.\n");		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);		if (err) {			dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, "				"aborting.\n");			goto err_free_res;		}	}	mdev = (struct mthca_dev *) ib_alloc_device(sizeof *mdev);	if (!mdev) {		dev_err(&pdev->dev, "Device struct alloc failed, "			"aborting.\n");		err = -ENOMEM;		goto err_free_res;	}	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	 * attempt a firmware command, since a boot ROM may have left	 * the HCA in an undefined state.	 */	err = mthca_reset(mdev);	if (err) {		mthca_err(mdev, "Failed to reset HCA, aborting.\n");		goto err_free_dev;	}	if (msi_x && !mthca_enable_msi_x(mdev))		mdev->mthca_flags |= MTHCA_FLAG_MSI_X;	if (msi && !(mdev->mthca_flags & MTHCA_FLAG_MSI_X) &&	    !pci_enable_msi(pdev))		mdev->mthca_flags |= MTHCA_FLAG_MSI;	if (mthca_cmd_init(mdev)) {		mthca_err(mdev, "Failed to init command interface, aborting.\n");		goto err_free_dev;	}	err = mthca_tune_pci(mdev);	if (err)		goto err_cmd;	err = mthca_init_hca(mdev);	if (err)		goto err_cmd;	if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) {		mthca_warn(mdev, "HCA FW version %d.%d.%d is old (%d.%d.%d 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;	err = mthca_register_device(mdev);	if (err)		goto err_cleanup;	err = mthca_create_agents(mdev);	if (err)		goto err_unregister;	pci_set_drvdata(pdev, mdev);	return 0;err_unregister:	mthca_unregister_device(mdev);err_cleanup:	mthca_cleanup_mcg_table(mdev);	mthca_cleanup_av_table(mdev);	mthca_cleanup_qp_table(mdev);	mthca_cleanup_srq_table(mdev);	mthca_cleanup_cq_table(mdev);	mthca_cmd_use_polling(mdev);	mthca_cleanup_eq_table(mdev);	mthca_pd_free(mdev, &mdev->driver_pd);	mthca_cleanup_mr_table(mdev);	mthca_cleanup_pd_table(mdev);	mthca_cleanup_uar_table(mdev);err_close:	mthca_close_hca(mdev);err_cmd:	mthca_cmd_cleanup(mdev);err_free_dev:	if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)		pci_disable_msix(pdev);	if (mdev->mthca_flags & MTHCA_FLAG_MSI)		pci_disable_msi(pdev);	ib_dealloc_device(&mdev->ib_dev);err_free_res:	mthca_release_regions(pdev, ddr_hidden);err_disable_pdev:	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);	return err;}static void __devexit mthca_remove_one(struct pci_dev *pdev){	struct mthca_dev *mdev = pci_get_drvdata(pdev);	u8 status;	int p;	if (mdev) {		mthca_free_agents(mdev);		mthca_unregister_device(mdev);		for (p = 1; p <= mdev->limits.num_ports; ++p)			mthca_CLOSE_IB(mdev, p, &status);		mthca_cleanup_mcg_table(mdev);		mthca_cleanup_av_table(mdev);		mthca_cleanup_qp_table(mdev);		mthca_cleanup_srq_table(mdev);		mthca_cleanup_cq_table(mdev);		mthca_cmd_use_polling(mdev);		mthca_cleanup_eq_table(mdev);		mthca_pd_free(mdev, &mdev->driver_pd);		mthca_cleanup_mr_table(mdev);		mthca_cleanup_pd_table(mdev);		iounmap(mdev->kar);		mthca_uar_free(mdev, &mdev->driver_uar);		mthca_cleanup_uar_table(mdev);		mthca_close_hca(mdev);		mthca_cmd_cleanup(mdev);		if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)			pci_disable_msix(pdev);		if (mdev->mthca_flags & MTHCA_FLAG_MSI)			pci_disable_msi(pdev);		ib_dealloc_device(&mdev->ib_dev);		mthca_release_regions(pdev, mdev->mthca_flags &				      MTHCA_FLAG_DDR_HIDDEN);		pci_disable_device(pdev);		pci_set_drvdata(pdev, NULL);	}}static struct pci_device_id mthca_pci_table[] = {	{ PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_TAVOR),	  .driver_data = TAVOR },	{ PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_TAVOR),	  .driver_data = TAVOR },	{ PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT),	  .driver_data = ARBEL_COMPAT },	{ PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT),	  .driver_data = ARBEL_COMPAT },	{ PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_ARBEL),	  .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, }};MODULE_DEVICE_TABLE(pci, mthca_pci_table);static struct pci_driver mthca_driver = {	.name		= DRV_NAME,	.id_table	= mthca_pci_table,	.probe		= mthca_init_one,	.remove		= __devexit_p(mthca_remove_one)};static int __init mthca_init(void){	int ret;	ret = pci_register_driver(&mthca_driver);	return ret < 0 ? ret : 0;}static void __exit mthca_cleanup(void){	pci_unregister_driver(&mthca_driver);}module_init(mthca_init);module_exit(mthca_cleanup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -