[PATCH]dma rules violation in the option driver
Oliver Neukum <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Organization | Novell |
| Message-ID | <[email protected]> |
Hi, the option driver - allocations 17K with kmalloc - violates dma rules on inconsistent architectures This patch fixes that using an array of USB buffers. Regards Oliver Signed-off-by: Oliver Neukum <[email protected]> ----- --- a/drivers/usb/serial/option.c 2007-03-27 13:31:04.000000000 +0200 +++ b/drivers/usb/serial/option.c 2007-03-27 14:21:21.000000000 +0200 @@ -226,10 +226,12 @@ struct option_port_private { /* Input endpoints and buffer for this port */ struct urb *in_urbs[N_IN_URB]; - char in_buffer[N_IN_URB][IN_BUFLEN]; + u8 *in_buffer[N_IN_URB]; + dma_addr_t in_dma[N_IN_URB]; /* Output endpoints and buffer for this port */ struct urb *out_urbs[N_OUT_URB]; - char out_buffer[N_OUT_URB][OUT_BUFLEN]; + u8 *out_buffer[N_OUT_URB]; + dma_addr_t out_dma[N_IN_URB]; /* Settings for the port */ int rts_state; /* Handshaking pins (outputs) */ @@ -617,7 +619,7 @@ /* Helper functions used by option_setup_urbs */ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, - int dir, void *ctx, char *buf, int len, + int dir, void *ctx, u8 **buf, int len, dma_addr_t *handle, void (*callback)(struct urb *)) { struct urb *urb; @@ -627,14 +629,23 @@ urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (urb == NULL) { - dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint); + dbg("%s: allocation of an urb for endpoint %d failed.", __FUNCTION__, endpoint); + return NULL; + } + + *buf = usb_buffer_alloc(serial->dev, len, GFP_KERNEL, handle); + if (*buf == NULL) { + dbg("%s: allocation of a buffer for endpoint %d failed.", __FUNCTION__, endpoint); + usb_free_urb(urb); return NULL; } /* Fill URB using supplied data. */ usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, endpoint) | dir, - buf, len, callback, ctx); + *buf, len, callback, ctx); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + urb->transfer_dma = *handle; return urb; } @@ -656,14 +667,14 @@ for (j = 0; j < N_IN_URB; ++j) { portdata->in_urbs[j] = option_setup_urb (serial, port->bulk_in_endpointAddress, USB_DIR_IN, port, - portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); + &portdata->in_buffer[j], IN_BUFLEN, &portdata->in_dma[j], option_indat_callback); } /* outdat endpoints */ for (j = 0; j < N_OUT_URB; ++j) { portdata->out_urbs[j] = option_setup_urb (serial, port->bulk_out_endpointAddress, USB_DIR_OUT, port, - portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); + &portdata->out_buffer[j], OUT_BUFLEN, &portdata->out_dma[j], option_outdat_callback); } } } @@ -754,12 +765,16 @@ for (j = 0; j < N_IN_URB; j++) { if (portdata->in_urbs[j]) { usb_free_urb(portdata->in_urbs[j]); + usb_buffer_free(serial->dev, IN_BUFLEN, + portdata->in_buffer[j], portdata->in_dma[j]); portdata->in_urbs[j] = NULL; } } for (j = 0; j < N_OUT_URB; j++) { if (portdata->out_urbs[j]) { usb_free_urb(portdata->out_urbs[j]); + usb_buffer_free(serial->dev, OUT_BUFLEN, + portdata->out_buffer[j], portdata->out_dma[j]); portdata->out_urbs[j] = NULL; } } ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ [email protected] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel