firmware: Changes for v4.17-rc1
These changes are rather small, with just a fix for a return value check and some preparatory work for Tegra194 BPMP support. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAlqrz+cTHHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zoeYLEACtgcGVUSA/gsqdskhIHVE9zVmFgQes sivqoXAsMKvuHnBpJ3QG0BLXF0FWFmXwpRtCmblWwsp+OredeXv+Kv7Zki4/hvBD IsuXaerTxTcI8PgD94TwiPNqSX8HrqAvQs5402QxShSkQO0eGXUcFo3I1nzKAerm kHX2GNBqg2qDaAGA7jUcmAs/XNV4hxdm3tPWntqgB89jyuM2Qhyg0/v/XVnYjZJr gc8oClIpXZMdM1dRLbHWMVYUBLeSIHdAGVp9mfx53cCALoW9aGmwceO0I7ZWU2F0 07YHSnoRZO6Ma2+yzoDFNeaOzA3yuX2dfGYQ+kHHUXdWvO61uArs5eBrOinPNPSb +ohQtkxcU29NZ5YkIaS1C36sKrPDJMYFm/6aKB8bp+I+cy16g/P6I3XE5yFu/r55 7uWmfEiu9oNvllHEEPSlsslwaFZds9l8ticQ5D+DUm6duPsInrk4hNrqXRlM9daK kHw5dq/+gAZJOUhhjMqhTthyqpqKHJlR6hUX9clEB8H2LMkGbcQZQGJ669nNJBL1 FxROPfSm1cPsU6YdXePY0OGHoGN0U2jVgDgqwNdZW1I8QZSH1YDAG1I7YvCEyGdf 4egRaOPcE7JGhaOExVxDEI8Z1Nk1HAoSLEwVKeIeJEcrzknzCmAtnJ4L9tSlwYFp Ea8cQ9BWAcqX0w== =oigm -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
d0994465d0
2 changed files with 68 additions and 82 deletions
|
@ -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) {
|
||||||
bpmp->channels = devm_kcalloc(&pdev->dev, bpmp->num_channels,
|
|
||||||
sizeof(*channel), GFP_KERNEL);
|
|
||||||
if (!bpmp->channels) {
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto free_rx;
|
goto free_rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* message channel initialization */
|
bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel),
|
||||||
for (i = 0; i < bpmp->num_channels; i++) {
|
GFP_KERNEL);
|
||||||
struct tegra_bpmp_channel *channel = &bpmp->channels[i];
|
if (!bpmp->rx_channel) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto free_rx;
|
||||||
|
}
|
||||||
|
|
||||||
err = tegra_bpmp_channel_init(channel, bpmp, i);
|
bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count,
|
||||||
|
sizeof(*bpmp->threaded_channels),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!bpmp->threaded_channels) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto free_rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tegra_bpmp_channel_init(bpmp->tx_channel, bpmp,
|
||||||
|
bpmp->soc->channels.cpu_tx.offset);
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 @@ free_mrq:
|
||||||
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 @@ free_tx:
|
||||||
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,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue