ChangeSet 1.1722.83.9, 2004/06/02 13:49:28-07:00, [EMAIL PROTECTED]
[PATCH] USB: fix racy access to urb->status in cdc acm driver
Hi,
fix access to urb->status by introduction of an explicit flag
for finished data transfer.
- fix racy access to urb->status
Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
drivers/usb/class/cdc-acm.c | 16 ++++++++++------
drivers/usb/class/cdc-acm.h | 1 +
2 files changed, 11 insertions(+), 6 deletions(-)
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c Fri Jun 18 11:05:57 2004
+++ b/drivers/usb/class/cdc-acm.c Fri Jun 18 11:05:57 2004
@@ -223,12 +223,14 @@
struct acm *acm = (struct acm *)urb->context;
if (!ACM_READY(acm))
- return;
+ goto out;
if (urb->status)
dbg("nonzero write bulk status received: %d", urb->status);
schedule_work(&acm->work);
+out:
+ acm->ready_for_write = 1;
}
static void acm_softint(void *private)
@@ -328,7 +330,7 @@
if (!ACM_READY(acm))
return -EINVAL;
- if (acm->writeurb->status == -EINPROGRESS)
+ if (!acm->ready_for_write)
return 0;
if (!count)
return 0;
@@ -344,10 +346,11 @@
acm->writeurb->transfer_buffer_length = count;
acm->writeurb->dev = acm->dev;
- /* GFP_KERNEL probably works if from_user */
- stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC);
+ acm->ready_for_write = 0;
+ stat = usb_submit_urb(acm->writeurb, GFP_NOIO);
if (stat < 0) {
dbg("usb_submit_urb(write bulk) failed");
+ acm->ready_for_write = 1;
return stat;
}
@@ -359,7 +362,7 @@
struct acm *acm = tty->driver_data;
if (!ACM_READY(acm))
return -EINVAL;
- return acm->writeurb->status == -EINPROGRESS ? 0 : acm->writesize;
+ return !acm->ready_for_write ? 0 : acm->writesize;
}
static int acm_tty_chars_in_buffer(struct tty_struct *tty)
@@ -367,7 +370,7 @@
struct acm *acm = tty->driver_data;
if (!ACM_READY(acm))
return -EINVAL;
- return acm->writeurb->status == -EINPROGRESS ?
acm->writeurb->transfer_buffer_length : 0;
+ return !acm->ready_for_write ? acm->writeurb->transfer_buffer_length : 0;
}
static void acm_tty_throttle(struct tty_struct *tty)
@@ -610,6 +613,7 @@
acm->bh.func = acm_rx_tasklet;
acm->bh.data = (unsigned long) acm;
INIT_WORK(&acm->work, acm_softint, acm);
+ acm->ready_for_write = 1;
if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
diff -Nru a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
--- a/drivers/usb/class/cdc-acm.h Fri Jun 18 11:05:57 2004
+++ b/drivers/usb/class/cdc-acm.h Fri Jun 18 11:05:57 2004
@@ -96,6 +96,7 @@
unsigned int minor; /* acm minor number */
unsigned char throttle; /* throttled by tty layer */
unsigned char clocal; /* termios CLOCAL */
+ unsigned char ready_for_write; /* write urb can be used */
};
/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
-------------------------------------------------------
This SF.Net email is sponsored by The 2004 JavaOne(SM) Conference
Learn from the experts at JavaOne(SM), Sun's Worldwide Java Developer
Conference, June 28 - July 1 at the Moscone Center in San Francisco, CA
REGISTER AND SAVE! http://java.sun.com/javaone/sf Priority Code NWMGYKND
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel