Skip to content

Commit b9e8a7d

Browse files
dgerlachnmenon
authored andcommitted
firmware: ti_sci: Switch transport to polled mode during system suspend
During system suspend it is completely valid for devices to invoke TISCI commands during the noirq phase of the suspend path. Specifically this will always be seen for devices that define a power-domains DT property and make use of the ti_sci_pm_domains genpd implementation. The genpd_finish_suspend call will power off devices during the noirq phase, which will invoke TISCI. In order to support this, the ti_sci driver must switch to not use wait_for_completion_timeout during suspend, but instead rely on a manual check for if the completion is not yet done, and proceed only if this is the case. Signed-off-by: Dave Gerlach <d-gerlach@ti.com> Signed-off-by: Nishanth Menon <nm@ti.com> Link: https://lore.kernel.org/r/20220412192138.31189-1-d-gerlach@ti.com
1 parent f226041 commit b9e8a7d

1 file changed

Lines changed: 55 additions & 6 deletions

File tree

drivers/firmware/ti_sci.c

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* Texas Instruments System Control Interface Protocol Driver
44
*
5-
* Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
5+
* Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com/
66
* Nishanth Menon
77
*/
88

@@ -12,6 +12,7 @@
1212
#include <linux/debugfs.h>
1313
#include <linux/export.h>
1414
#include <linux/io.h>
15+
#include <linux/iopoll.h>
1516
#include <linux/kernel.h>
1617
#include <linux/mailbox_client.h>
1718
#include <linux/module.h>
@@ -96,6 +97,7 @@ struct ti_sci_desc {
9697
* @node: list head
9798
* @host_id: Host ID
9899
* @users: Number of users of this instance
100+
* @is_suspending: Flag set to indicate in suspend path.
99101
*/
100102
struct ti_sci_info {
101103
struct device *dev;
@@ -114,7 +116,7 @@ struct ti_sci_info {
114116
u8 host_id;
115117
/* protected by ti_sci_list_mutex */
116118
int users;
117-
119+
bool is_suspending;
118120
};
119121

120122
#define cl_to_ti_sci_info(c) container_of(c, struct ti_sci_info, cl)
@@ -349,6 +351,8 @@ static struct ti_sci_xfer *ti_sci_get_one_xfer(struct ti_sci_info *info,
349351

350352
hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
351353
xfer->tx_message.len = tx_message_size;
354+
xfer->tx_message.chan_rx = info->chan_rx;
355+
xfer->tx_message.timeout_rx_ms = info->desc->max_rx_timeout_ms;
352356
xfer->rx_len = (u8)rx_message_size;
353357

354358
reinit_completion(&xfer->done);
@@ -406,20 +410,35 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info,
406410
int ret;
407411
int timeout;
408412
struct device *dev = info->dev;
413+
bool done_state = true;
409414

410415
ret = mbox_send_message(info->chan_tx, &xfer->tx_message);
411416
if (ret < 0)
412417
return ret;
413418

414419
ret = 0;
415420

416-
/* And we wait for the response. */
417-
timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
418-
if (!wait_for_completion_timeout(&xfer->done, timeout)) {
421+
if (!info->is_suspending) {
422+
/* And we wait for the response. */
423+
timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
424+
if (!wait_for_completion_timeout(&xfer->done, timeout))
425+
ret = -ETIMEDOUT;
426+
} else {
427+
/*
428+
* If we are suspending, we cannot use wait_for_completion_timeout
429+
* during noirq phase, so we must manually poll the completion.
430+
*/
431+
ret = read_poll_timeout_atomic(try_wait_for_completion, done_state,
432+
true, 1,
433+
info->desc->max_rx_timeout_ms * 1000,
434+
false, &xfer->done);
435+
}
436+
437+
if (ret == -ETIMEDOUT || !done_state) {
419438
dev_err(dev, "Mbox timedout in resp(caller: %pS)\n",
420439
(void *)_RET_IP_);
421-
ret = -ETIMEDOUT;
422440
}
441+
423442
/*
424443
* NOTE: we might prefer not to need the mailbox ticker to manage the
425444
* transfer queueing since the protocol layer queues things by itself.
@@ -3264,6 +3283,35 @@ static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode,
32643283
return NOTIFY_BAD;
32653284
}
32663285

3286+
static void ti_sci_set_is_suspending(struct ti_sci_info *info, bool is_suspending)
3287+
{
3288+
info->is_suspending = is_suspending;
3289+
}
3290+
3291+
static int ti_sci_suspend(struct device *dev)
3292+
{
3293+
struct ti_sci_info *info = dev_get_drvdata(dev);
3294+
/*
3295+
* We must switch operation to polled mode now as drivers and the genpd
3296+
* layer may make late TI SCI calls to change clock and device states
3297+
* from the noirq phase of suspend.
3298+
*/
3299+
ti_sci_set_is_suspending(info, true);
3300+
3301+
return 0;
3302+
}
3303+
3304+
static int ti_sci_resume(struct device *dev)
3305+
{
3306+
struct ti_sci_info *info = dev_get_drvdata(dev);
3307+
3308+
ti_sci_set_is_suspending(info, false);
3309+
3310+
return 0;
3311+
}
3312+
3313+
static DEFINE_SIMPLE_DEV_PM_OPS(ti_sci_pm_ops, ti_sci_suspend, ti_sci_resume);
3314+
32673315
/* Description for K2G */
32683316
static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
32693317
.default_host_id = 2,
@@ -3472,6 +3520,7 @@ static struct platform_driver ti_sci_driver = {
34723520
.driver = {
34733521
.name = "ti-sci",
34743522
.of_match_table = of_match_ptr(ti_sci_of_match),
3523+
.pm = &ti_sci_pm_ops,
34753524
},
34763525
};
34773526
module_platform_driver(ti_sci_driver);

0 commit comments

Comments
 (0)