Merge branch 'i2c/for-current-fixed' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: "Three driver bugfixes, and two reverts because the original patches revealed underlying problems which the Tegra guys are now working on" * 'i2c/for-current-fixed' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: aspeed: Avoid i2c interrupt status clear race condition. i2c: amd-mp2-pci: Fix Oops in amd_mp2_pci_init() error handling Revert "i2c: tegra: Better handle case where CPU0 is busy for a long time" Revert "i2c: tegra: Synchronize DMA before termination" i2c: iproc: generate stop event for slave writes
This commit is contained in:
commit
ab386c46e4
@ -349,12 +349,12 @@ static int amd_mp2_pci_probe(struct pci_dev *pci_dev,
|
||||
if (!privdata)
|
||||
return -ENOMEM;
|
||||
|
||||
privdata->pci_dev = pci_dev;
|
||||
rc = amd_mp2_pci_init(privdata, pci_dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mutex_init(&privdata->c2p_lock);
|
||||
privdata->pci_dev = pci_dev;
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&pci_dev->dev, 1000);
|
||||
pm_runtime_use_autosuspend(&pci_dev->dev);
|
||||
|
@ -603,6 +603,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
|
||||
/* Ack all interrupts except for Rx done */
|
||||
writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
|
||||
bus->base + ASPEED_I2C_INTR_STS_REG);
|
||||
readl(bus->base + ASPEED_I2C_INTR_STS_REG);
|
||||
irq_remaining = irq_received;
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C_SLAVE)
|
||||
@ -645,9 +646,11 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
|
||||
irq_received, irq_handled);
|
||||
|
||||
/* Ack Rx done */
|
||||
if (irq_received & ASPEED_I2CD_INTR_RX_DONE)
|
||||
if (irq_received & ASPEED_I2CD_INTR_RX_DONE) {
|
||||
writel(ASPEED_I2CD_INTR_RX_DONE,
|
||||
bus->base + ASPEED_I2C_INTR_STS_REG);
|
||||
readl(bus->base + ASPEED_I2C_INTR_STS_REG);
|
||||
}
|
||||
spin_unlock(&bus->lock);
|
||||
return irq_remaining ? IRQ_NONE : IRQ_HANDLED;
|
||||
}
|
||||
|
@ -360,6 +360,9 @@ static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
|
||||
value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
|
||||
i2c_slave_event(iproc_i2c->slave,
|
||||
I2C_SLAVE_WRITE_RECEIVED, &value);
|
||||
if (rx_status == I2C_SLAVE_RX_END)
|
||||
i2c_slave_event(iproc_i2c->slave,
|
||||
I2C_SLAVE_STOP, &value);
|
||||
}
|
||||
} else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) {
|
||||
/* Master read other than start */
|
||||
|
@ -996,13 +996,14 @@ 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();
|
||||
@ -1029,18 +1030,14 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
|
||||
disable_irq(i2c_dev->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.
|
||||
* There is a chance that completion may happen after IRQ
|
||||
* synchronization, which is done by disable_irq().
|
||||
*/
|
||||
if (ret == 0)
|
||||
ret = tegra_i2c_poll_completion_timeout(i2c_dev,
|
||||
complete, 0);
|
||||
if (ret == 0 && completion_done(complete)) {
|
||||
dev_warn(i2c_dev->dev,
|
||||
"completion done after timeout\n");
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1219,15 +1216,6 @@ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user