Hi again,

On Fri, Nov 14, 2014 at 09:47:56PM -0600, Felipe Balbi wrote:
> > > how ? This is an interesting bug which deserves further explanation.
> > 
> > Look at the loops above, and at the omap_i2c_complete_cmd:
> > 
> > static inline void
> > omap_i2c_complete_cmd(struct omap_i2c_dev *dev, u16 err)
> > {
> >     dev->cmd_err |= err;
> >     complete(&dev->cmd_complete);
> > }
> > 
> > You can see, loop will be aborted if counter reached 100. Final state
> > of transfer depends on values stored in the 'err' and 'dev->cmd_err'.
> > If 'err' and 'dev->cmd_err' are zero, than transfer would be aborted
> > with status 0.

look at the IRQ handler again:

| omap_i2c_isr_thread(int this_irq, void *dev_id)
| {
|       struct omap_i2c_dev *dev = dev_id;
|       unsigned long flags;
|       u16 bits;
|       u16 stat;
|       int err = 0, count = 0;
| 
|       spin_lock_irqsave(&dev->lock, flags);
|       do {

[...]

|               if (stat & OMAP_I2C_STAT_NACK) {
|                       err |= OMAP_I2C_STAT_NACK;
|                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
|                       break;
|               }
| 
|               if (stat & OMAP_I2C_STAT_AL) {
|                       dev_err(dev->dev, "Arbitration lost\n");
|                       err |= OMAP_I2C_STAT_AL;
|                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
|                       break;
|               }

[...]

| 
|       } while (stat);
| 
|       omap_i2c_complete_cmd(dev, err);
| 
| out:
|       spin_unlock_irqrestore(&dev->lock, flags);
| 
|       return IRQ_HANDLED;
| }

How could I ever call omap_i2c_complete_cmd() with 'err' set as 0 if I
had either a NACK or Arbitration Lost ?

-- 
balbi

Attachment: signature.asc
Description: Digital signature

Reply via email to