mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-17 20:29:24 +00:00
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
4 changed files with 20 additions and 26 deletions
|
@ -349,12 +349,12 @@ static int amd_mp2_pci_probe(struct pci_dev *pci_dev,
|
||||||
if (!privdata)
|
if (!privdata)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
privdata->pci_dev = pci_dev;
|
||||||
rc = amd_mp2_pci_init(privdata, pci_dev);
|
rc = amd_mp2_pci_init(privdata, pci_dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
mutex_init(&privdata->c2p_lock);
|
mutex_init(&privdata->c2p_lock);
|
||||||
privdata->pci_dev = pci_dev;
|
|
||||||
|
|
||||||
pm_runtime_set_autosuspend_delay(&pci_dev->dev, 1000);
|
pm_runtime_set_autosuspend_delay(&pci_dev->dev, 1000);
|
||||||
pm_runtime_use_autosuspend(&pci_dev->dev);
|
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 */
|
/* Ack all interrupts except for Rx done */
|
||||||
writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
|
writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
|
||||||
bus->base + ASPEED_I2C_INTR_STS_REG);
|
bus->base + ASPEED_I2C_INTR_STS_REG);
|
||||||
|
readl(bus->base + ASPEED_I2C_INTR_STS_REG);
|
||||||
irq_remaining = irq_received;
|
irq_remaining = irq_received;
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_I2C_SLAVE)
|
#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);
|
irq_received, irq_handled);
|
||||||
|
|
||||||
/* Ack Rx done */
|
/* 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,
|
writel(ASPEED_I2CD_INTR_RX_DONE,
|
||||||
bus->base + ASPEED_I2C_INTR_STS_REG);
|
bus->base + ASPEED_I2C_INTR_STS_REG);
|
||||||
|
readl(bus->base + ASPEED_I2C_INTR_STS_REG);
|
||||||
|
}
|
||||||
spin_unlock(&bus->lock);
|
spin_unlock(&bus->lock);
|
||||||
return irq_remaining ? IRQ_NONE : IRQ_HANDLED;
|
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);
|
value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
|
||||||
i2c_slave_event(iproc_i2c->slave,
|
i2c_slave_event(iproc_i2c->slave,
|
||||||
I2C_SLAVE_WRITE_RECEIVED, &value);
|
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)) {
|
} else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) {
|
||||||
/* Master read other than start */
|
/* Master read other than start */
|
||||||
|
|
|
@ -996,13 +996,14 @@ tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
|
||||||
do {
|
do {
|
||||||
u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS);
|
u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS);
|
||||||
|
|
||||||
if (status)
|
if (status) {
|
||||||
tegra_i2c_isr(i2c_dev->irq, i2c_dev);
|
tegra_i2c_isr(i2c_dev->irq, i2c_dev);
|
||||||
|
|
||||||
if (completion_done(complete)) {
|
if (completion_done(complete)) {
|
||||||
s64 delta = ktime_ms_delta(ktimeout, ktime);
|
s64 delta = ktime_ms_delta(ktimeout, ktime);
|
||||||
|
|
||||||
return msecs_to_jiffies(delta) ?: 1;
|
return msecs_to_jiffies(delta) ?: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ktime = ktime_get();
|
ktime = ktime_get();
|
||||||
|
@ -1029,18 +1030,14 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
|
||||||
disable_irq(i2c_dev->irq);
|
disable_irq(i2c_dev->irq);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Under some rare circumstances (like running KASAN +
|
* There is a chance that completion may happen after IRQ
|
||||||
* NFS root) CPU, which handles interrupt, may stuck in
|
* synchronization, which is done by disable_irq().
|
||||||
* 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)
|
if (ret == 0 && completion_done(complete)) {
|
||||||
ret = tegra_i2c_poll_completion_timeout(i2c_dev,
|
dev_warn(i2c_dev->dev,
|
||||||
complete, 0);
|
"completion done after timeout\n");
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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(
|
time_left = tegra_i2c_wait_completion_timeout(
|
||||||
i2c_dev, &i2c_dev->dma_complete, xfer_time);
|
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 ?
|
dmaengine_terminate_sync(i2c_dev->msg_read ?
|
||||||
i2c_dev->rx_dma_chan :
|
i2c_dev->rx_dma_chan :
|
||||||
i2c_dev->tx_dma_chan);
|
i2c_dev->tx_dma_chan);
|
||||||
|
|
Loading…
Add table
Reference in a new issue