static int otx_cptvf_probe()

in marvell/octeontx/otx_cptvf_main.c [781:928]


static int otx_cptvf_probe(struct pci_dev *pdev,
			   const struct pci_device_id *ent)
{
	struct device *dev = &pdev->dev;
	struct otx_cptvf *cptvf;
	int err;

	cptvf = devm_kzalloc(dev, sizeof(*cptvf), GFP_KERNEL);
	if (!cptvf)
		return -ENOMEM;

	pci_set_drvdata(pdev, cptvf);
	cptvf->pdev = pdev;

	err = pci_enable_device(pdev);
	if (err) {
		dev_err(dev, "Failed to enable PCI device\n");
		goto clear_drvdata;
	}
	err = pci_request_regions(pdev, DRV_NAME);
	if (err) {
		dev_err(dev, "PCI request regions failed 0x%x\n", err);
		goto disable_device;
	}
	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48));
	if (err) {
		dev_err(dev, "Unable to get usable 48-bit DMA configuration\n");
		goto release_regions;
	}

	/* MAP PF's configuration registers */
	cptvf->reg_base = pci_iomap(pdev, OTX_CPT_VF_PCI_CFG_BAR, 0);
	if (!cptvf->reg_base) {
		dev_err(dev, "Cannot map config register space, aborting\n");
		err = -ENOMEM;
		goto release_regions;
	}

	cptvf->node = dev_to_node(&pdev->dev);
	err = pci_alloc_irq_vectors(pdev, OTX_CPT_VF_MSIX_VECTORS,
				    OTX_CPT_VF_MSIX_VECTORS, PCI_IRQ_MSIX);
	if (err < 0) {
		dev_err(dev, "Request for #%d msix vectors failed\n",
			OTX_CPT_VF_MSIX_VECTORS);
		goto unmap_region;
	}

	err = request_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_MISC),
			  cptvf_misc_intr_handler, 0, "CPT VF misc intr",
			  cptvf);
	if (err) {
		dev_err(dev, "Failed to request misc irq\n");
		goto free_vectors;
	}

	/* Enable mailbox interrupt */
	cptvf_enable_mbox_interrupts(cptvf);
	cptvf_enable_swerr_interrupts(cptvf);

	/* Check cpt pf status, gets chip ID / device Id from PF if ready */
	err = otx_cptvf_check_pf_ready(cptvf);
	if (err)
		goto free_misc_irq;

	/* CPT VF software resources initialization */
	cptvf->cqinfo.qchunksize = OTX_CPT_CMD_QCHUNK_SIZE;
	err = cptvf_sw_init(cptvf, OTX_CPT_CMD_QLEN, OTX_CPT_NUM_QS_PER_VF);
	if (err) {
		dev_err(dev, "cptvf_sw_init() failed\n");
		goto free_misc_irq;
	}
	/* Convey VQ LEN to PF */
	err = otx_cptvf_send_vq_size_msg(cptvf);
	if (err)
		goto sw_cleanup;

	/* CPT VF device initialization */
	cptvf_device_init(cptvf);
	/* Send msg to PF to assign currnet Q to required group */
	err = otx_cptvf_send_vf_to_grp_msg(cptvf, cptvf->vfgrp);
	if (err)
		goto sw_cleanup;

	cptvf->priority = 1;
	err = otx_cptvf_send_vf_priority_msg(cptvf);
	if (err)
		goto sw_cleanup;

	err = request_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_DONE),
			  cptvf_done_intr_handler, 0, "CPT VF done intr",
			  cptvf);
	if (err) {
		dev_err(dev, "Failed to request done irq\n");
		goto free_done_irq;
	}

	/* Enable done interrupt */
	cptvf_enable_done_interrupts(cptvf);

	/* Set irq affinity masks */
	cptvf_set_irq_affinity(cptvf, CPT_VF_INT_VEC_E_MISC);
	cptvf_set_irq_affinity(cptvf, CPT_VF_INT_VEC_E_DONE);

	err = otx_cptvf_send_vf_up(cptvf);
	if (err)
		goto free_irq_affinity;

	/* Initialize algorithms and set ops */
	err = otx_cpt_crypto_init(pdev, THIS_MODULE,
		    cptvf->vftype == OTX_CPT_SE_TYPES ? OTX_CPT_SE : OTX_CPT_AE,
		    cptvf->vftype, 1, cptvf->num_vfs);
	if (err) {
		dev_err(dev, "Failed to register crypto algs\n");
		goto free_irq_affinity;
	}

	err = sysfs_create_group(&dev->kobj, &otx_cptvf_sysfs_group);
	if (err) {
		dev_err(dev, "Creating sysfs entries failed\n");
		goto crypto_exit;
	}

	return 0;

crypto_exit:
	otx_cpt_crypto_exit(pdev, THIS_MODULE, cptvf->vftype);
free_irq_affinity:
	cptvf_free_irq_affinity(cptvf, CPT_VF_INT_VEC_E_DONE);
	cptvf_free_irq_affinity(cptvf, CPT_VF_INT_VEC_E_MISC);
free_done_irq:
	free_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_DONE), cptvf);
sw_cleanup:
	cptvf_sw_cleanup(cptvf);
free_misc_irq:
	free_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_MISC), cptvf);
free_vectors:
	pci_free_irq_vectors(cptvf->pdev);
unmap_region:
	pci_iounmap(pdev, cptvf->reg_base);
release_regions:
	pci_release_regions(pdev);
disable_device:
	pci_disable_device(pdev);
clear_drvdata:
	pci_set_drvdata(pdev, NULL);

	return err;
}