Commit ed1407e7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'i2c-for-6.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "A set of regular driver fixes"

* tag 'i2c-for-6.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: xgene-slimpro: Fix out-of-bounds bug in xgene_slimpro_i2c_xfer()
  i2c: hisi: Only use the completion interrupt to finish the transfer
  i2c: hisi: Avoid redundant interrupts
  i2c: mxs: ensure that DMA buffers are safe for DMA
  i2c: imx-lpi2c: check only for enabled interrupt flags
  i2c: imx-lpi2c: clean rx/tx buffers upon new message
parents 608f1b13 92fbb6d1
...@@ -316,6 +316,13 @@ static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr) ...@@ -316,6 +316,13 @@ static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr)
max_write == 0) max_write == 0)
break; break;
} }
/*
* Disable the TX_EMPTY interrupt after finishing all the messages to
* avoid overwhelming the CPU.
*/
if (ctlr->msg_tx_idx == ctlr->msg_num)
hisi_i2c_disable_int(ctlr, HISI_I2C_INT_TX_EMPTY);
} }
static irqreturn_t hisi_i2c_irq(int irq, void *context) static irqreturn_t hisi_i2c_irq(int irq, void *context)
...@@ -341,7 +348,11 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context) ...@@ -341,7 +348,11 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context)
hisi_i2c_read_rx_fifo(ctlr); hisi_i2c_read_rx_fifo(ctlr);
out: out:
if (int_stat & HISI_I2C_INT_TRANS_CPLT || ctlr->xfer_err) { /*
* Only use TRANS_CPLT to indicate the completion. On error cases we'll
* get two interrupts, INT_ERR first then TRANS_CPLT.
*/
if (int_stat & HISI_I2C_INT_TRANS_CPLT) {
hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL); hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL); hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
complete(ctlr->completion); complete(ctlr->completion);
......
...@@ -463,6 +463,8 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter, ...@@ -463,6 +463,8 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
if (num == 1 && msgs[0].len == 0) if (num == 1 && msgs[0].len == 0)
goto stop; goto stop;
lpi2c_imx->rx_buf = NULL;
lpi2c_imx->tx_buf = NULL;
lpi2c_imx->delivered = 0; lpi2c_imx->delivered = 0;
lpi2c_imx->msglen = msgs[i].len; lpi2c_imx->msglen = msgs[i].len;
init_completion(&lpi2c_imx->complete); init_completion(&lpi2c_imx->complete);
...@@ -503,10 +505,14 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter, ...@@ -503,10 +505,14 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id) static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
{ {
struct lpi2c_imx_struct *lpi2c_imx = dev_id; struct lpi2c_imx_struct *lpi2c_imx = dev_id;
unsigned int enabled;
unsigned int temp; unsigned int temp;
enabled = readl(lpi2c_imx->base + LPI2C_MIER);
lpi2c_imx_intctrl(lpi2c_imx, 0); lpi2c_imx_intctrl(lpi2c_imx, 0);
temp = readl(lpi2c_imx->base + LPI2C_MSR); temp = readl(lpi2c_imx->base + LPI2C_MSR);
temp &= enabled;
if (temp & MSR_RDF) if (temp & MSR_RDF)
lpi2c_imx_read_rxfifo(lpi2c_imx); lpi2c_imx_read_rxfifo(lpi2c_imx);
......
...@@ -171,7 +171,7 @@ static void mxs_i2c_dma_irq_callback(void *param) ...@@ -171,7 +171,7 @@ static void mxs_i2c_dma_irq_callback(void *param)
} }
static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap, static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
struct i2c_msg *msg, uint32_t flags) struct i2c_msg *msg, u8 *buf, uint32_t flags)
{ {
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap); struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
...@@ -226,7 +226,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap, ...@@ -226,7 +226,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
} }
/* Queue the DMA data transfer. */ /* Queue the DMA data transfer. */
sg_init_one(&i2c->sg_io[1], msg->buf, msg->len); sg_init_one(&i2c->sg_io[1], buf, msg->len);
dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE); dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1, desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
DMA_DEV_TO_MEM, DMA_DEV_TO_MEM,
...@@ -259,7 +259,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap, ...@@ -259,7 +259,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
/* Queue the DMA data transfer. */ /* Queue the DMA data transfer. */
sg_init_table(i2c->sg_io, 2); sg_init_table(i2c->sg_io, 2);
sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1); sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1);
sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len); sg_set_buf(&i2c->sg_io[1], buf, msg->len);
dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2, desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
DMA_MEM_TO_DEV, DMA_MEM_TO_DEV,
...@@ -563,6 +563,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -563,6 +563,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap); struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
int ret; int ret;
int flags; int flags;
u8 *dma_buf;
int use_pio = 0; int use_pio = 0;
unsigned long time_left; unsigned long time_left;
...@@ -588,13 +589,20 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -588,13 +589,20 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
if (ret && (ret != -ENXIO)) if (ret && (ret != -ENXIO))
mxs_i2c_reset(i2c); mxs_i2c_reset(i2c);
} else { } else {
dma_buf = i2c_get_dma_safe_msg_buf(msg, 1);
if (!dma_buf)
return -ENOMEM;
reinit_completion(&i2c->cmd_complete); reinit_completion(&i2c->cmd_complete);
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); ret = mxs_i2c_dma_setup_xfer(adap, msg, dma_buf, flags);
if (ret) if (ret) {
i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
return ret; return ret;
}
time_left = wait_for_completion_timeout(&i2c->cmd_complete, time_left = wait_for_completion_timeout(&i2c->cmd_complete,
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
i2c_put_dma_safe_msg_buf(dma_buf, msg, true);
if (!time_left) if (!time_left)
goto timeout; goto timeout;
......
...@@ -308,6 +308,9 @@ static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip, ...@@ -308,6 +308,9 @@ static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip,
u32 msg[3]; u32 msg[3];
int rc; int rc;
if (writelen > I2C_SMBUS_BLOCK_MAX)
return -EINVAL;
memcpy(ctx->dma_buffer, data, writelen); memcpy(ctx->dma_buffer, data, writelen);
paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen, paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen,
DMA_TO_DEVICE); DMA_TO_DEVICE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment