[patch] fix common mistake in polling loops

From: Zed 0xff
Date: Fri Jul 28 2006 - 04:26:20 EST


From: Andrej Zaikin <zed.0xff@xxxxxxxxx>
Signed-off-by: Andrej Zaikin <zed.0xff@xxxxxxxxx>

task taken from http://kerneljanitors.org/TODO:

A _lot_ of drivers end up caring about absolute time, because a _lot_ of
drivers have a very simple issue like:

- poll this port every 10ms until it returns "ready", or until we time
out after 500ms.

And the thing is, you can do it the stupid way:

for (i = 0; i < 50; i++) {
if (ready())
return 0;
msleep(10);
}
.. timeout ..

or you can do it the _right_ way. The stupid way is simpler, but anybody
who doesn't see what the problem is has some serious problems in kernel
programming. Hint: it might not be polling for half a second, it might be
polling for half a _minute_ for all you know.

In other words, the _right_ way to do this is literally

unsigned long timeout = jiffies + msecs_to_jiffies(500);
for (;;) {
if (ready())
return 0;
if (time_after(timeout, jiffies))
break;
msleep(10);
}

which is unquestionably more complex, yes, but it's more complex because
it is CORRECT!

### Diffstat output
drivers/acpi/sbs.c | 11 +++++++----
drivers/atm/firestream.c | 17 +++++++++--------
drivers/block/sx8.c | 12 +++++++-----
drivers/char/sonypi.c | 14 ++++++++++++--
drivers/char/tpm/tpm_infineon.c | 21 ++++++++++++---------
drivers/char/watchdog/pcwd.c | 8 ++++++--
drivers/hwmon/hdaps.c | 10 +++++++---
drivers/infiniband/hw/mthca/mthca_reset.c | 8 ++++++--
drivers/input/mouse/psmouse-base.c | 7 ++++++-
drivers/media/video/cx88/cx88-core.c | 9 +++++++--
drivers/media/video/meye.c | 11 +++++++++--
drivers/media/video/ov511.c | 9 +++++++--
drivers/media/video/ovcamchip/ovcamchip_core.c | 10 ++++++++--
drivers/pcmcia/cs.c | 9 +++++++--
drivers/serial/icom.c | 11 +++++++----
sound/isa/cs423x/cs4231_lib.c | 10 +++++-----
sound/pci/cs46xx/cs46xx_lib.c | 19 ++++++++++++-------
17 files changed, 134 insertions(+), 62 deletions(-)
diff -upr -X linux-2.6.17/Documentation/dontdiff a/drivers/acpi/sbs.c
b/drivers/acpi/sbs.c
--- a/drivers/acpi/sbs.c 2006-07-27 21:55:54.000000000 +0600
+++ b/drivers/acpi/sbs.c 2006-07-28 00:41:12.000000000 +0600
@@ -1573,7 +1573,8 @@ static int acpi_sbs_add(struct acpi_devi
struct acpi_ec_hc *ec_hc = NULL;
int result, remove_result = 0;
unsigned long sbs_obj;
- int id, cnt;
+ int id;
+ unsigned long timeout;
acpi_status status = AE_OK;

sbs = kmalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
@@ -1583,13 +1584,15 @@ static int acpi_sbs_add(struct acpi_devi
}
memset(sbs, 0, sizeof(struct acpi_sbs));

- cnt = 0;
- while (cnt < 10) {
- cnt++;
+ timeout = jiffies + msecs_to_jiffies(10000);
+ for(;;){
ec_hc = acpi_get_ec_hc(device);
if (ec_hc) {
break;
}
+ if (time_after(timeout, jiffies)) {
+ break;
+ }
msleep(1000);
}

diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/atm/firestream.c b/drivers/atm/firestream.c
--- a/drivers/atm/firestream.c 2006-07-27 21:55:47.000000000 +0600
+++ b/drivers/atm/firestream.c 2006-07-28 00:49:30.000000000 +0600
@@ -1652,8 +1652,9 @@ static void fs_poll (unsigned long data)
static int __devinit fs_init (struct fs_dev *dev)
{
struct pci_dev *pci_dev;
- int isr, to;
+ int isr;
int i;
+ unsigned long timeout;

func_enter ();
pci_dev = dev->pci_dev;
@@ -1692,8 +1693,8 @@ static int __devinit fs_init (struct fs_

/* 10ms * 100 is 1 second. That should be enough, as AN3:9 says it takes
1ms. */
- to = 100;
- while (--to) {
+ timeout = jiffies + msecs_to_jiffies(1000);
+ for(;;) {
isr = read_fs (dev, ISR);

/* This bit is documented as "RESERVED" */
@@ -1706,15 +1707,15 @@ static int __devinit fs_init (struct fs_
break;
}

+ if (time_after(timeout, jiffies)) {
+ printk (KERN_ERR "timeout initializing the FS... \n");
+ return 1;
+ }
+
/* Try again after 10ms. */
msleep(10);
}

- if (!to) {
- printk (KERN_ERR "timeout initializing the FS... \n");
- return 1;
- }
-
/* XXX fix for fs155 */
dev->channel_mask = 0x1f;
dev->channo = 0;
diff -upr -X linux-2.6.17/Documentation/dontdiff a/drivers/block/sx8.c
b/drivers/block/sx8.c
--- a/drivers/block/sx8.c 2006-07-27 21:56:05.000000000 +0600
+++ b/drivers/block/sx8.c 2006-07-28 00:52:33.000000000 +0600
@@ -550,21 +550,23 @@ static struct carm_request *carm_get_spe
unsigned long flags;
struct carm_request *crq = NULL;
struct request *rq;
- int tries = 5000;
+ unsigned long timeout= jiffies + msecs_to_jiffies(50000);

- while (tries-- > 0) {
+ for(;;) {
spin_lock_irqsave(&host->lock, flags);
crq = carm_get_request(host);
spin_unlock_irqrestore(&host->lock, flags);

if (crq)
break;
+
+ if (time_after(timeout, jiffies)) {
+ return NULL;
+ }
+
msleep(10);
}

- if (!crq)
- return NULL;
-
rq = blk_get_request(host->oob_q, WRITE /* bogus */, GFP_KERNEL);
if (!rq) {
spin_lock_irqsave(&host->lock, flags);
diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/char/sonypi.c b/drivers/char/sonypi.c
--- a/drivers/char/sonypi.c 2006-07-27 21:55:57.000000000 +0600
+++ b/drivers/char/sonypi.c 2006-07-28 00:59:48.000000000 +0600
@@ -724,6 +724,7 @@ static void sonypi_camera_off(void)
static void sonypi_camera_on(void)
{
int i, j;
+ unsigned long timeout;

if (sonypi_device.camera_power)
return;
@@ -734,9 +735,18 @@ static void sonypi_camera_on(void)
msleep(10);
sonypi_call1(0x93);

- for (i = 400; i > 0; i--) {
- if (sonypi_camera_ready())
+ timeout=jiffies + msecs_to_jiffies(4000);
+ for (;;) {
+ if (sonypi_camera_ready()){
+ i=1;
break;
+ }
+
+ if (time_after(timeout, jiffies)){
+ i=0;
+ break;
+ }
+
msleep(10);
}
if (i)
diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
--- a/drivers/char/tpm/tpm_infineon.c 2006-07-27 21:55:56.000000000 +0600
+++ b/drivers/char/tpm/tpm_infineon.c 2006-07-28 01:03:29.000000000 +0600
@@ -137,21 +137,24 @@ static int empty_fifo(struct tpm_chip *c
static int wait(struct tpm_chip *chip, int wait_for_bit)
{
int status;
- int i;
- for (i = 0; i < TPM_MAX_TRIES; i++) {
+ unsigned long timeout = jiffies +
msecs_to_jiffies(TPM_MAX_TRIES*TPM_MSLEEP_TIME);
+ for (;;) {
status = inb(chip->vendor.base + STAT);
/* check the status-register if wait_for_bit is set */
if (status & 1 << wait_for_bit)
break;
+
+ if (time_after(timeout, jiffies)) {
+ /* timeout occurs */
+ if (wait_for_bit == STAT_XFE)
+ dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n");
+ if (wait_for_bit == STAT_RDA)
+ dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n");
+ return -EIO;
+ }
+
msleep(TPM_MSLEEP_TIME);
}
- if (i == TPM_MAX_TRIES) { /* timeout occurs */
- if (wait_for_bit == STAT_XFE)
- dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n");
- if (wait_for_bit == STAT_RDA)
- dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n");
- return -EIO;
- }
return 0;
};

diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
--- a/drivers/char/watchdog/pcwd.c 2006-07-27 21:55:57.000000000 +0600
+++ b/drivers/char/watchdog/pcwd.c 2006-07-28 01:06:33.000000000 +0600
@@ -918,8 +918,8 @@ static int __init pcwd_checkcard(int bas
{
int port0, last_port0; /* Reg 0, in case it's REV A */
int port1, last_port1; /* Register 1 for REV C cards */
- int i;
int retval;
+ unsigned long timeout;

if (!request_region (base_addr, 4, "PCWD")) {
printk (KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr);
@@ -932,7 +932,8 @@ static int __init pcwd_checkcard(int bas
port1 = inb_p(base_addr + 1); /* For REV C boards */
if (port0 != 0xff || port1 != 0xff) {
/* Not an 'ff' from a floating bus, so must be a card! */
- for (i = 0; i < 4; ++i) {
+ timeout = jiffies + msecs_to_jiffies(2000);
+ for (;;) {

msleep(500);

@@ -948,6 +949,9 @@ static int __init pcwd_checkcard(int bas
retval = 1;
break;
}
+ if (time_after(timeout, jiffies)){
+ break;
+ }
}
}
release_region (base_addr, 4);
diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
--- a/drivers/hwmon/hdaps.c 2006-07-27 21:56:06.000000000 +0600
+++ b/drivers/hwmon/hdaps.c 2006-07-28 01:12:38.000000000 +0600
@@ -211,7 +211,8 @@ static int hdaps_read_pair(unsigned int
*/
static int hdaps_device_init(void)
{
- int total, ret = -ENXIO;
+ int ret = -ENXIO;
+ unsigned long timeout;

down(&hdaps_sem);

@@ -265,7 +266,8 @@ static int hdaps_device_init(void)
goto out;

/* we have done our dance, now let's wait for the applause */
- for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
+ timeout = jiffies + msecs_to_jiffies(INIT_TIMEOUT_MSECS);
+ for (;;){
int x, y;

/* a read of the device helps push it into action */
@@ -274,7 +276,9 @@ static int hdaps_device_init(void)
ret = 0;
break;
}
-
+ if (time_after(timeout, jiffies)){
+ break;
+ }
msleep(INIT_WAIT_MSECS);
}

diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/infiniband/hw/mthca/mthca_reset.c
b/drivers/infiniband/hw/mthca/mthca_reset.c
--- a/drivers/infiniband/hw/mthca/mthca_reset.c 2006-07-27
21:56:05.000000000 +0600
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c 2006-07-28
01:20:00.000000000 +0600
@@ -168,9 +168,9 @@ int mthca_reset(struct mthca_dev *mdev)
/* Now wait for PCI device to start responding again */
{
u32 v;
- int c = 0;
+ unsigned long timeout = jiffies + msecs_to_jiffies(10000);

- for (c = 0; c < 100; ++c) {
+ for (;;) {
if (pci_read_config_dword(bridge ? bridge : mdev->pdev, 0, &v)) {
err = -ENODEV;
mthca_err(mdev, "Couldn't access HCA after reset, "
@@ -181,6 +181,10 @@ int mthca_reset(struct mthca_dev *mdev)
if (v != 0xffffffff)
goto good;

+ if (time_after(timeout, jiffies)){
+ break;
+ }
+
msleep(100);
}

diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/input/mouse/psmouse-base.c
b/drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c 2006-07-27 21:56:06.000000000 +0600
+++ b/drivers/input/mouse/psmouse-base.c 2006-07-28 01:23:30.000000000 +0600
@@ -898,6 +898,7 @@ static void psmouse_resync(void *p)
psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
int failed = 0, enabled = 0;
int i;
+ unsigned long timeout;

mutex_lock(&psmouse_mutex);

@@ -955,11 +956,15 @@ static void psmouse_resync(void *p)
* repeat our attempts 5 times, otherwise we may be left out with disabled
* mouse.
*/
- for (i = 0; i < 5; i++) {
+ timeout = jiffies + msecs_to_jiffies(1000);
+ for (;;) {
if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
enabled = 1;
break;
}
+ if (time_after(timeout, jiffies)) {
+ break;
+ }
msleep(200);
}

diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/media/video/cx88/cx88-core.c
b/drivers/media/video/cx88/cx88-core.c
--- a/drivers/media/video/cx88/cx88-core.c 2006-07-27 21:56:07.000000000 +0600
+++ b/drivers/media/video/cx88/cx88-core.c 2006-07-28 01:35:40.000000000 +0600
@@ -756,7 +756,7 @@ static int set_pll(struct cx88_core *cor
static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
u64 pll;
u32 reg;
- int i;
+ unsigned long timeout;

if (prescale < 2)
prescale = 2;
@@ -774,7 +774,9 @@ static int set_pll(struct cx88_core *cor
dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
reg, cx_read(MO_PLL_REG), ofreq);
cx_write(MO_PLL_REG, reg);
- for (i = 0; i < 100; i++) {
+
+ timeout = jiffies + msecs_to_jiffies(1000);
+ for (;;) {
reg = cx_read(MO_DEVICE_STATUS);
if (reg & (1<<2)) {
dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
@@ -782,6 +784,9 @@ static int set_pll(struct cx88_core *cor
return 0;
}
dprintk(1,"pll not locked yet, waiting ...\n");
+ if(time_after(timeout, jiffies)){
+ break;
+ }
msleep(10);
}
dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/media/video/meye.c b/drivers/media/video/meye.c
--- a/drivers/media/video/meye.c 2006-07-27 21:56:08.000000000 +0600
+++ b/drivers/media/video/meye.c 2006-07-28 01:38:11.000000000 +0600
@@ -558,12 +558,15 @@ static void mchip_dma_free(void)
reset the dma engine */
static void mchip_hic_stop(void)
{
- int i, j;
+ int j;
+ unsigned long timeout;

meye.mchip_mode = MCHIP_HIC_MODE_NOOP;
if (!(mchip_read(MCHIP_HIC_STATUS) & MCHIP_HIC_STATUS_BUSY))
return;
- for (i = 0; i < 20; ++i) {
+
+ timeout = jiffies + msecs_to_jiffies(250*20);
+ for (;;) {
mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP);
mchip_delay(MCHIP_HIC_CMD, 0);
for (j = 0; j < 100; ++j) {
@@ -575,6 +578,10 @@ static void mchip_hic_stop(void)
printk(KERN_ERR "meye: need to reset HIC!\n");

mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET);
+
+ if (time_after(timeout, jiffies))
+ break;
+
msleep(250);
}
printk(KERN_ERR "meye: resetting HIC hanged!\n");
diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
--- a/drivers/media/video/ov511.c 2006-07-27 21:56:09.000000000 +0600
+++ b/drivers/media/video/ov511.c 2006-07-28 01:41:31.000000000 +0600
@@ -1136,6 +1136,7 @@ static int
init_ov_sensor(struct usb_ov511 *ov)
{
int i, success;
+ unsigned long timeout;

/* Reset the sensor */
if (i2c_w(ov, 0x12, 0x80) < 0)
@@ -1144,11 +1145,12 @@ init_ov_sensor(struct usb_ov511 *ov)
/* Wait for it to initialize */
msleep(150);

- for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
+ timeout = jiffies + msecs_to_jiffies(i2c_detect_tries*150);
+ for (i = 0, success = 0; ; i++) {
if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
(i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
success = 1;
- continue;
+ break;
}

/* Reset the sensor */
@@ -1159,6 +1161,9 @@ init_ov_sensor(struct usb_ov511 *ov)
/* Dummy read to sync I2C */
if (i2c_r(ov, 0x00) < 0)
return -EIO;
+
+ if (time_after(timeout, jiffies))
+ break;
}

if (!success)
diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/media/video/ovcamchip/ovcamchip_core.c
b/drivers/media/video/ovcamchip/ovcamchip_core.c
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c 2006-07-27
21:56:09.000000000 +0600
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c 2006-07-28
01:43:07.000000000 +0600
@@ -124,6 +124,7 @@ static int init_camchip(struct i2c_clien
{
int i, success;
unsigned char high, low;
+ unsigned long timeout;

/* Reset the chip */
ov_write(c, 0x12, 0x80);
@@ -131,12 +132,13 @@ static int init_camchip(struct i2c_clien
/* Wait for it to initialize */
msleep(150);

- for (i = 0, success = 0; i < I2C_DETECT_RETRIES && !success; i++) {
+ timeout = jiffies + msecs_to_jiffies(I2C_DETECT_RETRIES*150);
+ for (i = 0, success = 0; ; i++) {
if (ov_read(c, GENERIC_REG_ID_HIGH, &high) >= 0) {
if (ov_read(c, GENERIC_REG_ID_LOW, &low) >= 0) {
if (high == 0x7F && low == 0xA2) {
success = 1;
- continue;
+ break;
}
}
}
@@ -149,6 +151,10 @@ static int init_camchip(struct i2c_clien

/* Dummy read to sync I2C */
ov_read(c, 0x00, &low);
+
+ if (time_after(timeout, jiffies)) {
+ break;
+ }
}

if (!success)
diff -upr -X linux-2.6.17/Documentation/dontdiff a/drivers/pcmcia/cs.c
b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c 2006-07-27 21:56:12.000000000 +0600
+++ b/drivers/pcmcia/cs.c 2006-07-28 01:53:57.000000000 +0600
@@ -419,7 +419,8 @@ static void socket_shutdown(struct pcmci

static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
{
- int status, i;
+ int status;
+ unsigned long timeout;

cs_dbg(skt, 4, "setup\n");

@@ -429,7 +430,8 @@ static int socket_setup(struct pcmcia_so

msleep(initial_delay * 10);

- for (i = 0; i < 100; i++) {
+ timeout = jiffies + msecs_to_jiffies(10000);
+ for (;;) {
skt->ops->get_status(skt, &status);
if (!(status & SS_DETECT))
return CS_NO_CARD;
@@ -437,6 +439,9 @@ static int socket_setup(struct pcmcia_so
if (!(status & SS_PENDING))
break;

+ if (time_after(timeout, jiffies))
+ break;
+
msleep(100);
}

diff -upr -X linux-2.6.17/Documentation/dontdiff
a/drivers/serial/icom.c b/drivers/serial/icom.c
--- a/drivers/serial/icom.c 2006-07-27 21:56:12.000000000 +0600
+++ b/drivers/serial/icom.c 2006-07-28 09:53:19.000000000 +0600
@@ -349,6 +349,7 @@ static void load_code(struct icom_port *
unsigned char *new_page = NULL;
unsigned char cable_id = NO_CABLE;
struct pci_dev *dev = icom_port->adapter->pci_dev;
+ unsigned long timeout;

/* Clear out any pending interrupts */
writew(0x3FFF, icom_port->int_reg);
@@ -460,15 +461,17 @@ static void load_code(struct icom_port *
writeb(START_DOWNLOAD, &icom_port->dram->sync);

/* Wait max 1 Sec for data download and processor to start */
- for (index = 0; index < 10; index++) {
+ timeout = jiffies + msecs_to_jiffies(1000);
+ for (;;) {
msleep(100);
if (readb(&icom_port->dram->misc_flags) & ICOM_HDW_ACTIVE)
break;
+ if (time_after(timeout, jiffies)) {
+ status = -1;
+ break;
+ }
}

- if (index == 10)
- status = -1;
-
/*
* check Cable ID
*/
diff -upr -X linux-2.6.17/Documentation/dontdiff
a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
--- a/sound/isa/cs423x/cs4231_lib.c 2006-07-27 21:55:44.000000000 +0600
+++ b/sound/isa/cs423x/cs4231_lib.c 2006-07-28 10:09:25.000000000 +0600
@@ -322,7 +322,7 @@ void snd_cs4231_mce_up(struct snd_cs4231

void snd_cs4231_mce_down(struct snd_cs4231 *chip)
{
- unsigned long flags;
+ unsigned long flags, timeout_l;
int timeout;

snd_cs4231_busy_wait(chip);
@@ -358,9 +358,9 @@ void snd_cs4231_mce_down(struct snd_cs42
printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
#endif
/* in 10 ms increments, check condition, up to 250 ms */
- timeout = 25;
+ timeout_l = jiffies + msecs_to_jiffies(250);
while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
- if (--timeout < 0) {
+ if (time_after(timeout_l, jiffies)){
snd_printk("mce_down - auto calibration time out (2)\n");
return;
}
@@ -370,9 +370,9 @@ void snd_cs4231_mce_down(struct snd_cs42
printk("(3) jiffies = %li\n", jiffies);
#endif
/* in 10 ms increments, check condition, up to 100 ms */
- timeout = 10;
+ timeout_l = jiffies + msecs_to_jiffies(100);
while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
- if (--timeout < 0) {
+ if (time_after(timeout_l, jiffies)){
snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
return;
}
diff -upr -X linux-2.6.17/Documentation/dontdiff
a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
--- a/sound/pci/cs46xx/cs46xx_lib.c 2006-07-27 21:55:45.000000000 +0600
+++ b/sound/pci/cs46xx/cs46xx_lib.c 2006-07-28 10:43:13.000000000 +0600
@@ -2379,8 +2379,9 @@ static void snd_cs46xx_codec_reset (stru

static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
{
- int idx, err;
+ int err;
struct snd_ac97_template ac97;
+ unsigned long timeout;

memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
@@ -2399,11 +2400,15 @@ static int __devinit cs46xx_detect_codec
}

snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec);
- for (idx = 0; idx < 100; ++idx) {
+ timeout = jiffies + msecs_to_jiffies(1000);
+ for (;;) {
if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) {
err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]);
return err;
}
+ if (time_after(timeout, jiffies)){
+ break;
+ }
msleep(10);
}
snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec);
@@ -2913,7 +2918,7 @@ static int snd_cs46xx_dev_free(struct sn
*/
static int snd_cs46xx_chip_init(struct snd_cs46xx *chip)
{
- int timeout;
+ unsigned long timeout;

/*
* First, blast the clock control register to zero so that the PLL starts
@@ -3036,8 +3041,8 @@ static int snd_cs46xx_chip_init(struct s
/*
* Wait for the codec ready signal from the AC97 codec.
*/
- timeout = 150;
- while (timeout-- > 0) {
+ timeout = jiffies + msecs_to_jiffies(1500);
+ while (!time_after(timeout, jiffies)) {
/*
* Read the AC97 status register to see if we've seen a CODEC READY
* signal from the AC97 codec.
@@ -3085,8 +3090,8 @@ static int snd_cs46xx_chip_init(struct s
* Wait until we've sampled input slots 3 and 4 as valid, meaning that
* the codec is pumping ADC data across the AC-link.
*/
- timeout = 150;
- while (timeout-- > 0) {
+ timeout = jiffies + msecs_to_jiffies(1500);
+ while (!time_after(timeout, jiffies)) {
/*
* Read the input slot valid register and see if input slots 3 and
* 4 are valid yet.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/