static int cci_enumerate_feature_devs()

in dfl-pci.c [282:338]


static int cci_enumerate_feature_devs(struct pci_dev *pcidev)
{
	struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
	struct dfl_fpga_enum_info *info;
	struct dfl_fpga_cdev *cdev;
	int nvec, ret = 0;
	int *irq_table;

	/* allocate enumeration info via pci_dev */
	info = dfl_fpga_enum_info_alloc(&pcidev->dev);
	if (!info)
		return -ENOMEM;

	/* add irq info for enumeration if the device support irq */
	nvec = cci_pci_alloc_irq(pcidev);
	if (nvec < 0) {
		dev_err(&pcidev->dev, "Fail to alloc irq %d.\n", nvec);
		ret = nvec;
		goto enum_info_free_exit;
	} else if (nvec) {
		irq_table = cci_pci_create_irq_table(pcidev, nvec);
		if (!irq_table) {
			ret = -ENOMEM;
			goto irq_free_exit;
		}

		ret = dfl_fpga_enum_info_add_irq(info, nvec, irq_table);
		kfree(irq_table);
		if (ret)
			goto irq_free_exit;
	}

	ret = find_dfls_by_vsec(pcidev, info);
	if (ret == -ENODEV)
		ret = find_dfls_by_default(pcidev, info);

	if (ret)
		goto irq_free_exit;

	/* start enumeration with prepared enumeration information */
	cdev = dfl_fpga_feature_devs_enumerate(info);
	if (IS_ERR(cdev)) {
		dev_err(&pcidev->dev, "Enumeration failure\n");
		ret = PTR_ERR(cdev);
		goto irq_free_exit;
	}

	drvdata->cdev = cdev;

irq_free_exit:
	if (ret)
		cci_pci_free_irq(pcidev);
enum_info_free_exit:
	dfl_fpga_enum_info_free(info);

	return ret;
}