Fix two theoretical races in atkbd

From: Pavel Machek
Date: Mon Apr 26 2004 - 16:15:01 EST


Hi!

This fixes two theoretical problems in atkbd.c.

1) It is not okay to use volatile char instead of atomic type. It
should not matter on most architectures.

2) Theoretical race on smp. atkbd->ack = 1 at the begining.

sendbyte:

atkbd->ack = 0;
serio_write()
atkbd_interrupt:
if (!atkbd->ack)
[cpu delayed write up-to now]
[acknowledge lost]

Memory barriers are needed to prevent that. Please apply,

Pavel

--- tmp/linux/drivers/input/keyboard/atkbd.c 2004-04-05 10:45:16.000000000 +0200
+++ linux/drivers/input/keyboard/atkbd.c 2004-04-26 23:01:12.000000000 +0200
@@ -182,7 +182,7 @@
unsigned char extra;
unsigned char release;
int lastkey;
- volatile signed char ack;
+ atomic_t ack; /* 0 .. nothing, 1 .. ACK, 2 .. NAK */
unsigned char emul;
unsigned short id;
unsigned char write;
@@ -233,13 +233,14 @@
atkbd->resend = 0;
#endif

- if (!atkbd->ack)
+ mb();
+ if (!atomic_read(&atkbd->ack))
switch (code) {
case ATKBD_RET_ACK:
- atkbd->ack = 1;
+ atomic_set(&atkbd->ack, 1);
goto out;
case ATKBD_RET_NAK:
- atkbd->ack = -1;
+ atomic_set(&atkbd->ack, 2);
goto out;
}

@@ -368,7 +369,7 @@
static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte)
{
int timeout = 20000; /* 200 msec */
- atkbd->ack = 0;
+ atomic_set(&atkbd->ack, 0); mb();

#ifdef ATKBD_DEBUG
printk(KERN_DEBUG "atkbd.c: Sent: %02x\n", byte);
@@ -376,9 +377,12 @@
if (serio_write(atkbd->serio, byte))
return -1;

- while (!atkbd->ack && timeout--) udelay(10);
+ while (!atomic_read(&atkbd->ack) && timeout--) {
+ udelay(10);
+ mb();
+ }

- return -(atkbd->ack <= 0);
+ return -(atomic_read(&atkbd->ack) != 1);
}

/*
@@ -710,7 +714,7 @@
atkbd->dev.rep[REP_PERIOD] = 33;
}

- atkbd->ack = 1;
+ atomic_set(&atkbd->ack, 1); mb();
atkbd->serio = serio;

init_input_dev(&atkbd->dev);

--
934a471f20d6580d5aad759bf0d97ddc
-
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/