static int tegra186_bpmp_init()

in tegra/bpmp-tegra186.c [163:259]


static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
{
	struct tegra186_bpmp *priv;
	unsigned int i;
	int err;

	priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	bpmp->priv = priv;
	priv->parent = bpmp;

	priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
	if (!priv->tx.pool) {
		dev_err(bpmp->dev, "TX shmem pool not found\n");
		return -EPROBE_DEFER;
	}

	priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
	if (!priv->tx.virt) {
		dev_err(bpmp->dev, "failed to allocate from TX pool\n");
		return -ENOMEM;
	}

	priv->rx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 1);
	if (!priv->rx.pool) {
		dev_err(bpmp->dev, "RX shmem pool not found\n");
		err = -EPROBE_DEFER;
		goto free_tx;
	}

	priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
	if (!priv->rx.virt) {
		dev_err(bpmp->dev, "failed to allocate from RX pool\n");
		err = -ENOMEM;
		goto free_tx;
	}

	err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
					 bpmp->soc->channels.cpu_tx.offset);
	if (err < 0)
		goto free_rx;

	err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
					 bpmp->soc->channels.cpu_rx.offset);
	if (err < 0)
		goto cleanup_tx_channel;

	for (i = 0; i < bpmp->threaded.count; i++) {
		unsigned int index = bpmp->soc->channels.thread.offset + i;

		err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
						 bpmp, index);
		if (err < 0)
			goto cleanup_channels;
	}

	/* mbox registration */
	priv->mbox.client.dev = bpmp->dev;
	priv->mbox.client.rx_callback = mbox_handle_rx;
	priv->mbox.client.tx_block = false;
	priv->mbox.client.knows_txdone = false;

	priv->mbox.channel = mbox_request_channel(&priv->mbox.client, 0);
	if (IS_ERR(priv->mbox.channel)) {
		err = PTR_ERR(priv->mbox.channel);
		dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
		goto cleanup_channels;
	}

	tegra186_bpmp_channel_reset(bpmp->tx_channel);
	tegra186_bpmp_channel_reset(bpmp->rx_channel);

	for (i = 0; i < bpmp->threaded.count; i++)
		tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);

	return 0;

cleanup_channels:
	for (i = 0; i < bpmp->threaded.count; i++) {
		if (!bpmp->threaded_channels[i].bpmp)
			continue;

		tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
	}

	tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
cleanup_tx_channel:
	tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
free_rx:
	gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
free_tx:
	gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);

	return err;
}