mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
firmware: tegra: Changes for v6.2-rc1
This adds new BPMP ABI so that newer features can be enabled. Furthermore, the BPMP driver is updated to use iosys-map helpers to allow working with shared memory regions that are located in system memory. Apart from that, several minor cleanups are included. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAmN7rlETHHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zoaT0EACUyPn96EovNyLMY9Ay/EgJbCtBB7MG k1ow5NoM3ZU8LXQLwtmqQcNrBxi9edQDU40vZqzoLrhWuTIQbVdu9F+rb6oYMnC4 4POrbXKtuuFz9lr+k8xYs/M44qFQsFosvH/yr64GL9/l2yQCrKd8UP8xkxlwcE9N K4a8Lum+aNM6UwAoDvFiY97PkYf3SHgfpFbZ1teWARTnpOGaC3zpUPqOIREL7f08 SezHFK5+qmMI6D+VtsG9EETjYYeHpstmEW5j2tM3HI/noAlfY7JEBffoaptWmJ02 7A4OkWS7vbR/m69JQcpVEj5oFDUQAYMYbdEfNR/FMPPL+nAviC2yiNjWzvELgqfJ xyrtK0GqXIGOS8bQbb+nlXK+T+RiaRMFFHFp6DVKKx06QHLNYHefoRR94AjUGwyu So4POKimX0VLgMZi2votP4gQH3WKgqTsvtk+Spwq4XLH+Id5wRhg6miEInpaid/L mwoVqr4cW2ECeH5RzadtR0mR1bgL0uweXBXQFLw5Hp6MnGhD3LwNUNz/NlL5sO11 q67df3K3zccatPniOQza/WV7uul0rC+EZl9zeexSGEMlUjVHv77/99e7vDfRWe12 NNBbQxL8SmlFXriYEdWv+ZuI43tXkuk9OaSx0A1WjA4XZFwn2/3JGz9owPCDdGII SyUKFp9olvkMYg== =e9FJ -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmN9O8AACgkQmmx57+YA GNl+hRAAlwOn0/70DAtKWh49vg03JDm/fe4HYPBRNRz3z20+3qMMaINB2nCKLDhy 1+uiafbkhW6Wl/NTA+RCFbHno3ztFjHxMvUyOa/PmN3FWz1hIGR/EQk8aRVY3Jsu y+Qf2+UhsyUVJYjU0S2Mz4kdbE2hGPAmVG05MCQ1CQhLk2nIoofLqqPfKOAHqppu KqCxMzsJmPjC/6FUtM6+o7AC1wnNMO9qOR152hoPe2d8yVdydta339sDxUBKH6fE HeodQNnvNmK3M1FQf9q7Mqa1ltyyTZZKB3MMWulZFPGnnZF8u8b2jslxNQaQ+pfb G61V9KvX7sLV8mw+lXPP+lquP85IwOOajhoCGF/Pa8nofjL5vfJE4lH4spuUkFTa nWKlVhXMnpAyzQ1K7qSeA+UycZwXGAUriwVJeSyB9jrg5bBzbtaNXQ+KoB/yV2Vn sQoH4Aspm52ePLggZUnDOZTuq6NUC4HZOyApPRQgPoSGiMkFwS6ic4ae0gGDXdyT ShHkAjF2wDOcL0fxpS5Y1lRtNI9NBFAeuETrjE1QQfT6MnTjLRpWnTsylIu01lTz 1Eh4x8cOwOiYuYD52ozbnZ0F3roUbbvIm67/zgF/Up9h8qwCyIUZ1rkHQDMruBrx c91zgDxoqrEfp7Mbdu/wFWnQYhfSD6g9spBixbtflmCnMblerog= =yh95 -----END PGP SIGNATURE----- Merge tag 'tegra-for-6.2-firmware-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into soc/drivers firmware: tegra: Changes for v6.2-rc1 This adds new BPMP ABI so that newer features can be enabled. Furthermore, the BPMP driver is updated to use iosys-map helpers to allow working with shared memory regions that are located in system memory. Apart from that, several minor cleanups are included. * tag 'tegra-for-6.2-firmware-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: firmware: tegra: Remove surplus dev_err() when using platform_get_irq_byname() firmware: tegra: Update BPMP ABI firmware: tegra: bpmp: Do not support big-endian firmware: tegra: bpmp: Use iosys-map helpers firmware: tegra: bpmp: Prefer u32 over uint32_t Link: https://lore.kernel.org/r/20221121171239.2041835-2-thierry.reding@gmail.com Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
a6eeafba11
@ -48,13 +48,9 @@ static int seqbuf_read(struct seqbuf *seqbuf, void *buf, size_t nbyte)
|
||||
return seqbuf_status(seqbuf);
|
||||
}
|
||||
|
||||
static int seqbuf_read_u32(struct seqbuf *seqbuf, uint32_t *v)
|
||||
static int seqbuf_read_u32(struct seqbuf *seqbuf, u32 *v)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = seqbuf_read(seqbuf, v, 4);
|
||||
*v = le32_to_cpu(*v);
|
||||
return err;
|
||||
return seqbuf_read(seqbuf, v, 4);
|
||||
}
|
||||
|
||||
static int seqbuf_read_str(struct seqbuf *seqbuf, const char **str)
|
||||
@ -109,10 +105,10 @@ out:
|
||||
}
|
||||
|
||||
static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name,
|
||||
uint32_t *fd, uint32_t *len, bool write)
|
||||
u32 *fd, u32 *len, bool write)
|
||||
{
|
||||
struct mrq_debug_request req = {
|
||||
.cmd = cpu_to_le32(write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO),
|
||||
.cmd = write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO,
|
||||
};
|
||||
struct mrq_debug_response resp;
|
||||
struct tegra_bpmp_message msg = {
|
||||
@ -147,10 +143,10 @@ static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mrq_debug_close(struct tegra_bpmp *bpmp, uint32_t fd)
|
||||
static int mrq_debug_close(struct tegra_bpmp *bpmp, u32 fd)
|
||||
{
|
||||
struct mrq_debug_request req = {
|
||||
.cmd = cpu_to_le32(CMD_DEBUG_CLOSE),
|
||||
.cmd = CMD_DEBUG_CLOSE,
|
||||
.frd = {
|
||||
.fd = fd,
|
||||
},
|
||||
@ -179,10 +175,10 @@ static int mrq_debug_close(struct tegra_bpmp *bpmp, uint32_t fd)
|
||||
}
|
||||
|
||||
static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
|
||||
char *data, size_t sz_data, uint32_t *nbytes)
|
||||
char *data, size_t sz_data, u32 *nbytes)
|
||||
{
|
||||
struct mrq_debug_request req = {
|
||||
.cmd = cpu_to_le32(CMD_DEBUG_READ),
|
||||
.cmd = CMD_DEBUG_READ,
|
||||
};
|
||||
struct mrq_debug_response resp;
|
||||
struct tegra_bpmp_message msg = {
|
||||
@ -196,7 +192,7 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
|
||||
.size = sizeof(resp),
|
||||
},
|
||||
};
|
||||
uint32_t fd = 0, len = 0;
|
||||
u32 fd = 0, len = 0;
|
||||
int remaining, err;
|
||||
|
||||
mutex_lock(&bpmp_debug_lock);
|
||||
@ -245,7 +241,7 @@ static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name,
|
||||
uint8_t *data, size_t sz_data)
|
||||
{
|
||||
struct mrq_debug_request req = {
|
||||
.cmd = cpu_to_le32(CMD_DEBUG_WRITE)
|
||||
.cmd = CMD_DEBUG_WRITE
|
||||
};
|
||||
struct mrq_debug_response resp;
|
||||
struct tegra_bpmp_message msg = {
|
||||
@ -259,7 +255,7 @@ static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name,
|
||||
.size = sizeof(resp),
|
||||
},
|
||||
};
|
||||
uint32_t fd = 0, len = 0;
|
||||
u32 fd = 0, len = 0;
|
||||
size_t remaining;
|
||||
int err;
|
||||
|
||||
@ -308,7 +304,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
|
||||
char fnamebuf[256];
|
||||
const char *filename;
|
||||
struct mrq_debug_request req = {
|
||||
.cmd = cpu_to_le32(CMD_DEBUG_READ),
|
||||
.cmd = CMD_DEBUG_READ,
|
||||
};
|
||||
struct mrq_debug_response resp;
|
||||
struct tegra_bpmp_message msg = {
|
||||
@ -322,7 +318,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
|
||||
.size = sizeof(resp),
|
||||
},
|
||||
};
|
||||
uint32_t fd = 0, len = 0;
|
||||
u32 fd = 0, len = 0;
|
||||
int remaining, err;
|
||||
|
||||
filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
|
||||
@ -406,8 +402,8 @@ static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp,
|
||||
{
|
||||
const size_t pathlen = SZ_256;
|
||||
const size_t bufsize = SZ_16K;
|
||||
uint32_t dsize, attrs = 0;
|
||||
struct dentry *dentry;
|
||||
u32 dsize, attrs = 0;
|
||||
struct seqbuf seqbuf;
|
||||
char *buf, *pathbuf;
|
||||
const char *name;
|
||||
@ -487,12 +483,12 @@ static int mrq_debugfs_read(struct tegra_bpmp *bpmp,
|
||||
size_t *nbytes)
|
||||
{
|
||||
struct mrq_debugfs_request req = {
|
||||
.cmd = cpu_to_le32(CMD_DEBUGFS_READ),
|
||||
.cmd = CMD_DEBUGFS_READ,
|
||||
.fop = {
|
||||
.fnameaddr = cpu_to_le32((uint32_t)name),
|
||||
.fnamelen = cpu_to_le32((uint32_t)sz_name),
|
||||
.dataaddr = cpu_to_le32((uint32_t)data),
|
||||
.datalen = cpu_to_le32((uint32_t)sz_data),
|
||||
.fnameaddr = (u32)name,
|
||||
.fnamelen = (u32)sz_name,
|
||||
.dataaddr = (u32)data,
|
||||
.datalen = (u32)sz_data,
|
||||
},
|
||||
};
|
||||
struct mrq_debugfs_response resp;
|
||||
@ -525,12 +521,12 @@ static int mrq_debugfs_write(struct tegra_bpmp *bpmp,
|
||||
dma_addr_t data, size_t sz_data)
|
||||
{
|
||||
const struct mrq_debugfs_request req = {
|
||||
.cmd = cpu_to_le32(CMD_DEBUGFS_WRITE),
|
||||
.cmd = CMD_DEBUGFS_WRITE,
|
||||
.fop = {
|
||||
.fnameaddr = cpu_to_le32((uint32_t)name),
|
||||
.fnamelen = cpu_to_le32((uint32_t)sz_name),
|
||||
.dataaddr = cpu_to_le32((uint32_t)data),
|
||||
.datalen = cpu_to_le32((uint32_t)sz_data),
|
||||
.fnameaddr = (u32)name,
|
||||
.fnamelen = (u32)sz_name,
|
||||
.dataaddr = (u32)data,
|
||||
.datalen = (u32)sz_data,
|
||||
},
|
||||
};
|
||||
struct tegra_bpmp_message msg = {
|
||||
@ -548,10 +544,10 @@ static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr,
|
||||
size_t size, size_t *nbytes)
|
||||
{
|
||||
const struct mrq_debugfs_request req = {
|
||||
.cmd = cpu_to_le32(CMD_DEBUGFS_DUMPDIR),
|
||||
.cmd = CMD_DEBUGFS_DUMPDIR,
|
||||
.dumpdir = {
|
||||
.dataaddr = cpu_to_le32((uint32_t)addr),
|
||||
.datalen = cpu_to_le32((uint32_t)size),
|
||||
.dataaddr = (u32)addr,
|
||||
.datalen = (u32)size,
|
||||
},
|
||||
};
|
||||
struct mrq_debugfs_response resp;
|
||||
@ -688,10 +684,10 @@ static const struct file_operations debugfs_fops = {
|
||||
};
|
||||
|
||||
static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
|
||||
struct dentry *parent, uint32_t depth)
|
||||
struct dentry *parent, u32 depth)
|
||||
{
|
||||
int err;
|
||||
uint32_t d, t;
|
||||
u32 d, t;
|
||||
const char *name;
|
||||
struct dentry *dentry;
|
||||
|
||||
|
@ -18,8 +18,8 @@ struct tegra186_bpmp {
|
||||
|
||||
struct {
|
||||
struct gen_pool *pool;
|
||||
void __iomem *virt;
|
||||
dma_addr_t phys;
|
||||
void *virt;
|
||||
} tx, rx;
|
||||
|
||||
struct {
|
||||
@ -40,31 +40,27 @@ mbox_client_to_bpmp(struct mbox_client *client)
|
||||
|
||||
static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
|
||||
{
|
||||
void *frame;
|
||||
int err;
|
||||
|
||||
frame = tegra_ivc_read_get_next_frame(channel->ivc);
|
||||
if (IS_ERR(frame)) {
|
||||
channel->ib = NULL;
|
||||
err = tegra_ivc_read_get_next_frame(channel->ivc, &channel->ib);
|
||||
if (err) {
|
||||
iosys_map_clear(&channel->ib);
|
||||
return false;
|
||||
}
|
||||
|
||||
channel->ib = frame;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
|
||||
{
|
||||
void *frame;
|
||||
int err;
|
||||
|
||||
frame = tegra_ivc_write_get_next_frame(channel->ivc);
|
||||
if (IS_ERR(frame)) {
|
||||
channel->ob = NULL;
|
||||
err = tegra_ivc_write_get_next_frame(channel->ivc, &channel->ob);
|
||||
if (err) {
|
||||
iosys_map_clear(&channel->ob);
|
||||
return false;
|
||||
}
|
||||
|
||||
channel->ob = frame;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -109,6 +105,7 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
|
||||
{
|
||||
struct tegra186_bpmp *priv = bpmp->priv;
|
||||
size_t message_size, queue_size;
|
||||
struct iosys_map rx, tx;
|
||||
unsigned int offset;
|
||||
int err;
|
||||
|
||||
@ -121,10 +118,11 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
|
||||
queue_size = tegra_ivc_total_queue_size(message_size);
|
||||
offset = queue_size * index;
|
||||
|
||||
err = tegra_ivc_init(channel->ivc, NULL,
|
||||
priv->rx.virt + offset, priv->rx.phys + offset,
|
||||
priv->tx.virt + offset, priv->tx.phys + offset,
|
||||
1, message_size, tegra186_bpmp_ivc_notify,
|
||||
iosys_map_set_vaddr_iomem(&rx, priv->rx.virt + offset);
|
||||
iosys_map_set_vaddr_iomem(&tx, priv->tx.virt + offset);
|
||||
|
||||
err = tegra_ivc_init(channel->ivc, NULL, &rx, priv->rx.phys + offset, &tx,
|
||||
priv->tx.phys + offset, 1, message_size, tegra186_bpmp_ivc_notify,
|
||||
bpmp);
|
||||
if (err < 0) {
|
||||
dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
|
||||
@ -179,7 +177,7 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
|
||||
priv->tx.virt = (void __iomem *)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;
|
||||
@ -192,7 +190,7 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
goto free_tx;
|
||||
}
|
||||
|
||||
priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
|
||||
priv->rx.virt = (void __iomem *)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;
|
||||
|
@ -137,8 +137,8 @@ static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
|
||||
unsigned int index)
|
||||
{
|
||||
struct tegra210_bpmp *priv = bpmp->priv;
|
||||
void __iomem *p;
|
||||
u32 address;
|
||||
void *p;
|
||||
|
||||
/* Retrieve channel base address from BPMP */
|
||||
writel(index << TRIGGER_ID_SHIFT | TRIGGER_CMD_GET,
|
||||
@ -149,8 +149,9 @@ static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
channel->ib = p;
|
||||
channel->ob = p;
|
||||
iosys_map_set_vaddr_iomem(&channel->ib, p);
|
||||
iosys_map_set_vaddr_iomem(&channel->ob, p);
|
||||
|
||||
channel->index = index;
|
||||
init_completion(&channel->completion);
|
||||
channel->bpmp = bpmp;
|
||||
@ -199,10 +200,8 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
}
|
||||
|
||||
err = platform_get_irq_byname(pdev, "tx");
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to get TX IRQ: %d\n", err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
priv->tx_irq_data = irq_get_irq_data(err);
|
||||
if (!priv->tx_irq_data) {
|
||||
@ -211,10 +210,8 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
|
||||
}
|
||||
|
||||
err = platform_get_irq_byname(pdev, "rx");
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to get rx IRQ: %d\n", err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = devm_request_irq(&pdev->dev, err, rx_irq,
|
||||
IRQF_NO_SUSPEND, dev_name(&pdev->dev), bpmp);
|
||||
|
@ -201,13 +201,13 @@ static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
|
||||
int err;
|
||||
|
||||
if (data && size > 0)
|
||||
memcpy_fromio(data, channel->ib->data, size);
|
||||
tegra_bpmp_mb_read(data, &channel->ib, size);
|
||||
|
||||
err = tegra_bpmp_ack_response(channel);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
*ret = channel->ib->code;
|
||||
*ret = tegra_bpmp_mb_read_field(&channel->ib, code);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -241,11 +241,11 @@ static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
|
||||
unsigned int mrq, unsigned long flags,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
channel->ob->code = mrq;
|
||||
channel->ob->flags = flags;
|
||||
tegra_bpmp_mb_write_field(&channel->ob, code, mrq);
|
||||
tegra_bpmp_mb_write_field(&channel->ob, flags, flags);
|
||||
|
||||
if (data && size > 0)
|
||||
memcpy_toio(channel->ob->data, data, size);
|
||||
tegra_bpmp_mb_write(&channel->ob, data, size);
|
||||
|
||||
return tegra_bpmp_post_request(channel);
|
||||
}
|
||||
@ -400,7 +400,7 @@ static struct tegra_bpmp_mrq *tegra_bpmp_find_mrq(struct tegra_bpmp *bpmp,
|
||||
void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
unsigned long flags = channel->ib->flags;
|
||||
unsigned long flags = tegra_bpmp_mb_read_field(&channel->ib, flags);
|
||||
struct tegra_bpmp *bpmp = channel->bpmp;
|
||||
int err;
|
||||
|
||||
@ -417,10 +417,10 @@ void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
|
||||
if (WARN_ON(!tegra_bpmp_is_response_channel_free(channel)))
|
||||
return;
|
||||
|
||||
channel->ob->code = code;
|
||||
tegra_bpmp_mb_write_field(&channel->ob, code, code);
|
||||
|
||||
if (data && size > 0)
|
||||
memcpy_toio(channel->ob->data, data, size);
|
||||
tegra_bpmp_mb_write(&channel->ob, data, size);
|
||||
|
||||
err = tegra_bpmp_post_response(channel);
|
||||
if (WARN_ON(err < 0))
|
||||
@ -502,7 +502,7 @@ EXPORT_SYMBOL_GPL(tegra_bpmp_free_mrq);
|
||||
|
||||
bool tegra_bpmp_mrq_is_supported(struct tegra_bpmp *bpmp, unsigned int mrq)
|
||||
{
|
||||
struct mrq_query_abi_request req = { .mrq = cpu_to_le32(mrq) };
|
||||
struct mrq_query_abi_request req = { .mrq = mrq };
|
||||
struct mrq_query_abi_response resp;
|
||||
struct tegra_bpmp_message msg = {
|
||||
.mrq = MRQ_QUERY_ABI,
|
||||
@ -529,13 +529,13 @@ static void tegra_bpmp_mrq_handle_ping(unsigned int mrq,
|
||||
struct tegra_bpmp_channel *channel,
|
||||
void *data)
|
||||
{
|
||||
struct mrq_ping_request *request;
|
||||
struct mrq_ping_request request;
|
||||
struct mrq_ping_response response;
|
||||
|
||||
request = (struct mrq_ping_request *)channel->ib->data;
|
||||
tegra_bpmp_mb_read(&request, &channel->ib, sizeof(request));
|
||||
|
||||
memset(&response, 0, sizeof(response));
|
||||
response.reply = request->challenge << 1;
|
||||
response.reply = request.challenge << 1;
|
||||
|
||||
tegra_bpmp_mrq_return(channel, 0, &response, sizeof(response));
|
||||
}
|
||||
@ -648,7 +648,7 @@ static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag,
|
||||
|
||||
static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
|
||||
{
|
||||
unsigned long flags = channel->ob->flags;
|
||||
unsigned long flags = tegra_bpmp_mb_read_field(&channel->ob, flags);
|
||||
|
||||
if ((flags & MSG_RING) == 0)
|
||||
return;
|
||||
@ -666,8 +666,11 @@ void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp)
|
||||
count = bpmp->soc->channels.thread.count;
|
||||
busy = bpmp->threaded.busy;
|
||||
|
||||
if (tegra_bpmp_is_request_ready(channel))
|
||||
tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel);
|
||||
if (tegra_bpmp_is_request_ready(channel)) {
|
||||
unsigned int mrq = tegra_bpmp_mb_read_field(&channel->ib, code);
|
||||
|
||||
tegra_bpmp_handle_mrq(bpmp, mrq, channel);
|
||||
}
|
||||
|
||||
spin_lock(&bpmp->lock);
|
||||
|
||||
|
@ -68,6 +68,12 @@ struct tegra_ivc_header {
|
||||
} rx;
|
||||
};
|
||||
|
||||
#define tegra_ivc_header_read_field(hdr, field) \
|
||||
iosys_map_rd_field(hdr, 0, struct tegra_ivc_header, field)
|
||||
|
||||
#define tegra_ivc_header_write_field(hdr, field, value) \
|
||||
iosys_map_wr_field(hdr, 0, struct tegra_ivc_header, field, value)
|
||||
|
||||
static inline void tegra_ivc_invalidate(struct tegra_ivc *ivc, dma_addr_t phys)
|
||||
{
|
||||
if (!ivc->peer)
|
||||
@ -86,16 +92,15 @@ static inline void tegra_ivc_flush(struct tegra_ivc *ivc, dma_addr_t phys)
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
static inline bool tegra_ivc_empty(struct tegra_ivc *ivc,
|
||||
struct tegra_ivc_header *header)
|
||||
static inline bool tegra_ivc_empty(struct tegra_ivc *ivc, struct iosys_map *map)
|
||||
{
|
||||
/*
|
||||
* This function performs multiple checks on the same values with
|
||||
* security implications, so create snapshots with READ_ONCE() to
|
||||
* ensure that these checks use the same values.
|
||||
*/
|
||||
u32 tx = READ_ONCE(header->tx.count);
|
||||
u32 rx = READ_ONCE(header->rx.count);
|
||||
u32 tx = tegra_ivc_header_read_field(map, tx.count);
|
||||
u32 rx = tegra_ivc_header_read_field(map, rx.count);
|
||||
|
||||
/*
|
||||
* Perform an over-full check to prevent denial of service attacks
|
||||
@ -113,11 +118,10 @@ static inline bool tegra_ivc_empty(struct tegra_ivc *ivc,
|
||||
return tx == rx;
|
||||
}
|
||||
|
||||
static inline bool tegra_ivc_full(struct tegra_ivc *ivc,
|
||||
struct tegra_ivc_header *header)
|
||||
static inline bool tegra_ivc_full(struct tegra_ivc *ivc, struct iosys_map *map)
|
||||
{
|
||||
u32 tx = READ_ONCE(header->tx.count);
|
||||
u32 rx = READ_ONCE(header->rx.count);
|
||||
u32 tx = tegra_ivc_header_read_field(map, tx.count);
|
||||
u32 rx = tegra_ivc_header_read_field(map, rx.count);
|
||||
|
||||
/*
|
||||
* Invalid cases where the counters indicate that the queue is over
|
||||
@ -126,11 +130,10 @@ static inline bool tegra_ivc_full(struct tegra_ivc *ivc,
|
||||
return tx - rx >= ivc->num_frames;
|
||||
}
|
||||
|
||||
static inline u32 tegra_ivc_available(struct tegra_ivc *ivc,
|
||||
struct tegra_ivc_header *header)
|
||||
static inline u32 tegra_ivc_available(struct tegra_ivc *ivc, struct iosys_map *map)
|
||||
{
|
||||
u32 tx = READ_ONCE(header->tx.count);
|
||||
u32 rx = READ_ONCE(header->rx.count);
|
||||
u32 tx = tegra_ivc_header_read_field(map, tx.count);
|
||||
u32 rx = tegra_ivc_header_read_field(map, rx.count);
|
||||
|
||||
/*
|
||||
* This function isn't expected to be used in scenarios where an
|
||||
@ -143,8 +146,9 @@ static inline u32 tegra_ivc_available(struct tegra_ivc *ivc,
|
||||
|
||||
static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
|
||||
{
|
||||
WRITE_ONCE(ivc->tx.channel->tx.count,
|
||||
READ_ONCE(ivc->tx.channel->tx.count) + 1);
|
||||
unsigned int count = tegra_ivc_header_read_field(&ivc->tx.map, tx.count);
|
||||
|
||||
tegra_ivc_header_write_field(&ivc->tx.map, tx.count, count + 1);
|
||||
|
||||
if (ivc->tx.position == ivc->num_frames - 1)
|
||||
ivc->tx.position = 0;
|
||||
@ -154,8 +158,9 @@ static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
|
||||
|
||||
static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
|
||||
{
|
||||
WRITE_ONCE(ivc->rx.channel->rx.count,
|
||||
READ_ONCE(ivc->rx.channel->rx.count) + 1);
|
||||
unsigned int count = tegra_ivc_header_read_field(&ivc->rx.map, rx.count);
|
||||
|
||||
tegra_ivc_header_write_field(&ivc->rx.map, rx.count, count + 1);
|
||||
|
||||
if (ivc->rx.position == ivc->num_frames - 1)
|
||||
ivc->rx.position = 0;
|
||||
@ -166,6 +171,7 @@ static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
|
||||
static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
|
||||
{
|
||||
unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
|
||||
unsigned int state;
|
||||
|
||||
/*
|
||||
* tx.channel->state is set locally, so it is not synchronized with
|
||||
@ -175,7 +181,8 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
|
||||
* asynchronous transition of rx.channel->state to
|
||||
* TEGRA_IVC_STATE_ACK is not allowed.
|
||||
*/
|
||||
if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
|
||||
state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
|
||||
if (state != TEGRA_IVC_STATE_ESTABLISHED)
|
||||
return -ECONNRESET;
|
||||
|
||||
/*
|
||||
@ -185,12 +192,12 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
|
||||
* Synchronization is only necessary when these pointers indicate
|
||||
* empty or full.
|
||||
*/
|
||||
if (!tegra_ivc_empty(ivc, ivc->rx.channel))
|
||||
if (!tegra_ivc_empty(ivc, &ivc->rx.map))
|
||||
return 0;
|
||||
|
||||
tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
|
||||
|
||||
if (tegra_ivc_empty(ivc, ivc->rx.channel))
|
||||
if (tegra_ivc_empty(ivc, &ivc->rx.map))
|
||||
return -ENOSPC;
|
||||
|
||||
return 0;
|
||||
@ -199,29 +206,34 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
|
||||
static inline int tegra_ivc_check_write(struct tegra_ivc *ivc)
|
||||
{
|
||||
unsigned int offset = offsetof(struct tegra_ivc_header, rx.count);
|
||||
unsigned int state;
|
||||
|
||||
if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
|
||||
state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
|
||||
if (state != TEGRA_IVC_STATE_ESTABLISHED)
|
||||
return -ECONNRESET;
|
||||
|
||||
if (!tegra_ivc_full(ivc, ivc->tx.channel))
|
||||
if (!tegra_ivc_full(ivc, &ivc->tx.map))
|
||||
return 0;
|
||||
|
||||
tegra_ivc_invalidate(ivc, ivc->tx.phys + offset);
|
||||
|
||||
if (tegra_ivc_full(ivc, ivc->tx.channel))
|
||||
if (tegra_ivc_full(ivc, &ivc->tx.map))
|
||||
return -ENOSPC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *tegra_ivc_frame_virt(struct tegra_ivc *ivc,
|
||||
struct tegra_ivc_header *header,
|
||||
unsigned int frame)
|
||||
static int tegra_ivc_frame_virt(struct tegra_ivc *ivc, const struct iosys_map *header,
|
||||
unsigned int frame, struct iosys_map *map)
|
||||
{
|
||||
if (WARN_ON(frame >= ivc->num_frames))
|
||||
return ERR_PTR(-EINVAL);
|
||||
size_t offset = sizeof(struct tegra_ivc_header) + ivc->frame_size * frame;
|
||||
|
||||
return (void *)(header + 1) + ivc->frame_size * frame;
|
||||
if (WARN_ON(frame >= ivc->num_frames))
|
||||
return -EINVAL;
|
||||
|
||||
*map = IOSYS_MAP_INIT_OFFSET(header, offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline dma_addr_t tegra_ivc_frame_phys(struct tegra_ivc *ivc,
|
||||
@ -264,16 +276,16 @@ static inline void tegra_ivc_flush_frame(struct tegra_ivc *ivc,
|
||||
}
|
||||
|
||||
/* directly peek at the next frame rx'ed */
|
||||
void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc)
|
||||
int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (WARN_ON(ivc == NULL))
|
||||
return ERR_PTR(-EINVAL);
|
||||
return -EINVAL;
|
||||
|
||||
err = tegra_ivc_check_read(ivc);
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Order observation of ivc->rx.position potentially indicating new
|
||||
@ -284,7 +296,7 @@ void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc)
|
||||
tegra_ivc_invalidate_frame(ivc, ivc->rx.phys, ivc->rx.position, 0,
|
||||
ivc->frame_size);
|
||||
|
||||
return tegra_ivc_frame_virt(ivc, ivc->rx.channel, ivc->rx.position);
|
||||
return tegra_ivc_frame_virt(ivc, &ivc->rx.map, ivc->rx.position, map);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_read_get_next_frame);
|
||||
|
||||
@ -320,7 +332,7 @@ int tegra_ivc_read_advance(struct tegra_ivc *ivc)
|
||||
*/
|
||||
tegra_ivc_invalidate(ivc, ivc->rx.phys + tx);
|
||||
|
||||
if (tegra_ivc_available(ivc, ivc->rx.channel) == ivc->num_frames - 1)
|
||||
if (tegra_ivc_available(ivc, &ivc->rx.map) == ivc->num_frames - 1)
|
||||
ivc->notify(ivc, ivc->notify_data);
|
||||
|
||||
return 0;
|
||||
@ -328,15 +340,15 @@ int tegra_ivc_read_advance(struct tegra_ivc *ivc)
|
||||
EXPORT_SYMBOL(tegra_ivc_read_advance);
|
||||
|
||||
/* directly poke at the next frame to be tx'ed */
|
||||
void *tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc)
|
||||
int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = tegra_ivc_check_write(ivc);
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
return err;
|
||||
|
||||
return tegra_ivc_frame_virt(ivc, ivc->tx.channel, ivc->tx.position);
|
||||
return tegra_ivc_frame_virt(ivc, &ivc->tx.map, ivc->tx.position, map);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_write_get_next_frame);
|
||||
|
||||
@ -376,7 +388,7 @@ int tegra_ivc_write_advance(struct tegra_ivc *ivc)
|
||||
*/
|
||||
tegra_ivc_invalidate(ivc, ivc->tx.phys + rx);
|
||||
|
||||
if (tegra_ivc_available(ivc, ivc->tx.channel) == 1)
|
||||
if (tegra_ivc_available(ivc, &ivc->tx.map) == 1)
|
||||
ivc->notify(ivc, ivc->notify_data);
|
||||
|
||||
return 0;
|
||||
@ -387,7 +399,7 @@ void tegra_ivc_reset(struct tegra_ivc *ivc)
|
||||
{
|
||||
unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
|
||||
|
||||
ivc->tx.channel->tx.state = TEGRA_IVC_STATE_SYNC;
|
||||
tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_SYNC);
|
||||
tegra_ivc_flush(ivc, ivc->tx.phys + offset);
|
||||
ivc->notify(ivc, ivc->notify_data);
|
||||
}
|
||||
@ -416,13 +428,14 @@ EXPORT_SYMBOL(tegra_ivc_reset);
|
||||
int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
{
|
||||
unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
|
||||
enum tegra_ivc_state state;
|
||||
enum tegra_ivc_state rx_state, tx_state;
|
||||
|
||||
/* Copy the receiver's state out of shared memory. */
|
||||
tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
|
||||
state = READ_ONCE(ivc->rx.channel->tx.state);
|
||||
rx_state = tegra_ivc_header_read_field(&ivc->rx.map, tx.state);
|
||||
tx_state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
|
||||
|
||||
if (state == TEGRA_IVC_STATE_SYNC) {
|
||||
if (rx_state == TEGRA_IVC_STATE_SYNC) {
|
||||
offset = offsetof(struct tegra_ivc_header, tx.count);
|
||||
|
||||
/*
|
||||
@ -436,8 +449,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
* state and won't make progress until we change our state,
|
||||
* so the counters are not in use at this time.
|
||||
*/
|
||||
ivc->tx.channel->tx.count = 0;
|
||||
ivc->rx.channel->rx.count = 0;
|
||||
tegra_ivc_header_write_field(&ivc->tx.map, tx.count, 0);
|
||||
tegra_ivc_header_write_field(&ivc->rx.map, rx.count, 0);
|
||||
|
||||
ivc->tx.position = 0;
|
||||
ivc->rx.position = 0;
|
||||
@ -452,7 +465,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
* Move to ACK state. We have just cleared our counters, so it
|
||||
* is now safe for the remote end to start using these values.
|
||||
*/
|
||||
ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ACK;
|
||||
tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ACK);
|
||||
tegra_ivc_flush(ivc, ivc->tx.phys + offset);
|
||||
|
||||
/*
|
||||
@ -460,8 +473,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
*/
|
||||
ivc->notify(ivc, ivc->notify_data);
|
||||
|
||||
} else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_SYNC &&
|
||||
state == TEGRA_IVC_STATE_ACK) {
|
||||
} else if (tx_state == TEGRA_IVC_STATE_SYNC &&
|
||||
rx_state == TEGRA_IVC_STATE_ACK) {
|
||||
offset = offsetof(struct tegra_ivc_header, tx.count);
|
||||
|
||||
/*
|
||||
@ -475,8 +488,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
* state and won't make progress until we change our state,
|
||||
* so the counters are not in use at this time.
|
||||
*/
|
||||
ivc->tx.channel->tx.count = 0;
|
||||
ivc->rx.channel->rx.count = 0;
|
||||
tegra_ivc_header_write_field(&ivc->tx.map, tx.count, 0);
|
||||
tegra_ivc_header_write_field(&ivc->rx.map, rx.count, 0);
|
||||
|
||||
ivc->tx.position = 0;
|
||||
ivc->rx.position = 0;
|
||||
@ -492,7 +505,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
* already cleared its counters, so it is safe to start
|
||||
* writing/reading on this channel.
|
||||
*/
|
||||
ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED;
|
||||
tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ESTABLISHED);
|
||||
tegra_ivc_flush(ivc, ivc->tx.phys + offset);
|
||||
|
||||
/*
|
||||
@ -500,7 +513,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
*/
|
||||
ivc->notify(ivc, ivc->notify_data);
|
||||
|
||||
} else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_ACK) {
|
||||
} else if (tx_state == TEGRA_IVC_STATE_ACK) {
|
||||
offset = offsetof(struct tegra_ivc_header, tx.count);
|
||||
|
||||
/*
|
||||
@ -516,7 +529,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
* cleared its counters, so it is safe to start writing/reading
|
||||
* on this channel.
|
||||
*/
|
||||
ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED;
|
||||
tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ESTABLISHED);
|
||||
tegra_ivc_flush(ivc, ivc->tx.phys + offset);
|
||||
|
||||
/*
|
||||
@ -533,7 +546,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
|
||||
*/
|
||||
}
|
||||
|
||||
if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
|
||||
if (tx_state != TEGRA_IVC_STATE_ESTABLISHED)
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
@ -609,8 +622,29 @@ static int tegra_ivc_check_params(unsigned long rx, unsigned long tx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
|
||||
dma_addr_t rx_phys, void *tx, dma_addr_t tx_phys,
|
||||
static inline void iosys_map_copy(struct iosys_map *dst, const struct iosys_map *src)
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
static inline unsigned long iosys_map_get_address(const struct iosys_map *map)
|
||||
{
|
||||
if (map->is_iomem)
|
||||
return (unsigned long)map->vaddr_iomem;
|
||||
|
||||
return (unsigned long)map->vaddr;
|
||||
}
|
||||
|
||||
static inline void *iosys_map_get_vaddr(const struct iosys_map *map)
|
||||
{
|
||||
if (WARN_ON(map->is_iomem))
|
||||
return NULL;
|
||||
|
||||
return map->vaddr;
|
||||
}
|
||||
|
||||
int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, const struct iosys_map *rx,
|
||||
dma_addr_t rx_phys, const struct iosys_map *tx, dma_addr_t tx_phys,
|
||||
unsigned int num_frames, size_t frame_size,
|
||||
void (*notify)(struct tegra_ivc *ivc, void *data),
|
||||
void *data)
|
||||
@ -628,7 +662,7 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
|
||||
if (frame_size > INT_MAX)
|
||||
return -E2BIG;
|
||||
|
||||
err = tegra_ivc_check_params((unsigned long)rx, (unsigned long)tx,
|
||||
err = tegra_ivc_check_params(iosys_map_get_address(rx), iosys_map_get_address(tx),
|
||||
num_frames, frame_size);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -636,12 +670,12 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
|
||||
queue_size = tegra_ivc_total_queue_size(num_frames * frame_size);
|
||||
|
||||
if (peer) {
|
||||
ivc->rx.phys = dma_map_single(peer, rx, queue_size,
|
||||
ivc->rx.phys = dma_map_single(peer, iosys_map_get_vaddr(rx), queue_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(peer, ivc->rx.phys))
|
||||
return -ENOMEM;
|
||||
|
||||
ivc->tx.phys = dma_map_single(peer, tx, queue_size,
|
||||
ivc->tx.phys = dma_map_single(peer, iosys_map_get_vaddr(tx), queue_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(peer, ivc->tx.phys)) {
|
||||
dma_unmap_single(peer, ivc->rx.phys, queue_size,
|
||||
@ -653,8 +687,8 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
|
||||
ivc->tx.phys = tx_phys;
|
||||
}
|
||||
|
||||
ivc->rx.channel = rx;
|
||||
ivc->tx.channel = tx;
|
||||
iosys_map_copy(&ivc->rx.map, rx);
|
||||
iosys_map_copy(&ivc->tx.map, tx);
|
||||
ivc->peer = peer;
|
||||
ivc->notify = notify;
|
||||
ivc->notify_data = data;
|
||||
|
@ -106,21 +106,22 @@ static void tz_device_update_work_fn(struct work_struct *work)
|
||||
static void bpmp_mrq_thermal(unsigned int mrq, struct tegra_bpmp_channel *ch,
|
||||
void *data)
|
||||
{
|
||||
struct mrq_thermal_bpmp_to_host_request *req;
|
||||
struct mrq_thermal_bpmp_to_host_request req;
|
||||
struct tegra_bpmp_thermal *tegra = data;
|
||||
size_t offset;
|
||||
int i;
|
||||
|
||||
req = (struct mrq_thermal_bpmp_to_host_request *)ch->ib->data;
|
||||
offset = offsetof(struct tegra_bpmp_mb_data, data);
|
||||
iosys_map_memcpy_from(&req, &ch->ib, offset, sizeof(req));
|
||||
|
||||
if (req->type != CMD_THERMAL_HOST_TRIP_REACHED) {
|
||||
dev_err(tegra->dev, "%s: invalid request type: %d\n",
|
||||
__func__, req->type);
|
||||
if (req.type != CMD_THERMAL_HOST_TRIP_REACHED) {
|
||||
dev_err(tegra->dev, "%s: invalid request type: %d\n", __func__, req.type);
|
||||
tegra_bpmp_mrq_return(ch, -EINVAL, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < tegra->num_zones; ++i) {
|
||||
if (tegra->zones[i]->idx != req->host_trip_reached.zone)
|
||||
if (tegra->zones[i]->idx != req.host_trip_reached.zone)
|
||||
continue;
|
||||
|
||||
schedule_work(&tegra->zones[i]->tz_device_update_work);
|
||||
@ -129,7 +130,7 @@ static void bpmp_mrq_thermal(unsigned int mrq, struct tegra_bpmp_channel *ch,
|
||||
}
|
||||
|
||||
dev_err(tegra->dev, "%s: invalid thermal zone: %d\n", __func__,
|
||||
req->host_trip_reached.zone);
|
||||
req.host_trip_reached.zone);
|
||||
tegra_bpmp_mrq_return(ch, -EINVAL, NULL, 0);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
||||
#ifndef __SOC_TEGRA_BPMP_H
|
||||
#define __SOC_TEGRA_BPMP_H
|
||||
|
||||
#include <linux/iosys-map.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/reset-controller.h>
|
||||
@ -36,10 +37,22 @@ struct tegra_bpmp_mb_data {
|
||||
u8 data[MSG_DATA_MIN_SZ];
|
||||
} __packed;
|
||||
|
||||
#define tegra_bpmp_mb_read(dst, mb, size) \
|
||||
iosys_map_memcpy_from(dst, mb, offsetof(struct tegra_bpmp_mb_data, data), size)
|
||||
|
||||
#define tegra_bpmp_mb_write(mb, src, size) \
|
||||
iosys_map_memcpy_to(mb, offsetof(struct tegra_bpmp_mb_data, data), src, size)
|
||||
|
||||
#define tegra_bpmp_mb_read_field(mb, field) \
|
||||
iosys_map_rd_field(mb, 0, struct tegra_bpmp_mb_data, field)
|
||||
|
||||
#define tegra_bpmp_mb_write_field(mb, field, value) \
|
||||
iosys_map_wr_field(mb, 0, struct tegra_bpmp_mb_data, field, value)
|
||||
|
||||
struct tegra_bpmp_channel {
|
||||
struct tegra_bpmp *bpmp;
|
||||
struct tegra_bpmp_mb_data *ib;
|
||||
struct tegra_bpmp_mb_data *ob;
|
||||
struct iosys_map ib;
|
||||
struct iosys_map ob;
|
||||
struct completion completion;
|
||||
struct tegra_ivc *ivc;
|
||||
unsigned int index;
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/iosys-map.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct tegra_ivc_header;
|
||||
@ -16,7 +17,7 @@ struct tegra_ivc {
|
||||
struct device *peer;
|
||||
|
||||
struct {
|
||||
struct tegra_ivc_header *channel;
|
||||
struct iosys_map map;
|
||||
unsigned int position;
|
||||
dma_addr_t phys;
|
||||
} rx, tx;
|
||||
@ -37,7 +38,7 @@ struct tegra_ivc {
|
||||
*
|
||||
* Returns a pointer to the frame, or an error encoded pointer.
|
||||
*/
|
||||
void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc);
|
||||
int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map);
|
||||
|
||||
/**
|
||||
* tegra_ivc_read_advance - Advance the read queue
|
||||
@ -57,7 +58,7 @@ int tegra_ivc_read_advance(struct tegra_ivc *ivc);
|
||||
*
|
||||
* Returns a pointer to the frame, or an error encoded pointer.
|
||||
*/
|
||||
void *tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc);
|
||||
int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map);
|
||||
|
||||
/**
|
||||
* tegra_ivc_write_advance - Advance the write queue
|
||||
@ -92,8 +93,8 @@ void tegra_ivc_reset(struct tegra_ivc *ivc);
|
||||
|
||||
size_t tegra_ivc_align(size_t size);
|
||||
unsigned tegra_ivc_total_queue_size(unsigned queue_size);
|
||||
int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
|
||||
dma_addr_t rx_phys, void *tx, dma_addr_t tx_phys,
|
||||
int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, const struct iosys_map *rx,
|
||||
dma_addr_t rx_phys, const struct iosys_map *tx, dma_addr_t tx_phys,
|
||||
unsigned int num_frames, size_t frame_size,
|
||||
void (*notify)(struct tegra_ivc *ivc, void *data),
|
||||
void *data);
|
||||
|
Loading…
Reference in New Issue
Block a user