Commit bd66be54 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "Two more I2C driver bugfixes"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: mpc: Use atomic read and fix break condition
  i2c: virtio: fix completion handling
parents 2acdaf59 a74c313a
...@@ -636,7 +636,7 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) ...@@ -636,7 +636,7 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
status = readb(i2c->base + MPC_I2C_SR); status = readb(i2c->base + MPC_I2C_SR);
if (status & CSR_MIF) { if (status & CSR_MIF) {
/* Wait up to 100us for transfer to properly complete */ /* Wait up to 100us for transfer to properly complete */
readb_poll_timeout(i2c->base + MPC_I2C_SR, status, !(status & CSR_MCF), 0, 100); readb_poll_timeout_atomic(i2c->base + MPC_I2C_SR, status, status & CSR_MCF, 0, 100);
writeb(0, i2c->base + MPC_I2C_SR); writeb(0, i2c->base + MPC_I2C_SR);
mpc_i2c_do_intr(i2c, status); mpc_i2c_do_intr(i2c, status);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -22,24 +22,24 @@ ...@@ -22,24 +22,24 @@
/** /**
* struct virtio_i2c - virtio I2C data * struct virtio_i2c - virtio I2C data
* @vdev: virtio device for this controller * @vdev: virtio device for this controller
* @completion: completion of virtio I2C message
* @adap: I2C adapter for this controller * @adap: I2C adapter for this controller
* @vq: the virtio virtqueue for communication * @vq: the virtio virtqueue for communication
*/ */
struct virtio_i2c { struct virtio_i2c {
struct virtio_device *vdev; struct virtio_device *vdev;
struct completion completion;
struct i2c_adapter adap; struct i2c_adapter adap;
struct virtqueue *vq; struct virtqueue *vq;
}; };
/** /**
* struct virtio_i2c_req - the virtio I2C request structure * struct virtio_i2c_req - the virtio I2C request structure
* @completion: completion of virtio I2C message
* @out_hdr: the OUT header of the virtio I2C message * @out_hdr: the OUT header of the virtio I2C message
* @buf: the buffer into which data is read, or from which it's written * @buf: the buffer into which data is read, or from which it's written
* @in_hdr: the IN header of the virtio I2C message * @in_hdr: the IN header of the virtio I2C message
*/ */
struct virtio_i2c_req { struct virtio_i2c_req {
struct completion completion;
struct virtio_i2c_out_hdr out_hdr ____cacheline_aligned; struct virtio_i2c_out_hdr out_hdr ____cacheline_aligned;
uint8_t *buf ____cacheline_aligned; uint8_t *buf ____cacheline_aligned;
struct virtio_i2c_in_hdr in_hdr ____cacheline_aligned; struct virtio_i2c_in_hdr in_hdr ____cacheline_aligned;
...@@ -47,9 +47,11 @@ struct virtio_i2c_req { ...@@ -47,9 +47,11 @@ struct virtio_i2c_req {
static void virtio_i2c_msg_done(struct virtqueue *vq) static void virtio_i2c_msg_done(struct virtqueue *vq)
{ {
struct virtio_i2c *vi = vq->vdev->priv; struct virtio_i2c_req *req;
unsigned int len;
complete(&vi->completion); while ((req = virtqueue_get_buf(vq, &len)))
complete(&req->completion);
} }
static int virtio_i2c_prepare_reqs(struct virtqueue *vq, static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
...@@ -62,6 +64,8 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq, ...@@ -62,6 +64,8 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
int outcnt = 0, incnt = 0; int outcnt = 0, incnt = 0;
init_completion(&reqs[i].completion);
/* /*
* Only 7-bit mode supported for this moment. For the address * Only 7-bit mode supported for this moment. For the address
* format, Please check the Virtio I2C Specification. * format, Please check the Virtio I2C Specification.
...@@ -106,21 +110,15 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq, ...@@ -106,21 +110,15 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq,
struct virtio_i2c_req *reqs, struct virtio_i2c_req *reqs,
struct i2c_msg *msgs, int num) struct i2c_msg *msgs, int num)
{ {
struct virtio_i2c_req *req;
bool failed = false; bool failed = false;
unsigned int len;
int i, j = 0; int i, j = 0;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
/* Detach the ith request from the vq */ struct virtio_i2c_req *req = &reqs[i];
req = virtqueue_get_buf(vq, &len);
/* wait_for_completion(&req->completion);
* Condition req == &reqs[i] should always meet since we have
* total num requests in the vq. reqs[i] can never be NULL here. if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK)
*/
if (!failed && (WARN_ON(req != &reqs[i]) ||
req->in_hdr.status != VIRTIO_I2C_MSG_OK))
failed = true; failed = true;
i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed); i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed);
...@@ -156,12 +154,8 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -156,12 +154,8 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
* remote here to clear the virtqueue, so we can try another set of * remote here to clear the virtqueue, so we can try another set of
* messages later on. * messages later on.
*/ */
reinit_completion(&vi->completion);
virtqueue_kick(vq); virtqueue_kick(vq);
wait_for_completion(&vi->completion);
count = virtio_i2c_complete_reqs(vq, reqs, msgs, count); count = virtio_i2c_complete_reqs(vq, reqs, msgs, count);
err_free: err_free:
...@@ -210,8 +204,6 @@ static int virtio_i2c_probe(struct virtio_device *vdev) ...@@ -210,8 +204,6 @@ static int virtio_i2c_probe(struct virtio_device *vdev)
vdev->priv = vi; vdev->priv = vi;
vi->vdev = vdev; vi->vdev = vdev;
init_completion(&vi->completion);
ret = virtio_i2c_setup_vqs(vi); ret = virtio_i2c_setup_vqs(vi);
if (ret) if (ret)
return ret; return ret;
......
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