From 370d010f0ef09db7ab157a6b5d6d9a737b148f2a Mon Sep 17 00:00:00 2001 From: Timo Alho Date: Thu, 7 Sep 2017 12:31:01 +0300 Subject: firmware: tegra: Propagate error code to caller Response messages from Tegra BPMP firmware contain an error return code as the first word of payload. The error code is used to indicate incorrectly formatted request message or use of non-existing resource (clk, reset, powergate) identifier. Current implementation of tegra_bpmp_transfer() ignores this code and does not pass it to caller. Fix this by adding an extra struct member to tegra_bpmp_message and populate that with return code. Signed-off-by: Timo Alho Acked-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp.c | 22 ++++++++++++++++------ include/soc/tegra/bpmp.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 73ca55b7b7ec..33683b5a0d48 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -194,16 +194,24 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel) } static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, - void *data, size_t size) + void *data, size_t size, int *ret) { + int err; + if (data && size > 0) memcpy(data, channel->ib->data, size); - return tegra_ivc_read_advance(channel->ivc); + err = tegra_ivc_read_advance(channel->ivc); + if (err < 0) + return err; + + *ret = channel->ib->code; + + return 0; } static ssize_t tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, - void *data, size_t size) + void *data, size_t size, int *ret) { struct tegra_bpmp *bpmp = channel->bpmp; unsigned long flags; @@ -217,7 +225,7 @@ static ssize_t tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, } spin_lock_irqsave(&bpmp->lock, flags); - err = __tegra_bpmp_channel_read(channel, data, size); + err = __tegra_bpmp_channel_read(channel, data, size, ret); clear_bit(index, bpmp->threaded.allocated); spin_unlock_irqrestore(&bpmp->lock, flags); @@ -337,7 +345,8 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp, if (err < 0) return err; - return __tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size); + return __tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size, + &msg->rx.ret); } EXPORT_SYMBOL_GPL(tegra_bpmp_transfer_atomic); @@ -371,7 +380,8 @@ int tegra_bpmp_transfer(struct tegra_bpmp *bpmp, if (err == 0) return -ETIMEDOUT; - return tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size); + return tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size, + &msg->rx.ret); } EXPORT_SYMBOL_GPL(tegra_bpmp_transfer); diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h index 9ba65222bd3f..57519f4c126a 100644 --- a/include/soc/tegra/bpmp.h +++ b/include/soc/tegra/bpmp.h @@ -110,6 +110,7 @@ struct tegra_bpmp_message { struct { void *data; size_t size; + int ret; } rx; }; -- cgit From 2e1e09ed423781d209c1fea773b1c3e614550ea5 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Mon, 24 Jul 2017 19:29:16 +0300 Subject: firmware: tegra: Expose tegra_bpmp_mrq_return() Expose and export the tegra_bpmp_mrq_return() function for use by drivers outside the core BPMP driver. This function is used to reply to messages originating from the BPMP, which is required in the thermal driver. Signed-off-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp.c | 5 +++-- include/soc/tegra/bpmp.h | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 33683b5a0d48..aa4bbbd7bdb4 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -397,8 +397,8 @@ static struct tegra_bpmp_mrq *tegra_bpmp_find_mrq(struct tegra_bpmp *bpmp, return NULL; } -static void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, - int code, const void *data, size_t size) +void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code, + const void *data, size_t size) { unsigned long flags = channel->ib->flags; struct tegra_bpmp *bpmp = channel->bpmp; @@ -436,6 +436,7 @@ static void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, mbox_client_txdone(bpmp->mbox.channel, 0); } } +EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_return); static void tegra_bpmp_handle_mrq(struct tegra_bpmp *bpmp, unsigned int mrq, diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h index 57519f4c126a..b382ed01af09 100644 --- a/include/soc/tegra/bpmp.h +++ b/include/soc/tegra/bpmp.h @@ -118,6 +118,8 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp, struct tegra_bpmp_message *msg); int tegra_bpmp_transfer(struct tegra_bpmp *bpmp, struct tegra_bpmp_message *msg); +void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code, + const void *data, size_t size); int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, unsigned int mrq, tegra_bpmp_mrq_handler_t handler, void *data); -- cgit From 80d47a91e5db96e5db391aaad414fb6ceb40e7c0 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Mon, 24 Jul 2017 19:29:17 +0300 Subject: firmware: tegra: Add stubs when BPMP not enabled Add static inline stubs to bpmp.h when CONFIG_BPMP is not enabled. This allows building BPMP-related drivers with COMPILE_TEST. Signed-off-by: Mikko Perttunen Signed-off-by: Thierry Reding --- include/soc/tegra/bpmp.h | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h index b382ed01af09..1cf210504814 100644 --- a/include/soc/tegra/bpmp.h +++ b/include/soc/tegra/bpmp.h @@ -96,9 +96,6 @@ struct tegra_bpmp { struct genpd_onecell_data genpd; }; -struct tegra_bpmp *tegra_bpmp_get(struct device *dev); -void tegra_bpmp_put(struct tegra_bpmp *bpmp); - struct tegra_bpmp_message { unsigned int mrq; @@ -114,6 +111,9 @@ struct tegra_bpmp_message { } rx; }; +#if IS_ENABLED(CONFIG_TEGRA_BPMP) +struct tegra_bpmp *tegra_bpmp_get(struct device *dev); +void tegra_bpmp_put(struct tegra_bpmp *bpmp); int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp, struct tegra_bpmp_message *msg); int tegra_bpmp_transfer(struct tegra_bpmp *bpmp, @@ -125,6 +125,42 @@ int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, unsigned int mrq, tegra_bpmp_mrq_handler_t handler, void *data); void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp, unsigned int mrq, void *data); +#else +static inline struct tegra_bpmp *tegra_bpmp_get(struct device *dev) +{ + return ERR_PTR(-ENOTSUPP); +} +static inline void tegra_bpmp_put(struct tegra_bpmp *bpmp) +{ +} +static inline int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp, + struct tegra_bpmp_message *msg) +{ + return -ENOTSUPP; +} +static inline int tegra_bpmp_transfer(struct tegra_bpmp *bpmp, + struct tegra_bpmp_message *msg) +{ + return -ENOTSUPP; +} +static inline void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, + int code, const void *data, + size_t size) +{ +} + +static inline int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, + unsigned int mrq, + tegra_bpmp_mrq_handler_t handler, + void *data) +{ + return -ENOTSUPP; +} +static inline void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp, + unsigned int mrq, void *data) +{ +} +#endif #if IS_ENABLED(CONFIG_CLK_TEGRA_BPMP) int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp); -- cgit