From c49db937b41ee22b50813c2028e5a1d2ce1e9257 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 24 Sep 2010 14:17:17 -0300 Subject: [PATCH] --- yaml --- r: 219236 b: refs/heads/master c: df2b9b0f9c02689ce3b3f0b5dbc6c9b272bbe1ab h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/media/video/cafe_ccic.c | 36 +++++++++++++-------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/[refs] b/[refs] index d0dc9f5d827f..9d209da0e15f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a716e9d75f04ff71fb5e391a7a189b6f1b032bbc +refs/heads/master: df2b9b0f9c02689ce3b3f0b5dbc6c9b272bbe1ab diff --git a/trunk/drivers/media/video/cafe_ccic.c b/trunk/drivers/media/video/cafe_ccic.c index 2ffb6df955b3..05d810ad454a 100644 --- a/trunk/drivers/media/video/cafe_ccic.c +++ b/trunk/drivers/media/video/cafe_ccic.c @@ -363,7 +363,6 @@ static int cafe_smbus_write_data(struct cafe_camera *cam, { unsigned int rval; unsigned long flags; - DEFINE_WAIT(the_wait); spin_lock_irqsave(&cam->dev_lock, flags); rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); @@ -378,28 +377,27 @@ static int cafe_smbus_write_data(struct cafe_camera *cam, cafe_reg_write(cam, REG_TWSIC1, rval); spin_unlock_irqrestore(&cam->dev_lock, flags); + /* Unfortunately, reading TWSIC1 too soon after sending a command + * causes the device to die. + * Use a busy-wait because we often send a large quantity of small + * commands at-once; using msleep() would cause a lot of context + * switches which take longer than 2ms, resulting in a noticable + * boot-time and capture-start delays. + */ + mdelay(2); + /* - * Time to wait for the write to complete. THIS IS A RACY - * WAY TO DO IT, but the sad fact is that reading the TWSIC1 - * register too quickly after starting the operation sends - * the device into a place that may be kinder and better, but - * which is absolutely useless for controlling the sensor. In - * practice we have plenty of time to get into our sleep state - * before the interrupt hits, and the worst case is that we - * time out and then see that things completed, so this seems - * the best way for now. + * Another sad fact is that sometimes, commands silently complete but + * cafe_smbus_write_done() never becomes aware of this. + * This happens at random and appears to possible occur with any + * command. + * We don't understand why this is. We work around this issue + * with the timeout in the wait below, assuming that all commands + * complete within the timeout. */ - do { - prepare_to_wait(&cam->smbus_wait, &the_wait, - TASK_UNINTERRUPTIBLE); - schedule_timeout(1); /* even 1 jiffy is too long */ - finish_wait(&cam->smbus_wait, &the_wait); - } while (!cafe_smbus_write_done(cam)); - -#ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), CAFE_SMBUS_TIMEOUT); -#endif + spin_lock_irqsave(&cam->dev_lock, flags); rval = cafe_reg_read(cam, REG_TWSIC1); spin_unlock_irqrestore(&cam->dev_lock, flags);