Hi,
the driver uses a common buffer for all urbs. Unfortunately this
violates the coherency requirements. Fix by using usb_buffer_alloc().
Regards
Oliver
Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.
===================================================================
[EMAIL PROTECTED], 2004-05-31 22:50:21+02:00, [EMAIL PROTECTED]
- fix dma coherency bug
cdc-acm.c | 77 +++++++++++++++++++++++++++++++++++++++++---------------------
cdc-acm.h | 3 ++
2 files changed, 54 insertions(+), 26 deletions(-)
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c Mon May 31 22:50:49 2004
+++ b/drivers/usb/class/cdc-acm.c Mon May 31 22:50:49 2004
@@ -522,7 +522,7 @@
struct acm *acm;
int minor;
int ctrlsize,readsize;
- char *buf;
+ u8 *buf;
u8 ac_management_function = 0;
u8 call_management_function = 0;
int call_interface_num = -1;
@@ -629,7 +629,7 @@
if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
- return -ENOMEM;
+ goto alloc_fail;
}
memset(acm, 0, sizeof(struct acm));
@@ -641,55 +641,62 @@
acm->minor = minor;
acm->dev = usb_dev;
acm->ctrl_caps = ac_management_function;
-
+ acm->ctrlsize = ctrlsize;
+ acm->readsize = readsize;
acm->bh.func = acm_rx_tasklet;
acm->bh.data = (unsigned long) acm;
INIT_WORK(&acm->work, acm_softint, acm);
spin_lock_init(&acm->throttle_lock);
acm->ready_for_write = 1;
-
- if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
- dev_dbg(&intf->dev, "out of memory (buf kmalloc)\n");
- kfree(acm);
- return -ENOMEM;
+ buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
+ if (!buf) {
+ dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
+ goto alloc_fail2;
+ }
+ acm->ctrl_buffer = buf;
+
+ buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma);
+ if (!buf) {
+ dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n");
+ goto alloc_fail3;
+ }
+ acm->read_buffer = buf;
+
+ buf = usb_buffer_alloc(usb_dev, acm->writesize, GFP_KERNEL, &acm->write_dma);
+ if (!buf) {
+ dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
+ goto alloc_fail4;
}
+ acm->ctrl_buffer = buf;
acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->ctrlurb) {
dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
- kfree(acm);
- kfree(buf);
- return -ENOMEM;
+ goto alloc_fail5;
}
acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->readurb) {
dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n");
- usb_free_urb(acm->ctrlurb);
- kfree(acm);
- kfree(buf);
- return -ENOMEM;
+ goto alloc_fail6;
}
acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->writeurb) {
dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
- usb_free_urb(acm->readurb);
- usb_free_urb(acm->ctrlurb);
- kfree(acm);
- kfree(buf);
- return -ENOMEM;
+ goto alloc_fail7;
}
usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev,
epctrl->bEndpointAddress),
- buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
+ acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm,
epctrl->bInterval);
+ acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev,
epread->bEndpointAddress),
- buf += ctrlsize, readsize, acm_read_bulk, acm);
- acm->readurb->transfer_flags |= URB_NO_FSBR;
+ acm->read_buffer, readsize, acm_read_bulk, acm);
+ acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev,
epwrite->bEndpointAddress),
- buf += readsize, acm->writesize, acm_write_bulk, acm);
- acm->writeurb->transfer_flags |= URB_NO_FSBR;
+ acm->write_buffer, acm->writesize, acm_write_bulk, acm);
+ acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
@@ -706,11 +713,27 @@
acm_table[minor] = acm;
usb_set_intfdata (intf, acm);
return 0;
+
+alloc_fail7:
+ usb_free_urb(acm->readurb);
+alloc_fail6:
+ usb_free_urb(acm->ctrlurb);
+alloc_fail5:
+ usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma);
+alloc_fail4:
+ usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
+alloc_fail3:
+ usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
+alloc_fail2:
+ kfree(acm);
+alloc_fail:
+ return -ENOMEM;
}
static void acm_disconnect(struct usb_interface *intf)
{
struct acm *acm = usb_get_intfdata (intf);
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
if (!acm || !acm->dev) {
dbg("disconnect on nonexisting interface");
@@ -727,7 +750,9 @@
flush_scheduled_work(); /* wait for acm_softint */
- kfree(acm->ctrlurb->transfer_buffer);
+ usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma);
+ usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
+ usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
usb_driver_release_interface(&acm_driver, acm->data);
diff -Nru a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
--- a/drivers/usb/class/cdc-acm.h Mon May 31 22:50:49 2004
+++ b/drivers/usb/class/cdc-acm.h Mon May 31 22:50:49 2004
@@ -86,6 +86,8 @@
struct usb_interface *data; /* data interface */
struct tty_struct *tty; /* the corresponding tty */
struct urb *ctrlurb, *readurb, *writeurb; /* urbs */
+ u8 *ctrl_buffer, *read_buffer, *write_buffer; /* buffers of urbs */
+ dma_addr_t ctrl_dma, read_dma, write_dma; /* dma handles of buffers */
struct acm_line line; /* line coding (bits, stop,
parity) */
struct work_struct work; /* work queue entry for line
discipline waking up */
struct tasklet_struct bh; /* rx processing */
@@ -93,6 +95,7 @@
unsigned int ctrlin; /* input control lines (DCD,
DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR,
RTS) */
unsigned int writesize; /* max packet size for the
output bulk endpoint */
+ unsigned int readsize,ctrlsize; /* buffer sizes for freeing */
unsigned int used; /* someone has this acm's
device open */
unsigned int minor; /* acm minor number */
unsigned char throttle; /* throttled by tty layer */
===================================================================
This BitKeeper patch contains the following changesets:
1.1768
## Wrapped with gzip_uu ##
M'XL( *F:NT [U7:T_;2!3];/^*NZU4!9K'C-\)"BJ4T**6AT+Y5LF:C,>)
M16)3VZ'+UOO?]\[$"4Z !$*[@&3/S)USSYTYYUJ\A:M,I!TM&4>W(M7?PN<D
MRSO:A/&[EMAIL PROTECTED]:)1/1FL6WOJ5"9*V<&3JN7["<CP"G
MLXY&F^9B)[EMAIL PROTECTED]<[EMAIL PROTECTED]:Z>)^DM&P?9!Y:/QDG<
MS%,69Q.1LR9/)L4BM# (,?#7IJY);*>@#K'<@M. 4F91$1##\AQ+GQ'[\+"
M922+V";%)[7=PK;:Q-"/@#:IZWA K!:Q6R8%P^C8I&/0]\3H$ )/(L-[ QI$
M/X3?6\E'G4,#PNAO""8,>#(2J8CY'0RF0_T+2-*6?G%_E'KCA3^Z3AC1]S>P
M#E)9==::9H,6XY,FK["W",73<]RV4PRX:8>4AH9EAJ9P!T^?UA(B'[,L:_&
M-Q;8Y<W8A%HXM"P;*6X#-IJ#$>(:;6H4Q"2N5;B&0_C 85Z;N\RP^.NPYT1M
MUVN[2MIK-DFQ_\%*7H=-:9NXIE-8.&PK,SBK3J#69B>8?\X)TTQ )FY8RG*!
M)@A#K$@:01W].332G^H/A7VQ[A:V\,F)YX&A:U,/=GF>COU9\CKLIH(%]Z.?
M:92+<KBGM7;G)"$)89H.,MAMZ1IZV6=!D/HY*"P<UT'AJ+<9!KXJ &E\/*M@
M+!3(' [EMAIL PROTECTED]<:[EMAIL PROTECTED] \F5/T^YI@)S)($Q2"+%K1_%0
MXJR7+-_<G[?L#UN)E2]W;E+8-G'[EMAIL PROTECTED]"<_U>OLY[V;+WR+?1Z
M9!M2'2>SA](MYM_3CQS3D/.SAZ8-DSP!-AXGW ]9-)8!EJ4"\(&"Q_R-_;F8
MH L+795+<\'ATOQ58N"IVHAA8W)/US SKF-AI3-\E; F)P)Q6U^ UN'3\87_
MI=<_ZWVMP[M%;FF&'<P8A5#["R%VX!=2QZU^,!C6WJ'PP\:^0GJ33'-IDXF8
M).D=U.3NN?A5TIWO\1L)[EMAIL PROTECTED]/_5LHMF2)M=6S?-Q>QL-XC1<S-O5T1<O>S
MBC [EMAIL PROTECTED] WJJE$5WVJX6M?U9Q5A[4D".5.D3MZ*AT!P*)L8YYF-J
MMJ44L2U8&.'2QR(<&>$Z2JP>>2S"E1'>S!*>LH2FP2JAJH1QS5=+4?I#C>H@
M;N1$8W]P$N="=IF=O4I1^%UH[*MN(R\D'+-A!D47KOJ'_MFY_ZU_<'9YW.O[
M1Z<'_NG!A:+C(@^DXY5T8/7&JVJ4?,JE\;4:[E3-NS[[\>5A'XIU7-I4<6D;
M2URJW\&'JI*4YA&KG-3\ZTB=N,0#:J/>*]?8P2:(*I??/1_A:]4#P.0523P:
M65[44J1=1I96DAN>=M+:8RG]5!'_.NBENUVY]]5V4VD.ZR"7Y+LB[=4V7&F:
M"'FM@&8W>+^""ZG(IVD,C=[9^6GO5-X*52;-\G3*<RA31US ;OF.MHZD04+&
MA9\G/D[C;$UV$P0_PN^M=*%\F+_YX#>@O>3 -T"]Y* 7_SWSD>#7V732=;D3
-<&X:^G^Y2=Y!M \
-------------------------------------------------------
This SF.Net email is sponsored by: Oracle 10g
Get certified on the hottest thing ever to hit the market... Oracle 10g.
Take an Oracle 10g class now, and we'll give you the exam FREE.
http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel