Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0994465 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'tegra-for-4.17-firmware' of...

Merge tag 'tegra-for-4.17-firmware' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers

Pull "firmware: Changes for v4.17-rc1" from Thierry Reding:

These changes are rather small, with just a fix for a return value check
and some preparatory work for Tegra194 BPMP support.

* tag 'tegra-for-4.17-firmware' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  firmware: tegra: adjust tested variable
  firmware: tegra: Simplify channel management
parents 3bea9c58 1320f768
Loading
Loading
Loading
Loading
+65 −79
Original line number Original line Diff line number Diff line
@@ -70,57 +70,20 @@ void tegra_bpmp_put(struct tegra_bpmp *bpmp)
}
}
EXPORT_SYMBOL_GPL(tegra_bpmp_put);
EXPORT_SYMBOL_GPL(tegra_bpmp_put);


static int tegra_bpmp_channel_get_index(struct tegra_bpmp_channel *channel)
{
	return channel - channel->bpmp->channels;
}

static int
static int
tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel)
tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel)
{
{
	struct tegra_bpmp *bpmp = channel->bpmp;
	struct tegra_bpmp *bpmp = channel->bpmp;
	unsigned int offset, count;
	unsigned int count;
	int index;
	int index;


	offset = bpmp->soc->channels.thread.offset;
	count = bpmp->soc->channels.thread.count;
	count = bpmp->soc->channels.thread.count;


	index = tegra_bpmp_channel_get_index(channel);
	index = channel - channel->bpmp->threaded_channels;
	if (index < 0)
	if (index < 0 || index >= count)
		return index;

	if (index < offset || index >= offset + count)
		return -EINVAL;
		return -EINVAL;


	return index - offset;
	return index;
}

static struct tegra_bpmp_channel *
tegra_bpmp_channel_get_thread(struct tegra_bpmp *bpmp, unsigned int index)
{
	unsigned int offset = bpmp->soc->channels.thread.offset;
	unsigned int count = bpmp->soc->channels.thread.count;

	if (index >= count)
		return NULL;

	return &bpmp->channels[offset + index];
}

static struct tegra_bpmp_channel *
tegra_bpmp_channel_get_tx(struct tegra_bpmp *bpmp)
{
	unsigned int offset = bpmp->soc->channels.cpu_tx.offset;

	return &bpmp->channels[offset + smp_processor_id()];
}

static struct tegra_bpmp_channel *
tegra_bpmp_channel_get_rx(struct tegra_bpmp *bpmp)
{
	unsigned int offset = bpmp->soc->channels.cpu_rx.offset;

	return &bpmp->channels[offset];
}
}


static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
@@ -271,11 +234,7 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,
		goto unlock;
		goto unlock;
	}
	}


	channel = tegra_bpmp_channel_get_thread(bpmp, index);
	channel = &bpmp->threaded_channels[index];
	if (!channel) {
		err = -EINVAL;
		goto unlock;
	}


	if (!tegra_bpmp_master_free(channel)) {
	if (!tegra_bpmp_master_free(channel)) {
		err = -EBUSY;
		err = -EBUSY;
@@ -328,12 +287,18 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
	if (!tegra_bpmp_message_valid(msg))
	if (!tegra_bpmp_message_valid(msg))
		return -EINVAL;
		return -EINVAL;


	channel = tegra_bpmp_channel_get_tx(bpmp);
	channel = bpmp->tx_channel;

	spin_lock(&bpmp->atomic_tx_lock);


	err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK,
	err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK,
				       msg->tx.data, msg->tx.size);
				       msg->tx.data, msg->tx.size);
	if (err < 0)
	if (err < 0) {
		spin_unlock(&bpmp->atomic_tx_lock);
		return err;
		return err;
	}

	spin_unlock(&bpmp->atomic_tx_lock);


	err = mbox_send_message(bpmp->mbox.channel, NULL);
	err = mbox_send_message(bpmp->mbox.channel, NULL);
	if (err < 0)
	if (err < 0)
@@ -607,7 +572,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
	unsigned int i, count;
	unsigned int i, count;
	unsigned long *busy;
	unsigned long *busy;


	channel = tegra_bpmp_channel_get_rx(bpmp);
	channel = bpmp->rx_channel;
	count = bpmp->soc->channels.thread.count;
	count = bpmp->soc->channels.thread.count;
	busy = bpmp->threaded.busy;
	busy = bpmp->threaded.busy;


