ChangeSet 1.1372.2.4, 2003/07/09 20:51:05-07:00, mdharm-usb@one-eyed-alien.net [PATCH] USB: fix datafab and freecom to use I/O buffer This patch makes the Datafab and the Freecom driver both use the I/O safe buffer us->iobuf instead of local stack or local allocations. drivers/usb/storage/datafab.c | 90 ++++++++++++++++++++++++++++-------------- drivers/usb/storage/freecom.c | 33 +++------------ 2 files changed, 68 insertions(+), 55 deletions(-) diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c --- a/drivers/usb/storage/datafab.c Thu Jul 10 16:01:37 2003 +++ b/drivers/usb/storage/datafab.c Thu Jul 10 16:01:37 2003 @@ -94,7 +94,7 @@ unsigned char *dest, int use_sg) { - unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x20, 0x01 }; + unsigned char *command = us->iobuf; unsigned char *buffer = NULL; unsigned char *ptr; unsigned char thistime; @@ -116,8 +116,6 @@ return rc; } - command[5] += (info->lun << 4); - totallen = sectors * info->ssize; do { @@ -138,10 +136,13 @@ command[3] = (sector >> 8) & 0xFF; command[4] = (sector >> 16) & 0xFF; + command[5] = 0xE0 + (info->lun << 4); command[5] |= (sector >> 24) & 0x0F; + command[6] = 0x20; + command[7] = 0x01; // send the read command - result = datafab_bulk_write(us, command, sizeof(command)); + result = datafab_bulk_write(us, command, 8); if (result != USB_STOR_XFER_GOOD) goto leave; @@ -180,8 +181,8 @@ unsigned char *src, int use_sg) { - unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x30, 0x02 }; - unsigned char reply[2] = { 0, 0 }; + unsigned char *command = us->iobuf; + unsigned char *reply = us->iobuf; unsigned char *buffer = NULL; unsigned char *ptr; unsigned char thistime; @@ -202,8 +203,6 @@ return rc; } - command[5] += (info->lun << 4); - // If we're using scatter-gather, we have to create a new // buffer to read all of the data in first, since a // scatter-gather buffer could in theory start in the middle @@ -237,10 +236,13 @@ command[3] = (sector >> 8) & 0xFF; command[4] = (sector >> 16) & 0xFF; + command[5] = 0xE0 + (info->lun << 4); command[5] |= (sector >> 24) & 0x0F; + command[6] = 0x30; + command[7] = 0x02; // send the command - result = datafab_bulk_write(us, command, sizeof(command)); + result = datafab_bulk_write(us, command, 8); if (result != USB_STOR_XFER_GOOD) goto leave; @@ -250,7 +252,7 @@ goto leave; // read the result - result = datafab_bulk_read(us, reply, sizeof(reply)); + result = datafab_bulk_read(us, reply, 2); if (result != USB_STOR_XFER_GOOD) goto leave; @@ -291,13 +293,19 @@ // // There might be a better way of doing this? - unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; - unsigned char buf[512]; + static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; + unsigned char *command = us->iobuf; + unsigned char *buf; int count = 0, rc; if (!us || !info) return USB_STOR_TRANSPORT_ERROR; + memcpy(command, scommand, 8); + buf = kmalloc(512, GFP_NOIO); + if (!buf) + return USB_STOR_TRANSPORT_ERROR; + US_DEBUGP("datafab_determine_lun: locating...\n"); // we'll try 3 times before giving up... @@ -306,31 +314,41 @@ command[5] = 0xa0; rc = datafab_bulk_write(us, command, 8); - if (rc != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; + if (rc != USB_STOR_XFER_GOOD) { + rc = USB_STOR_TRANSPORT_ERROR; + goto leave; + } - rc = datafab_bulk_read(us, buf, sizeof(buf)); + rc = datafab_bulk_read(us, buf, 512); if (rc == USB_STOR_XFER_GOOD) { info->lun = 0; - return USB_STOR_TRANSPORT_GOOD; + rc = USB_STOR_TRANSPORT_GOOD; + goto leave; } command[5] = 0xb0; rc = datafab_bulk_write(us, command, 8); - if (rc != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; + if (rc != USB_STOR_XFER_GOOD) { + rc = USB_STOR_TRANSPORT_ERROR; + goto leave; + } - rc = datafab_bulk_read(us, buf, sizeof(buf)); + rc = datafab_bulk_read(us, buf, 512); if (rc == USB_STOR_XFER_GOOD) { info->lun = 1; - return USB_STOR_TRANSPORT_GOOD; + rc = USB_STOR_TRANSPORT_GOOD; + goto leave; } wait_ms(20); } - return USB_STOR_TRANSPORT_ERROR; + rc = USB_STOR_TRANSPORT_ERROR; + + leave: + kfree(buf); + return rc; } static int datafab_id_device(struct us_data *us, @@ -340,8 +358,9 @@ // to the ATA spec, 'Sector Count' isn't used but the Windows driver // sets this bit so we do too... // - unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; - unsigned char reply[512]; + static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; + unsigned char *command = us->iobuf; + unsigned char *reply; int rc; if (!us || !info) @@ -353,11 +372,18 @@ return rc; } + memcpy(command, scommand, 8); + reply = kmalloc(512, GFP_NOIO); + if (!reply) + return USB_STOR_TRANSPORT_ERROR; + command[5] += (info->lun << 4); rc = datafab_bulk_write(us, command, 8); - if (rc != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; + if (rc != USB_STOR_XFER_GOOD) { + rc = USB_STOR_TRANSPORT_ERROR; + goto leave; + } // we'll go ahead and extract the media capacity while we're here... // @@ -369,10 +395,15 @@ ((u32)(reply[116]) << 16) | ((u32)(reply[115]) << 8) | ((u32)(reply[114]) ); - return USB_STOR_TRANSPORT_GOOD; + rc = USB_STOR_TRANSPORT_GOOD; + goto leave; } - - return USB_STOR_TRANSPORT_ERROR; + + rc = USB_STOR_TRANSPORT_ERROR; + + leave: + kfree(reply); + return rc; } @@ -571,8 +602,7 @@ return USB_STOR_TRANSPORT_ERROR; } - // don't bother implementing READ_6 or WRITE_6. Just set MODE_XLATE and - // let the usb storage code convert to READ_10/WRITE_10 + // don't bother implementing READ_6 or WRITE_6. // if (srb->cmnd[0] == READ_10) { block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c --- a/drivers/usb/storage/freecom.c Thu Jul 10 16:01:37 2003 +++ b/drivers/usb/storage/freecom.c Thu Jul 10 16:01:37 2003 @@ -44,11 +44,6 @@ #define ERR_STAT 0x01 #define DRQ_STAT 0x08 -struct freecom_udata { - u8 buffer[64]; /* Common command block. */ -}; -typedef struct freecom_udata *freecom_udata_t; - /* All of the outgoing packets are 64 bytes long. */ struct freecom_cb_wrap { u8 Type; /* Command type. */ @@ -112,9 +107,8 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us, unsigned int ipipe, unsigned int opipe, int count) { - freecom_udata_t extra = (freecom_udata_t) us->extra; struct freecom_xfer_wrap *fxfr = - (struct freecom_xfer_wrap *) extra->buffer; + (struct freecom_xfer_wrap *) us->iobuf; int result; fxfr->Type = FCM_PACKET_INPUT | 0x00; @@ -147,9 +141,8 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us, int unsigned ipipe, unsigned int opipe, int count) { - freecom_udata_t extra = (freecom_udata_t) us->extra; struct freecom_xfer_wrap *fxfr = - (struct freecom_xfer_wrap *) extra->buffer; + (struct freecom_xfer_wrap *) us->iobuf; int result; fxfr->Type = FCM_PACKET_OUTPUT | 0x00; @@ -190,12 +183,9 @@ int result; unsigned int partial; int length; - freecom_udata_t extra; - extra = (freecom_udata_t) us->extra; - - fcb = (struct freecom_cb_wrap *) extra->buffer; - fst = (struct freecom_status *) extra->buffer; + fcb = (struct freecom_cb_wrap *) us->iobuf; + fst = (struct freecom_status *) us->iobuf; US_DEBUGP("Freecom TRANSPORT STARTED\n"); @@ -386,18 +376,11 @@ freecom_init (struct us_data *us) { int result; - char buffer[33]; + char *buffer = us->iobuf; - /* Allocate a buffer for us. The upper usb transport code will - * free this for us when cleaning up. */ - if (us->extra == NULL) { - us->extra = kmalloc (sizeof (struct freecom_udata), - GFP_KERNEL); - if (us->extra == NULL) { - US_DEBUGP("Out of memory\n"); - return USB_STOR_TRANSPORT_ERROR; - } - } + /* The DMA-mapped I/O buffer is 64 bytes long, just right for + * all our packets. No need to allocate any extra buffer space. + */ result = usb_stor_control_msg(us, us->recv_ctrl_pipe, 0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);