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

Reply via email to