static int pci_sun4v_probe()

in kernel/pci_sun4v.c [1220:1326]


static int pci_sun4v_probe(struct platform_device *op)
{
	const struct linux_prom64_registers *regs;
	static int hvapi_negotiated = 0;
	struct pci_pbm_info *pbm;
	struct device_node *dp;
	struct iommu *iommu;
	struct atu *atu;
	u32 devhandle;
	int i, err = -ENODEV;
	static bool hv_atu = true;

	dp = op->dev.of_node;

	if (!hvapi_negotiated++) {
		for (i = 0; i < ARRAY_SIZE(vpci_versions); i++) {
			vpci_major = vpci_versions[i].major;
			vpci_minor = vpci_versions[i].minor;

			err = sun4v_hvapi_register(HV_GRP_PCI, vpci_major,
						   &vpci_minor);
			if (!err)
				break;
		}

		if (err) {
			pr_err(PFX "Could not register hvapi, err=%d\n", err);
			return err;
		}
		pr_info(PFX "Registered hvapi major[%lu] minor[%lu]\n",
			vpci_major, vpci_minor);

		err = sun4v_hvapi_register(HV_GRP_ATU, vatu_major, &vatu_minor);
		if (err) {
			/* don't return an error if we fail to register the
			 * ATU group, but ATU hcalls won't be available.
			 */
			hv_atu = false;
		} else {
			pr_info(PFX "Registered hvapi ATU major[%lu] minor[%lu]\n",
				vatu_major, vatu_minor);
		}

		dma_ops = &sun4v_dma_ops;
	}

	regs = of_get_property(dp, "reg", NULL);
	err = -ENODEV;
	if (!regs) {
		printk(KERN_ERR PFX "Could not find config registers\n");
		goto out_err;
	}
	devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;

	err = -ENOMEM;
	if (!iommu_batch_initialized) {
		for_each_possible_cpu(i) {
			unsigned long page = get_zeroed_page(GFP_KERNEL);

			if (!page)
				goto out_err;

			per_cpu(iommu_batch, i).pglist = (u64 *) page;
		}
		iommu_batch_initialized = 1;
	}

	pbm = kzalloc(sizeof(*pbm), GFP_KERNEL);
	if (!pbm) {
		printk(KERN_ERR PFX "Could not allocate pci_pbm_info\n");
		goto out_err;
	}

	iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL);
	if (!iommu) {
		printk(KERN_ERR PFX "Could not allocate pbm iommu\n");
		goto out_free_controller;
	}

	pbm->iommu = iommu;
	iommu->atu = NULL;
	if (hv_atu) {
		atu = kzalloc(sizeof(*atu), GFP_KERNEL);
		if (!atu)
			pr_err(PFX "Could not allocate atu\n");
		else
			iommu->atu = atu;
	}

	err = pci_sun4v_pbm_init(pbm, op, devhandle);
	if (err)
		goto out_free_iommu;

	dev_set_drvdata(&op->dev, pbm);

	return 0;

out_free_iommu:
	kfree(iommu->atu);
	kfree(pbm->iommu);

out_free_controller:
	kfree(pbm);

out_err:
	return err;
}