Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: - regression fixes for i801 and designware - better API and leak fix for releasing DMA safe buffers - better greppable strings for the bitbang algorithm * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: sh_mobile: fix leak when using DMA bounce buffer i2c: sh_mobile: define start_ch() void as it only returns 0 anyhow i2c: refactor function to release a DMA safe buffer i2c: algos: bit: make the error messages grepable i2c: designware: Re-init controllers with pm_disabled set on resume i2c: i801: Allow ACPI AML access I/O ports not reserved for SMBus
This commit is contained in:
Коммит
754cf4b243
|
@ -50,10 +50,14 @@ bounce buffer. But you don't need to care about that detail, just use the
|
|||
returned buffer. If NULL is returned, the threshold was not met or a bounce
|
||||
buffer could not be allocated. Fall back to PIO in that case.
|
||||
|
||||
In any case, a buffer obtained from above needs to be released. It ensures data
|
||||
is copied back to the message and a potentially used bounce buffer is freed::
|
||||
In any case, a buffer obtained from above needs to be released. Another helper
|
||||
function ensures a potentially used bounce buffer is freed::
|
||||
|
||||
i2c_release_dma_safe_msg_buf(msg, dma_buf);
|
||||
i2c_put_dma_safe_msg_buf(dma_buf, msg, xferred);
|
||||
|
||||
The last argument 'xferred' controls if the buffer is synced back to the
|
||||
message or not. No syncing is needed in cases setting up DMA had an error and
|
||||
there was no data transferred.
|
||||
|
||||
The bounce buffer handling from the core is generic and simple. It will always
|
||||
allocate a new bounce buffer. If you want a more sophisticated handling (e.g.
|
||||
|
|
|
@ -110,8 +110,8 @@ static int sclhi(struct i2c_algo_bit_data *adap)
|
|||
}
|
||||
#ifdef DEBUG
|
||||
if (jiffies != start && i2c_debug >= 3)
|
||||
pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go "
|
||||
"high\n", jiffies - start);
|
||||
pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go high\n",
|
||||
jiffies - start);
|
||||
#endif
|
||||
|
||||
done:
|
||||
|
@ -171,8 +171,9 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
|
|||
setsda(adap, sb);
|
||||
udelay((adap->udelay + 1) / 2);
|
||||
if (sclhi(adap) < 0) { /* timed out */
|
||||
bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
|
||||
"timeout at bit #%d\n", (int)c, i);
|
||||
bit_dbg(1, &i2c_adap->dev,
|
||||
"i2c_outb: 0x%02x, timeout at bit #%d\n",
|
||||
(int)c, i);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
/* FIXME do arbitration here:
|
||||
|
@ -185,8 +186,8 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
|
|||
}
|
||||
sdahi(adap);
|
||||
if (sclhi(adap) < 0) { /* timeout */
|
||||
bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
|
||||
"timeout at ack\n", (int)c);
|
||||
bit_dbg(1, &i2c_adap->dev,
|
||||
"i2c_outb: 0x%02x, timeout at ack\n", (int)c);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
@ -215,8 +216,9 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
|
|||
sdahi(adap);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (sclhi(adap) < 0) { /* timeout */
|
||||
bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
|
||||
"#%d\n", 7 - i);
|
||||
bit_dbg(1, &i2c_adap->dev,
|
||||
"i2c_inb: timeout at bit #%d\n",
|
||||
7 - i);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
indata *= 2;
|
||||
|
@ -265,8 +267,9 @@ static int test_bus(struct i2c_adapter *i2c_adap)
|
|||
goto bailout;
|
||||
}
|
||||
if (!scl) {
|
||||
printk(KERN_WARNING "%s: SCL unexpected low "
|
||||
"while pulling SDA low!\n", name);
|
||||
printk(KERN_WARNING
|
||||
"%s: SCL unexpected low while pulling SDA low!\n",
|
||||
name);
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
|
@ -278,8 +281,9 @@ static int test_bus(struct i2c_adapter *i2c_adap)
|
|||
goto bailout;
|
||||
}
|
||||
if (!scl) {
|
||||
printk(KERN_WARNING "%s: SCL unexpected low "
|
||||
"while pulling SDA high!\n", name);
|
||||
printk(KERN_WARNING
|
||||
"%s: SCL unexpected low while pulling SDA high!\n",
|
||||
name);
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
|
@ -291,8 +295,9 @@ static int test_bus(struct i2c_adapter *i2c_adap)
|
|||
goto bailout;
|
||||
}
|
||||
if (!sda) {
|
||||
printk(KERN_WARNING "%s: SDA unexpected low "
|
||||
"while pulling SCL low!\n", name);
|
||||
printk(KERN_WARNING
|
||||
"%s: SDA unexpected low while pulling SCL low!\n",
|
||||
name);
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
|
@ -304,8 +309,9 @@ static int test_bus(struct i2c_adapter *i2c_adap)
|
|||
goto bailout;
|
||||
}
|
||||
if (!sda) {
|
||||
printk(KERN_WARNING "%s: SDA unexpected low "
|
||||
"while pulling SCL high!\n", name);
|
||||
printk(KERN_WARNING
|
||||
"%s: SDA unexpected low while pulling SCL high!\n",
|
||||
name);
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
|
@ -352,8 +358,8 @@ static int try_address(struct i2c_adapter *i2c_adap,
|
|||
i2c_start(adap);
|
||||
}
|
||||
if (i && ret)
|
||||
bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
|
||||
"0x%02x: %s\n", i + 1,
|
||||
bit_dbg(1, &i2c_adap->dev,
|
||||
"Used %d tries to %s client at 0x%02x: %s\n", i + 1,
|
||||
addr & 1 ? "read from" : "write to", addr >> 1,
|
||||
ret == 1 ? "success" : "failed, timeout?");
|
||||
return ret;
|
||||
|
@ -442,8 +448,9 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
|||
if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
|
||||
if (!(flags & I2C_M_NO_RD_ACK))
|
||||
acknak(i2c_adap, 0);
|
||||
dev_err(&i2c_adap->dev, "readbytes: invalid "
|
||||
"block length (%d)\n", inval);
|
||||
dev_err(&i2c_adap->dev,
|
||||
"readbytes: invalid block length (%d)\n",
|
||||
inval);
|
||||
return -EPROTO;
|
||||
}
|
||||
/* The original count value accounts for the extra
|
||||
|
@ -506,8 +513,8 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
|||
return -ENXIO;
|
||||
}
|
||||
if (flags & I2C_M_RD) {
|
||||
bit_dbg(3, &i2c_adap->dev, "emitting repeated "
|
||||
"start condition\n");
|
||||
bit_dbg(3, &i2c_adap->dev,
|
||||
"emitting repeated start condition\n");
|
||||
i2c_repstart(adap);
|
||||
/* okay, now switch into reading mode */
|
||||
addr |= 0x01;
|
||||
|
@ -564,8 +571,8 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
|
|||
}
|
||||
ret = bit_doAddress(i2c_adap, pmsg);
|
||||
if ((ret != 0) && !nak_ok) {
|
||||
bit_dbg(1, &i2c_adap->dev, "NAK from "
|
||||
"device addr 0x%02x msg #%d\n",
|
||||
bit_dbg(1, &i2c_adap->dev,
|
||||
"NAK from device addr 0x%02x msg #%d\n",
|
||||
msgs[i].addr, i);
|
||||
goto bailout;
|
||||
}
|
||||
|
|
|
@ -708,7 +708,6 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
|
|||
i2c_set_adapdata(adap, dev);
|
||||
|
||||
if (dev->pm_disabled) {
|
||||
dev_pm_syscore_device(dev->dev, true);
|
||||
irq_flags = IRQF_NO_SUSPEND;
|
||||
} else {
|
||||
irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND;
|
||||
|
|
|
@ -434,6 +434,9 @@ static int dw_i2c_plat_suspend(struct device *dev)
|
|||
{
|
||||
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (i_dev->pm_disabled)
|
||||
return 0;
|
||||
|
||||
i_dev->disable(i_dev);
|
||||
i2c_dw_prepare_clk(i_dev, false);
|
||||
|
||||
|
@ -444,7 +447,9 @@ static int dw_i2c_plat_resume(struct device *dev)
|
|||
{
|
||||
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (!i_dev->pm_disabled)
|
||||
i2c_dw_prepare_clk(i_dev, true);
|
||||
|
||||
i_dev->init(i_dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1415,6 +1415,13 @@ static void i801_add_tco(struct i801_priv *priv)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static bool i801_acpi_is_smbus_ioport(const struct i801_priv *priv,
|
||||
acpi_physical_address address)
|
||||
{
|
||||
return address >= priv->smba &&
|
||||
address <= pci_resource_end(priv->pci_dev, SMBBAR);
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
|
||||
u64 *value, void *handler_context, void *region_context)
|
||||
|
@ -1430,7 +1437,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
|
|||
*/
|
||||
mutex_lock(&priv->acpi_lock);
|
||||
|
||||
if (!priv->acpi_reserved) {
|
||||
if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) {
|
||||
priv->acpi_reserved = true;
|
||||
|
||||
dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n");
|
||||
|
|
|
@ -507,8 +507,6 @@ static void sh_mobile_i2c_dma_callback(void *data)
|
|||
pd->pos = pd->msg->len;
|
||||
pd->stop_after_dma = true;
|
||||
|
||||
i2c_release_dma_safe_msg_buf(pd->msg, pd->dma_buf);
|
||||
|
||||
iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE);
|
||||
}
|
||||
|
||||
|
@ -602,7 +600,7 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd)
|
|||
dma_async_issue_pending(chan);
|
||||
}
|
||||
|
||||
static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
|
||||
static void start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
|
||||
bool do_init)
|
||||
{
|
||||
if (do_init) {
|
||||
|
@ -627,7 +625,6 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
|
|||
|
||||
/* Enable all interrupts to begin with */
|
||||
iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int poll_dte(struct sh_mobile_i2c_data *pd)
|
||||
|
@ -698,9 +695,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
|
|||
pd->send_stop = i == num - 1 || msg->flags & I2C_M_STOP;
|
||||
pd->stop_after_dma = false;
|
||||
|
||||
err = start_ch(pd, msg, do_start);
|
||||
if (err)
|
||||
break;
|
||||
start_ch(pd, msg, do_start);
|
||||
|
||||
if (do_start)
|
||||
i2c_op(pd, OP_START, 0);
|
||||
|
@ -709,6 +704,10 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
|
|||
timeout = wait_event_timeout(pd->wait,
|
||||
pd->sr & (ICSR_TACK | SW_DONE),
|
||||
adapter->timeout);
|
||||
|
||||
/* 'stop_after_dma' tells if DMA transfer was complete */
|
||||
i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, pd->stop_after_dma);
|
||||
|
||||
if (!timeout) {
|
||||
dev_err(pd->dev, "Transfer request timed out\n");
|
||||
if (pd->dma_direction != DMA_NONE)
|
||||
|
|
|
@ -2293,21 +2293,22 @@ u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold)
|
|||
EXPORT_SYMBOL_GPL(i2c_get_dma_safe_msg_buf);
|
||||
|
||||
/**
|
||||
* i2c_release_dma_safe_msg_buf - release DMA safe buffer and sync with i2c_msg
|
||||
* @msg: the message to be synced with
|
||||
* i2c_put_dma_safe_msg_buf - release DMA safe buffer and sync with i2c_msg
|
||||
* @buf: the buffer obtained from i2c_get_dma_safe_msg_buf(). May be NULL.
|
||||
* @msg: the message which the buffer corresponds to
|
||||
* @xferred: bool saying if the message was transferred
|
||||
*/
|
||||
void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf)
|
||||
void i2c_put_dma_safe_msg_buf(u8 *buf, struct i2c_msg *msg, bool xferred)
|
||||
{
|
||||
if (!buf || buf == msg->buf)
|
||||
return;
|
||||
|
||||
if (msg->flags & I2C_M_RD)
|
||||
if (xferred && msg->flags & I2C_M_RD)
|
||||
memcpy(msg->buf, buf, msg->len);
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i2c_release_dma_safe_msg_buf);
|
||||
EXPORT_SYMBOL_GPL(i2c_put_dma_safe_msg_buf);
|
||||
|
||||
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
||||
MODULE_DESCRIPTION("I2C-Bus main module");
|
||||
|
|
|
@ -855,7 +855,7 @@ static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
|
|||
}
|
||||
|
||||
u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold);
|
||||
void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf);
|
||||
void i2c_put_dma_safe_msg_buf(u8 *buf, struct i2c_msg *msg, bool xferred);
|
||||
|
||||
int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr);
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче