mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 01:51:53 +00:00
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: "Some driver bugfixes and an old API removal now that all users are gone" * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: tegra: Synchronize DMA before termination i2c: tegra: Better handle case where CPU0 is busy for a long time i2c: remove i2c_new_probed_device API i2c: altera: use proper variable to hold errno i2c: designware: platdrv: Remove DPM_FLAG_SMART_SUSPEND flag on BYT and CHT
This commit is contained in:
commit
b484f3c3c6
@ -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 */
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
@ -1216,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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user