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

📄 mthca_main.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
static int __devinit mthca_setup_hca(struct mthca_dev *dev){	int err;	u8 status;	MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock);	err = mthca_init_pd_table(dev);	if (err) {		mthca_err(dev, "Failed to initialize "			  "protection domain table, aborting.\n");		return err;	}	err = mthca_init_mr_table(dev);	if (err) {		mthca_err(dev, "Failed to initialize "			  "memory region table, aborting.\n");		goto err_pd_table_free;	}	err = mthca_pd_alloc(dev, &dev->driver_pd);	if (err) {		mthca_err(dev, "Failed to create driver PD, "			  "aborting.\n");		goto err_mr_table_free;	}	if (dev->hca_type == ARBEL_NATIVE) {		mthca_warn(dev, "Sorry, native MT25208 mode support is not done, "			   "aborting.\n");		err = -ENODEV;		goto err_pd_free;	}	err = mthca_init_eq_table(dev);	if (err) {		mthca_err(dev, "Failed to initialize "			  "event queue table, aborting.\n");		goto err_pd_free;	}	err = mthca_cmd_use_events(dev);	if (err) {		mthca_err(dev, "Failed to switch to event-driven "			  "firmware commands, aborting.\n");		goto err_eq_table_free;	}	err = mthca_NOP(dev, &status);	if (err || status) {		mthca_err(dev, "NOP command failed to generate interrupt, aborting.\n");		if (dev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X))			mthca_err(dev, "Try again with MSI/MSI-X disabled.\n");		else			mthca_err(dev, "BIOS or ACPI interrupt routing problem?\n");		goto err_cmd_poll;	} else		mthca_dbg(dev, "NOP command IRQ test passed\n");	err = mthca_init_cq_table(dev);	if (err) {		mthca_err(dev, "Failed to initialize "			  "completion queue table, aborting.\n");		goto err_cmd_poll;	}	err = mthca_init_qp_table(dev);	if (err) {		mthca_err(dev, "Failed to initialize "			  "queue pair table, aborting.\n");		goto err_cq_table_free;	}	err = mthca_init_av_table(dev);	if (err) {		mthca_err(dev, "Failed to initialize "			  "address vector table, aborting.\n");		goto err_qp_table_free;	}	err = mthca_init_mcg_table(dev);	if (err) {		mthca_err(dev, "Failed to initialize "			  "multicast group table, aborting.\n");		goto err_av_table_free;	}	return 0;err_av_table_free:	mthca_cleanup_av_table(dev);err_qp_table_free:	mthca_cleanup_qp_table(dev);err_cq_table_free:	mthca_cleanup_cq_table(dev);err_cmd_poll:	mthca_cmd_use_polling(dev);err_eq_table_free:	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);	return err;}static int __devinit mthca_request_regions(struct pci_dev *pdev,					   int ddr_hidden){	int err;	/*	 * We request our first BAR in two chunks, since the MSI-X	 * vector table is right in the middle.	 *	 * This is why we can't just use pci_request_regions() -- if	 * we did then setting up MSI-X would fail, since the PCI core	 * wants to do request_mem_region on the MSI-X vector table.	 */	if (!request_mem_region(pci_resource_start(pdev, 0) +				MTHCA_HCR_BASE,				MTHCA_HCR_SIZE,				DRV_NAME)) {		err = -EBUSY;		goto err_hcr_failed;	}	if (!request_mem_region(pci_resource_start(pdev, 0) +				MTHCA_ECR_BASE,				MTHCA_MAP_ECR_SIZE,				DRV_NAME)) {		err = -EBUSY;		goto err_ecr_failed;	}	if (!request_mem_region(pci_resource_start(pdev, 0) +				MTHCA_CLR_INT_BASE,				MTHCA_CLR_INT_SIZE,				DRV_NAME)) {		err = -EBUSY;		goto err_int_failed;	}	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_CLR_INT_BASE,			   MTHCA_CLR_INT_SIZE);err_int_failed:	release_mem_region(pci_resource_start(pdev, 0) +			   MTHCA_ECR_BASE,			   MTHCA_MAP_ECR_SIZE);err_ecr_failed:	release_mem_region(pci_resource_start(pdev, 0) +			   MTHCA_HCR_BASE,			   MTHCA_HCR_SIZE);err_hcr_failed:	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_CLR_INT_BASE,			   MTHCA_CLR_INT_SIZE);	release_mem_region(pci_resource_start(pdev, 0) +			   MTHCA_ECR_BASE,			   MTHCA_MAP_ECR_SIZE);	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;}static void mthca_close_hca(struct mthca_dev *mdev){	u8 status;	mthca_CLOSE_HCA(mdev, 0, &status);	if (mdev->hca_type == ARBEL_NATIVE) {		mthca_free_icm_table(mdev, mdev->cq_table.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);		mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);		mthca_unmap_eq_icm(mdev);		mthca_UNMAP_ICM_AUX(mdev, &status);		mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);		mthca_UNMAP_FA(mdev, &status);		mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);		if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))			mthca_DISABLE_LAM(mdev, &status);	} else		mthca_SYS_DIS(mdev, &status);}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;	unsigned long mthca_base;	struct mthca_dev *mdev;	if (!mthca_version_printed) {		printk(KERN_INFO "%s", mthca_version);		++mthca_version_printed;	}	printk(KERN_INFO PFX "Initializing %s (%s)\n",	       pci_pretty_name(pdev), pci_name(pdev));	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.");		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.");		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;	mdev->hca_type = id->driver_data;	if (ddr_hidden)		mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN;	/*	 * 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;	sema_init(&mdev->cmd.hcr_sem, 1);	sema_init(&mdev->cmd.poll_sem, 1);	mdev->cmd.use_events = 0;	mthca_base = pci_resource_start(pdev, 0);	mdev->hcr = ioremap(mthca_base + MTHCA_HCR_BASE, MTHCA_HCR_SIZE);	if (!mdev->hcr) {		mthca_err(mdev, "Couldn't map command register, "			  "aborting.\n");		err = -ENOMEM;		goto err_free_dev;	}	mdev->clr_base = ioremap(mthca_base + MTHCA_CLR_INT_BASE,				 MTHCA_CLR_INT_SIZE);	if (!mdev->clr_base) {		mthca_err(mdev, "Couldn't map interrupt clear register, "			  "aborting.\n");		err = -ENOMEM;		goto err_iounmap;	}	mdev->ecr_base = ioremap(mthca_base + MTHCA_ECR_BASE,				 MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE);	if (!mdev->ecr_base) {		mthca_err(mdev, "Couldn't map ecr register, "			  "aborting.\n");		err = -ENOMEM;		goto err_iounmap_clr;	}	mthca_base = pci_resource_start(pdev, 2);	mdev->kar = ioremap(mthca_base + PAGE_SIZE * MTHCA_KAR_PAGE, PAGE_SIZE);	if (!mdev->kar) {		mthca_err(mdev, "Couldn't map kernel access region, "			  "aborting.\n");		err = -ENOMEM;		goto err_iounmap_ecr;	}	err = mthca_tune_pci(mdev);	if (err)		goto err_iounmap_kar;	err = mthca_init_hca(mdev);	if (err)		goto err_iounmap_kar;	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_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);err_close:	mthca_close_hca(mdev);err_iounmap_kar:	iounmap(mdev->kar);err_iounmap_ecr:	iounmap(mdev->ecr_base);err_iounmap_clr:	iounmap(mdev->clr_base);err_iounmap:	iounmap(mdev->hcr);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_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_close_hca(mdev);		iounmap(mdev->hcr);		iounmap(mdev->ecr_base);		iounmap(mdev->clr_base);		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 },	{ 0, }};MODULE_DEVICE_TABLE(pci, mthca_pci_table);static struct pci_driver mthca_driver = {	.name		= "ib_mthca",	.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 + -