From d79294d0de12ddd1420110813626d691f440b86f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 7 Apr 2020 20:11:16 +0200 Subject: [PATCH 1/5] i2c: designware: platdrv: Remove DPM_FLAG_SMART_SUSPEND flag on BYT and CHT We already set DPM_FLAG_SMART_PREPARE, so we completely skip all callbacks (other then prepare) where possible, quoting from dw_i2c_plat_prepare(): /* * If the ACPI companion device object is present for this device, it * may be accessed during suspend and resume of other devices via I2C * operation regions, so tell the PM core and middle layers to avoid * skipping system suspend/resume callbacks for it in that case. */ return !has_acpi_companion(dev); Also setting the DPM_FLAG_SMART_SUSPEND will cause acpi_subsys_suspend() to leave the controller runtime-suspended even if dw_i2c_plat_prepare() returned 0. Leaving the controller runtime-suspended normally, when the I2C controller is suspended during the suspend_late phase, is not an issue because the pm_runtime_get_sync() done by i2c_dw_xfer() will (runtime-)resume it. But for dw I2C controllers on Bay- and Cherry-Trail devices acpi_lpss.c leaves the controller alive until the suspend_noirq phase, because it may be used by the _PS3 ACPI methods of PCI devices and PCI devices are left powered on until the suspend_noirq phase. Between the suspend_late and resume_early phases runtime-pm is disabled. So for any ACPI I2C OPRegion accesses done after the suspend_late phase, the pm_runtime_get_sync() done by i2c_dw_xfer() is a no-op and the controller is left runtime-suspended. i2c_dw_xfer() has a check to catch this condition (rather then waiting for the I2C transfer to timeout because the controller is suspended). acpi_subsys_suspend() leaving the controller runtime-suspended in combination with an ACPI I2C OPRegion access done after the suspend_late phase triggers this check, leading to the following error being logged on a Bay Trail based Lenovo Thinkpad 8 tablet: [ 93.275882] i2c_designware 80860F41:00: Transfer while suspended [ 93.275993] WARNING: CPU: 0 PID: 412 at drivers/i2c/busses/i2c-designware-master.c:429 i2c_dw_xfer+0x239/0x280 ... [ 93.276252] Workqueue: kacpi_notify acpi_os_execute_deferred [ 93.276267] RIP: 0010:i2c_dw_xfer+0x239/0x280 ... [ 93.276340] Call Trace: [ 93.276366] __i2c_transfer+0x121/0x520 [ 93.276379] i2c_transfer+0x4c/0x100 [ 93.276392] i2c_acpi_space_handler+0x219/0x510 [ 93.276408] ? up+0x40/0x60 [ 93.276419] ? i2c_acpi_notify+0x130/0x130 [ 93.276433] acpi_ev_address_space_dispatch+0x1e1/0x252 ... So since on BYT and CHT platforms we want ACPI I2c OPRegion accesses to work until the suspend_noirq phase, we need the controller to be runtime-resumed during the suspend phase if it is runtime-suspended suspended at that time. This means that we must not set the DPM_FLAG_SMART_SUSPEND on these platforms. On BYT and CHT we already have a special ACCESS_NO_IRQ_SUSPEND flag to make sure the controller stays functional until the suspend_noirq phase. This commit makes the driver not set the DPM_FLAG_SMART_SUSPEND flag when that flag is set. Cc: stable@vger.kernel.org Fixes: b30f2f65568f ("i2c: designware: Set IRQF_NO_SUSPEND flag for all BYT and CHT controllers") Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Acked-by: Rafael J. Wysocki Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-platdrv.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index c98befe2a92e..5536673060cc 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -354,10 +354,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) adap->dev.of_node = pdev->dev.of_node; adap->nr = -1; - dev_pm_set_driver_flags(&pdev->dev, - DPM_FLAG_SMART_PREPARE | - DPM_FLAG_SMART_SUSPEND | - DPM_FLAG_LEAVE_SUSPENDED); + if (dev->flags & ACCESS_NO_IRQ_SUSPEND) { + dev_pm_set_driver_flags(&pdev->dev, + DPM_FLAG_SMART_PREPARE | + DPM_FLAG_LEAVE_SUSPENDED); + } else { + dev_pm_set_driver_flags(&pdev->dev, + DPM_FLAG_SMART_PREPARE | + DPM_FLAG_SMART_SUSPEND | + DPM_FLAG_LEAVE_SUSPENDED); + } /* The code below assumes runtime PM to be disabled. */ WARN_ON(pm_runtime_enabled(&pdev->dev)); From edb2c9dd3948738ef030c32b948543e84f4d3f81 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 27 Mar 2020 23:28:26 +0100 Subject: [PATCH 2/5] i2c: altera: use proper variable to hold errno device_property_read_u32() returns errno or 0, so we should use the integer variable 'ret' and not the u32 'val' to hold the retval. Fixes: 0560ad576268 ("i2c: altera: Add Altera I2C Controller driver") Signed-off-by: Wolfram Sang Reviewed-by: Thor Thayer Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-altera.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-altera.c b/drivers/i2c/busses/i2c-altera.c index 20ef63820c77..f5c00f903df3 100644 --- a/drivers/i2c/busses/i2c-altera.c +++ b/drivers/i2c/busses/i2c-altera.c @@ -384,7 +384,6 @@ static int altr_i2c_probe(struct platform_device *pdev) struct altr_i2c_dev *idev = NULL; struct resource *res; int irq, ret; - u32 val; idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL); if (!idev) @@ -411,17 +410,17 @@ static int altr_i2c_probe(struct platform_device *pdev) init_completion(&idev->msg_complete); spin_lock_init(&idev->lock); - val = device_property_read_u32(idev->dev, "fifo-size", + ret = device_property_read_u32(idev->dev, "fifo-size", &idev->fifo_size); - if (val) { + if (ret) { dev_err(&pdev->dev, "FIFO size set to default of %d\n", ALTR_I2C_DFLT_FIFO_SZ); idev->fifo_size = ALTR_I2C_DFLT_FIFO_SZ; } - val = device_property_read_u32(idev->dev, "clock-frequency", + ret = device_property_read_u32(idev->dev, "clock-frequency", &idev->bus_clk_rate); - if (val) { + if (ret) { dev_err(&pdev->dev, "Default to 100kHz\n"); idev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; /* default clock rate */ } From 3c1d1613be80c2e17f1ddf672df1d8a8caebfd0d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 6 Apr 2020 14:25:31 +0200 Subject: [PATCH 3/5] i2c: remove i2c_new_probed_device API All in-tree users have been converted to the new i2c_new_scanned_device function, so remove this deprecated one. Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 13 ------------- include/linux/i2c.h | 6 ------ 2 files changed, 19 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 5cc0b0ec5570..a66912782064 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -2273,19 +2273,6 @@ i2c_new_scanned_device(struct i2c_adapter *adap, } EXPORT_SYMBOL_GPL(i2c_new_scanned_device); -struct i2c_client * -i2c_new_probed_device(struct i2c_adapter *adap, - struct i2c_board_info *info, - unsigned short const *addr_list, - int (*probe)(struct i2c_adapter *adap, unsigned short addr)) -{ - struct i2c_client *client; - - client = i2c_new_scanned_device(adap, info, addr_list, probe); - return IS_ERR(client) ? NULL : client; -} -EXPORT_SYMBOL_GPL(i2c_new_probed_device); - struct i2c_adapter *i2c_get_adapter(int nr) { struct i2c_adapter *adapter; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 456fc17ecb1c..45d36ba4826b 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -461,12 +461,6 @@ i2c_new_scanned_device(struct i2c_adapter *adap, unsigned short const *addr_list, int (*probe)(struct i2c_adapter *adap, unsigned short addr)); -struct i2c_client * -i2c_new_probed_device(struct i2c_adapter *adap, - struct i2c_board_info *info, - unsigned short const *addr_list, - int (*probe)(struct i2c_adapter *adap, unsigned short addr)); - /* Common custom probe functions */ int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr); From a900aeac253729411cf33c6cb598c152e9e4137f Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 24 Mar 2020 22:12:16 +0300 Subject: [PATCH 4/5] i2c: tegra: Better handle case where CPU0 is busy for a long time Boot CPU0 always handle I2C interrupt and under some rare circumstances (like running KASAN + NFS root) it may stuck in uninterruptible state for a significant time. In this case we will get timeout if I2C transfer is running on a sibling CPU, despite of IRQ being raised. In order to handle this rare condition, the IRQ status needs to be checked after completion timeout. Signed-off-by: Dmitry Osipenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 4c4d17ddc96b..a795b4e278b1 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -996,14 +996,13 @@ tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev, do { u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS); - if (status) { + if (status) tegra_i2c_isr(i2c_dev->irq, i2c_dev); - if (completion_done(complete)) { - s64 delta = ktime_ms_delta(ktimeout, ktime); + if (completion_done(complete)) { + s64 delta = ktime_ms_delta(ktimeout, ktime); - return msecs_to_jiffies(delta) ?: 1; - } + return msecs_to_jiffies(delta) ?: 1; } ktime = ktime_get(); @@ -1030,14 +1029,18 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev, disable_irq(i2c_dev->irq); /* - * There is a chance that completion may happen after IRQ - * synchronization, which is done by disable_irq(). + * Under some rare circumstances (like running KASAN + + * NFS root) CPU, which handles interrupt, may stuck in + * uninterruptible state for a significant time. In this + * case we will get timeout if I2C transfer is running on + * a sibling CPU, despite of IRQ being raised. + * + * In order to handle this rare condition, the IRQ status + * needs to be checked after timeout. */ - if (ret == 0 && completion_done(complete)) { - dev_warn(i2c_dev->dev, - "completion done after timeout\n"); - ret = 1; - } + if (ret == 0) + ret = tegra_i2c_poll_completion_timeout(i2c_dev, + complete, 0); } return ret; From 8814044fe0fa182abc9ff818d3da562de98bc9a7 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 24 Mar 2020 22:12:17 +0300 Subject: [PATCH 5/5] i2c: tegra: Synchronize DMA before termination DMA transfer could be completed, but CPU (which handles DMA interrupt) may get too busy and can't handle the interrupt in a timely manner, despite of DMA IRQ being raised. In this case the DMA state needs to synchronized before terminating DMA transfer in order not to miss the DMA transfer completion. Signed-off-by: Dmitry Osipenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index a795b4e278b1..8280ac7cc1b7 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -1219,6 +1219,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, time_left = tegra_i2c_wait_completion_timeout( i2c_dev, &i2c_dev->dma_complete, xfer_time); + /* + * Synchronize DMA first, since dmaengine_terminate_sync() + * performs synchronization after the transfer's termination + * and we want to get a completion if transfer succeeded. + */ + dmaengine_synchronize(i2c_dev->msg_read ? + i2c_dev->rx_dma_chan : + i2c_dev->tx_dma_chan); + dmaengine_terminate_sync(i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan);