dm crypt: introduce crypt_write_io_loop
[cascardo/linux.git] / drivers / media / common / saa7146_i2c.c
index d9953f7..7e7689a 100644 (file)
@@ -189,13 +189,22 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                saa7146_write(dev, I2C_TRANSFER, *dword);
 
                dev->i2c_op = 1;
+               SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
                SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
 
-               wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
-               if (signal_pending (current)) {
-                       /* a signal arrived */
-                       return -ERESTARTSYS;
+               timeout = HZ/100 + 1; /* 10ms */
+               timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
+               if (timeout == -ERESTARTSYS || dev->i2c_op) {
+                       SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+                       SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+                       if (timeout == -ERESTARTSYS)
+                               /* a signal arrived */
+                               return -ERESTARTSYS;
+
+                       printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+                               dev->name, __FUNCTION__);
+                       return -EIO;
                }
                status = saa7146_read(dev, I2C_STATUS);
        } else {
@@ -211,17 +220,16 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                                break;
                        }
                        if (time_after(jiffies,timeout)) {
-                               printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n");
+                               printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+                                       dev->name, __FUNCTION__);
                                return -EIO;
                        }
                }
                /* wait until we get a transfer done or error */
                timeout = jiffies + HZ/100 + 1; /* 10ms */
+               /* first read usually delivers bogus results... */
+               saa7146_i2c_status(dev);
                while(1) {
-                       /**
-                        *  first read usually delivers bogus results...
-                        */
-                       saa7146_i2c_status(dev);
                        status = saa7146_i2c_status(dev);
                        if ((status & 0x3) != 1)
                                break;
@@ -229,19 +237,28 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                                /* this is normal when probing the bus
                                 * (no answer from nonexisistant device...)
                                 */
-                               DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
+                               printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+                                       dev->name, __FUNCTION__);
                                return -EIO;
                        }
-                       if ((++trial < 20) && short_delay)
+                       if (++trial < 50 && short_delay)
                                udelay(10);
                        else
-                       msleep(1);
+                               msleep(1);
                }
        }
 
        /* give a detailed status report */
-       if ( 0 != (status & SAA7146_I2C_ERR)) {
-
+       if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR |
+                            SAA7146_I2C_DTERR | SAA7146_I2C_DRERR |
+                            SAA7146_I2C_AL    | SAA7146_I2C_ERR   |
+                            SAA7146_I2C_BUSY)) ) {
+
+               if ( 0 == (status & SAA7146_I2C_ERR) ||
+                    0 == (status & SAA7146_I2C_BUSY) ) {
+                       /* it may take some time until ERR goes high - ignore */
+                       DEB_I2C(("unexpected i2c status %04x\n", status));
+               }
                if( 0 != (status & SAA7146_I2C_SPERR) ) {
                        DEB_I2C(("error due to invalid start/stop condition.\n"));
                }
@@ -271,7 +288,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
        return 0;
 }
 
-int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
+static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
 {
        int i = 0, count = 0;
        u32* buffer = dev->d_i2c.cpu_addr;