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
This commit is contained in:
Коммит
bd66be54b9
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче