static int knav_queue_probe()

in ti/knav_qmss_queue.c [1755:1887]


static int knav_queue_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	struct device_node *qmgrs, *queue_pools, *regions, *pdsps;
	const struct of_device_id *match;
	struct device *dev = &pdev->dev;
	u32 temp[2];
	int ret;

	if (!node) {
		dev_err(dev, "device tree info unavailable\n");
		return -ENODEV;
	}

	kdev = devm_kzalloc(dev, sizeof(struct knav_device), GFP_KERNEL);
	if (!kdev) {
		dev_err(dev, "memory allocation failed\n");
		return -ENOMEM;
	}

	match = of_match_device(of_match_ptr(keystone_qmss_of_match), dev);
	if (match && match->data)
		kdev->version = QMSS_66AK2G;

	platform_set_drvdata(pdev, kdev);
	kdev->dev = dev;
	INIT_LIST_HEAD(&kdev->queue_ranges);
	INIT_LIST_HEAD(&kdev->qmgrs);
	INIT_LIST_HEAD(&kdev->pools);
	INIT_LIST_HEAD(&kdev->regions);
	INIT_LIST_HEAD(&kdev->pdsps);

	pm_runtime_enable(&pdev->dev);
	ret = pm_runtime_get_sync(&pdev->dev);
	if (ret < 0) {
		pm_runtime_put_noidle(&pdev->dev);
		dev_err(dev, "Failed to enable QMSS\n");
		return ret;
	}

	if (of_property_read_u32_array(node, "queue-range", temp, 2)) {
		dev_err(dev, "queue-range not specified\n");
		ret = -ENODEV;
		goto err;
	}
	kdev->base_id    = temp[0];
	kdev->num_queues = temp[1];

	/* Initialize queue managers using device tree configuration */
	qmgrs =  of_get_child_by_name(node, "qmgrs");
	if (!qmgrs) {
		dev_err(dev, "queue manager info not specified\n");
		ret = -ENODEV;
		goto err;
	}
	ret = knav_queue_init_qmgrs(kdev, qmgrs);
	of_node_put(qmgrs);
	if (ret)
		goto err;

	/* get pdsp configuration values from device tree */
	pdsps =  of_get_child_by_name(node, "pdsps");
	if (pdsps) {
		ret = knav_queue_init_pdsps(kdev, pdsps);
		if (ret)
			goto err;

		ret = knav_queue_start_pdsps(kdev);
		if (ret)
			goto err;
	}
	of_node_put(pdsps);

	/* get usable queue range values from device tree */
	queue_pools = of_get_child_by_name(node, "queue-pools");
	if (!queue_pools) {
		dev_err(dev, "queue-pools not specified\n");
		ret = -ENODEV;
		goto err;
	}
	ret = knav_setup_queue_pools(kdev, queue_pools);
	of_node_put(queue_pools);
	if (ret)
		goto err;

	ret = knav_get_link_ram(kdev, "linkram0", &kdev->link_rams[0]);
	if (ret) {
		dev_err(kdev->dev, "could not setup linking ram\n");
		goto err;
	}

	ret = knav_get_link_ram(kdev, "linkram1", &kdev->link_rams[1]);
	if (ret) {
		/*
		 * nothing really, we have one linking ram already, so we just
		 * live within our means
		 */
	}

	ret = knav_queue_setup_link_ram(kdev);
	if (ret)
		goto err;

	regions = of_get_child_by_name(node, "descriptor-regions");
	if (!regions) {
		dev_err(dev, "descriptor-regions not specified\n");
		ret = -ENODEV;
		goto err;
	}
	ret = knav_queue_setup_regions(kdev, regions);
	of_node_put(regions);
	if (ret)
		goto err;

	ret = knav_queue_init_queues(kdev);
	if (ret < 0) {
		dev_err(dev, "hwqueue initialization failed\n");
		goto err;
	}

	debugfs_create_file("qmss", S_IFREG | S_IRUGO, NULL, NULL,
			    &knav_queue_debug_fops);
	device_ready = true;
	return 0;

err:
	knav_queue_stop_pdsps(kdev);
	knav_queue_free_regions(kdev);
	knav_free_queue_ranges(kdev);
	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
	return ret;
}