Commit bd66be54 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -636,7 +636,7 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
	status = readb(i2c->base + MPC_I2C_SR);
	if (status & CSR_MIF) {
		/* 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);
		mpc_i2c_do_intr(i2c, status);
		return IRQ_HANDLED;
+12 −20
Original line number Diff line number Diff line
@@ -22,24 +22,24 @@
/**
 * struct virtio_i2c - virtio I2C data
 * @vdev: virtio device for this controller
 * @completion: completion of virtio I2C message
 * @adap: I2C adapter for this controller
 * @vq: the virtio virtqueue for communication
 */
struct virtio_i2c {
	struct virtio_device *vdev;
	struct completion completion;
	struct i2c_adapter adap;
	struct virtqueue *vq;
};

/**
 * 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
 * @buf: the buffer into which data is read, or from which it's written
 * @in_hdr: the IN header of the virtio I2C message
 */
struct virtio_i2c_req {
	struct completion completion;
	struct virtio_i2c_out_hdr out_hdr	____cacheline_aligned;
	uint8_t *buf				____cacheline_aligned;
	struct virtio_i2c_in_hdr in_hdr		____cacheline_aligned;
@@ -47,9 +47,11 @@ struct virtio_i2c_req {

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,
@@ -62,6 +64,8 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
	for (i = 0; i < num; i++) {
		int outcnt = 0, incnt = 0;

		init_completion(&reqs[i].completion);

		/*
		 * Only 7-bit mode supported for this moment. For the address
		 * format, Please check the Virtio I2C Specification.
@@ -106,21 +110,15 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq,
				    struct virtio_i2c_req *reqs,
				    struct i2c_msg *msgs, int num)
{
	struct virtio_i2c_req *req;
	bool failed = false;
	unsigned int len;
	int i, j = 0;

	for (i = 0; i < num; i++) {
		/* Detach the ith request from the vq */
		req = virtqueue_get_buf(vq, &len);
		struct virtio_i2c_req *req = &reqs[i];

		/*
		 * 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 && (WARN_ON(req != &reqs[i]) ||
				req->in_hdr.status != VIRTIO_I2C_MSG_OK))
		wait_for_completion(&req->completion);

		if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK)
			failed = true;

		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,
	 * remote here to clear the virtqueue, so we can try another set of
	 * messages later on.
	 */

	reinit_completion(&vi->completion);
	virtqueue_kick(vq);

	wait_for_completion(&vi->completion);

	count = virtio_i2c_complete_reqs(vq, reqs, msgs, count);

err_free:
@@ -210,8 +204,6 @@ static int virtio_i2c_probe(struct virtio_device *vdev)
	vdev->priv = vi;
	vi->vdev = vdev;

	init_completion(&vi->completion);

	ret = virtio_i2c_setup_vqs(vi);
	if (ret)
		return ret;