@@ -619,9 +584,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
	for_each_set_bit(i, busy, count) {
	for_each_set_bit(i, busy, count) {
		struct tegra_bpmp_channel *channel;
		struct tegra_bpmp_channel *channel;


		channel = tegra_bpmp_channel_get_thread(bpmp, i);
		channel = &bpmp->threaded_channels[i];
		if (!channel)
			continue;


		if (tegra_bpmp_master_acked(channel)) {
		if (tegra_bpmp_master_acked(channel)) {
			tegra_bpmp_channel_signal(channel);
			tegra_bpmp_channel_signal(channel);
@@ -698,7 +661,6 @@ static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)


static int tegra_bpmp_probe(struct platform_device *pdev)
static int tegra_bpmp_probe(struct platform_device *pdev)
{
{
	struct tegra_bpmp_channel *channel;
	struct tegra_bpmp *bpmp;
	struct tegra_bpmp *bpmp;
	unsigned int i;
	unsigned int i;
	char tag[32];
	char tag[32];
@@ -732,7 +694,7 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
	}
	}


	bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys);
	bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys);
	if (!bpmp->rx.pool) {
	if (!bpmp->rx.virt) {
		dev_err(&pdev->dev, "failed to allocate from RX pool\n");
		dev_err(&pdev->dev, "failed to allocate from RX pool\n");
		err = -ENOMEM;
		err = -ENOMEM;
		goto free_tx;
		goto free_tx;
@@ -758,24 +720,45 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
		goto free_rx;
		goto free_rx;
	}
	}


	bpmp->num_channels = bpmp->soc->channels.cpu_tx.count +
	spin_lock_init(&bpmp->atomic_tx_lock);
			     bpmp->soc->channels.thread.count +
	bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel),
			     bpmp->soc->channels.cpu_rx.count;
					GFP_KERNEL);
	if (!bpmp->tx_channel) {
		err = -ENOMEM;
		goto free_rx;
	}

	bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel),
	                                GFP_KERNEL);
	if (!bpmp->rx_channel) {
		err = -ENOMEM;
		goto free_rx;
	}


	bpmp->channels = devm_kcalloc(&pdev->dev, bpmp->num_channels,
	bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count,
				      sizeof(*channel), GFP_KERNEL);
					       sizeof(*bpmp->threaded_channels),
	if (!bpmp->channels) {
					       GFP_KERNEL);
	if (!bpmp->threaded_channels) {
		err = -ENOMEM;
		err = -ENOMEM;
		goto free_rx;
		goto free_rx;
	}
	}


	/* message channel initialization */
	err = tegra_bpmp_channel_init(bpmp->tx_channel, bpmp,
	for (i = 0; i < bpmp->num_channels; i++) {
				      bpmp->soc->channels.cpu_tx.offset);
		struct tegra_bpmp_channel *channel = &bpmp->channels[i];
	if (err < 0)
		goto free_rx;

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


		err = tegra_bpmp_channel_init(channel, bpmp, i);
	for (i = 0; i < bpmp->threaded.count; i++) {
		err = tegra_bpmp_channel_init(
			&bpmp->threaded_channels[i], bpmp,
			bpmp->soc->channels.thread.offset + i);
		if (err < 0)
		if (err < 0)
			goto cleanup_channels;
			goto cleanup_threaded_channels;
	}
	}


	/* mbox registration */
	/* mbox registration */
@@ -788,15 +771,14 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
	if (IS_ERR(bpmp->mbox.channel)) {
	if (IS_ERR(bpmp->mbox.channel)) {
		err = PTR_ERR(bpmp->mbox.channel);
		err = PTR_ERR(bpmp->mbox.channel);
		dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err);
		dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err);
		goto cleanup_channels;
		goto cleanup_threaded_channels;
	}
	}


	/* reset message channels */
	/* reset message channels */
	for (i = 0; i < bpmp->num_channels; i++) {
	tegra_bpmp_channel_reset(bpmp->tx_channel);
		struct tegra_bpmp_channel *channel = &bpmp->channels[i];
	tegra_bpmp_channel_reset(bpmp->rx_channel);

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


	err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
	err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
				     tegra_bpmp_mrq_handle_ping, bpmp);
				     tegra_bpmp_mrq_handle_ping, bpmp);
@@ -845,9 +827,15 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
	tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
	tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
free_mbox:
free_mbox:
	mbox_free_channel(bpmp->mbox.channel);
	mbox_free_channel(bpmp->mbox.channel);
cleanup_channels:
cleanup_threaded_channels:
	while (i--)
	for (i = 0; i < bpmp->threaded.count; i++) {
		tegra_bpmp_channel_cleanup(&bpmp->channels[i]);
		if (bpmp->threaded_channels[i].bpmp)
			tegra_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
	}

	tegra_bpmp_channel_cleanup(bpmp->rx_channel);
cleanup_tx_channel:
	tegra_bpmp_channel_cleanup(bpmp->tx_channel);
free_rx:
free_rx:
	gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
	gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
free_tx:
free_tx:
@@ -858,18 +846,16 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
static const struct tegra_bpmp_soc tegra186_soc = {
static const struct tegra_bpmp_soc tegra186_soc = {
	.channels = {
	.channels = {
		.cpu_tx = {
		.cpu_tx = {
			.offset = 0,
			.offset = 3,
			.count = 6,
			.timeout = 60 * USEC_PER_SEC,
			.timeout = 60 * USEC_PER_SEC,
		},
		},
		.thread = {
		.thread = {
			.offset = 6,
			.offset = 0,
			.count = 7,
			.count = 3,
			.timeout = 600 * USEC_PER_SEC,
			.timeout = 600 * USEC_PER_SEC,
		},
		},
		.cpu_rx = {
		.cpu_rx = {
			.offset = 13,
			.offset = 13,
			.count = 1,
			.timeout = 0,
			.timeout = 0,
		},
		},
	},
	},
+2 −2
Original line number Original line Diff line number Diff line
@@ -75,8 +75,8 @@ struct tegra_bpmp {
		struct mbox_chan *channel;
		struct mbox_chan *channel;
	} mbox;
	} mbox;


	struct tegra_bpmp_channel *channels;
	spinlock_t atomic_tx_lock;
	unsigned int num_channels;
	struct tegra_bpmp_channel *tx_channel, *rx_channel, *threaded_channels;


	struct {
	struct {
		unsigned long *allocated;
		unsigned long *allocated;