summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2020-01-22 19:28:08 +0300
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>2020-01-22 18:52:16 +0200
commite7b7ab3847c9e727e14ba724024506beb156993c (patch)
tree020916ab2d66ceea8806c705a6de6b7c6c4cde63
parent74e9748b9b218e7863711b8c0dffb181154e4a23 (diff)
platform/x86: intel_scu_ipc: Sleeping is fine when polling
There is no reason why the driver would need to block other threads from running the CPU while it is waiting for the SCU IPC to complete its work. For this reason switch the driver to use usleep_range() instead with a bit more relaxed polling loop. Also add constant for the timeout and use the same value for both polling and interrupt modes. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c29
1 files changed, 14 insertions, 15 deletions
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index fa87bf91e5e4..c93571cea920 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -79,6 +79,9 @@ static struct intel_scu_ipc_dev ipcdev; /* Only one for now */
#define IPC_WRITE_BUFFER 0x80
#define IPC_READ_BUFFER 0x90
+/* Timeout in jiffies */
+#define IPC_TIMEOUT (3 * HZ)
+
static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
/*
@@ -132,24 +135,20 @@ static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset)
/* Wait till scu status is busy */
static inline int busy_loop(struct intel_scu_ipc_dev *scu)
{
- u32 status = ipc_read_status(scu);
- u32 loop_count = 100000;
+ unsigned long end = jiffies + msecs_to_jiffies(IPC_TIMEOUT);
- /* break if scu doesn't reset busy bit after huge retry */
- while ((status & IPC_STATUS_BUSY) && --loop_count) {
- udelay(1); /* scu processing time is in few u secods */
- status = ipc_read_status(scu);
- }
+ do {
+ u32 status;
- if (status & IPC_STATUS_BUSY) {
- dev_err(scu->dev, "IPC timed out");
- return -ETIMEDOUT;
- }
+ status = ipc_read_status(scu);
+ if (!(status & IPC_STATUS_BUSY))
+ return (status & IPC_STATUS_ERR) ? -EIO : 0;
- if (status & IPC_STATUS_ERR)
- return -EIO;
+ usleep_range(50, 100);
+ } while (time_before(jiffies, end));
- return 0;
+ dev_err(scu->dev, "IPC timed out");
+ return -ETIMEDOUT;
}
/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */
@@ -157,7 +156,7 @@ static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)
{
int status;
- if (!wait_for_completion_timeout(&scu->cmd_complete, 3 * HZ)) {
+ if (!wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT)) {
dev_err(scu->dev, "IPC timed out\n");
return -ETIMEDOUT;
}