ChangeSet 1.1508.1.5, 2003/06/30 10:59:06-07:00, mdharm-usb@one-eyed-alien.net [PATCH] USB storage: create private I/O buffer This patch creates a private I/O buffer for the 'core' subdrivers. This allows us to fix all cases of DMAing to/from the stacks, statics, or other bad places. drivers/usb/storage/transport.c | 83 ++++++++++++++++++++-------------------- drivers/usb/storage/usb.c | 14 ++++-- drivers/usb/storage/usb.h | 6 +- 3 files changed, 55 insertions(+), 48 deletions(-) diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Tue Jul 1 14:24:13 2003 +++ b/drivers/usb/storage/transport.c Tue Jul 1 14:24:13 2003 @@ -786,9 +786,9 @@ } /* STATUS STAGE */ - result = usb_stor_intr_transfer(us, us->irqdata, sizeof(us->irqdata)); + result = usb_stor_intr_transfer(us, us->iobuf, 2); US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", - us->irqdata[0], us->irqdata[1]); + us->iobuf[0], us->iobuf[1]); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -804,7 +804,7 @@ srb->cmnd[0] == INQUIRY) return USB_STOR_TRANSPORT_GOOD; else { - if (us->irqdata[0]) + if (us->iobuf[0]) return USB_STOR_TRANSPORT_FAILED; else return USB_STOR_TRANSPORT_GOOD; @@ -815,13 +815,13 @@ * The first byte should always be a 0x0 * The second byte & 0x0F should be 0x0 for good, otherwise error */ - if (us->irqdata[0]) { + if (us->iobuf[0]) { US_DEBUGP("CBI IRQ data showed reserved bType %d\n", - us->irqdata[0]); + us->iobuf[0]); return USB_STOR_TRANSPORT_ERROR; } - switch (us->irqdata[1] & 0x0F) { + switch (us->iobuf[1] & 0x0F) { case 0x00: return USB_STOR_TRANSPORT_GOOD; case 0x01: @@ -889,7 +889,6 @@ /* Determine what the maximum LUN supported is */ int usb_stor_Bulk_max_lun(struct us_data *us) { - unsigned char data; int result; /* issue the command */ @@ -897,14 +896,14 @@ US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, &data, sizeof(data), HZ); + 0, us->ifnum, us->iobuf, 1, HZ); US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", - result, data); + result, us->iobuf[0]); /* if we have a successful request, return the result */ if (result == 1) - return data; + return us->iobuf[0]; /* return the default -- no LUNs */ return 0; @@ -912,33 +911,34 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) { - struct bulk_cb_wrap bcb; - struct bulk_cs_wrap bcs; + struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; unsigned int transfer_length = srb->request_bufflen; int result; int fake_sense = 0; /* set up the command wrapper */ - bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN); - bcb.DataTransferLength = cpu_to_le32(transfer_length); - bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; - bcb.Tag = srb->serial_number; - bcb.Lun = srb->device->lun; + bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); + bcb->DataTransferLength = cpu_to_le32(transfer_length); + bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; + bcb->Tag = srb->serial_number; + bcb->Lun = srb->device->lun; if (us->flags & US_FL_SCM_MULT_TARG) - bcb.Lun |= srb->device->id << 4; - bcb.Length = srb->cmd_len; + bcb->Lun |= srb->device->id << 4; + bcb->Length = srb->cmd_len; /* copy the command payload */ - memset(bcb.CDB, 0, sizeof(bcb.CDB)); - memcpy(bcb.CDB, srb->cmnd, bcb.Length); + memset(bcb->CDB, 0, sizeof(bcb->CDB)); + memcpy(bcb->CDB, srb->cmnd, bcb->Length); /* send it to out endpoint */ US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n", - le32_to_cpu(bcb.Signature), bcb.Tag, - (bcb.Lun >> 4), (bcb.Lun & 0x0F), - le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length); + le32_to_cpu(bcb->Signature), bcb->Tag, + (bcb->Lun >> 4), (bcb->Lun & 0x0F), + le32_to_cpu(bcb->DataTransferLength), + bcb->Flags, bcb->Length); result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, - &bcb, US_BULK_CB_WRAP_LEN, NULL); + bcb, US_BULK_CB_WRAP_LEN, NULL); US_DEBUGP("Bulk command transfer result=%d\n", result); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -972,7 +972,7 @@ /* get CSW for device status */ US_DEBUGP("Attempting to get CSW...\n"); result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - &bcs, US_BULK_CS_WRAP_LEN, NULL); + bcs, US_BULK_CS_WRAP_LEN, NULL); /* did the attempt to read the CSW fail? */ if (result == USB_STOR_XFER_STALLED) { @@ -980,7 +980,7 @@ /* get the status again */ US_DEBUGP("Attempting to get CSW (2nd try)...\n"); result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - &bcs, US_BULK_CS_WRAP_LEN, NULL); + bcs, US_BULK_CS_WRAP_LEN, NULL); } /* if we still have a failure at this point, we're in trouble */ @@ -990,17 +990,18 @@ /* check bulk status */ US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n", - le32_to_cpu(bcs.Signature), bcs.Tag, - bcs.Residue, bcs.Status); - if ((bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs.Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || - bcs.Tag != bcb.Tag || - bcs.Status > US_BULK_STAT_PHASE) { + le32_to_cpu(bcs->Signature), bcs->Tag, + bcs->Residue, bcs->Status); + if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) && + bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || + bcs->Tag != srb->serial_number || + bcs->Status > US_BULK_STAT_PHASE) { US_DEBUGP("Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR; } /* based on the status code, we report good or bad */ - switch (bcs.Status) { + switch (bcs->Status) { case US_BULK_STAT_OK: /* device babbled -- return fake sense data */ if (fake_sense) { @@ -1087,18 +1088,18 @@ /* This issues a CB[I] Reset to the device in question */ +#define CB_RESET_CMD_SIZE 12 + int usb_stor_CB_reset(struct us_data *us) { - unsigned char cmd[12]; - - US_DEBUGP("CB_reset() called\n"); + US_DEBUGP("%s called\n", __FUNCTION__); - memset(cmd, 0xFF, sizeof(cmd)); - cmd[0] = SEND_DIAGNOSTIC; - cmd[1] = 4; + memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE); + us->iobuf[0] = SEND_DIAGNOSTIC; + us->iobuf[1] = 4; return usb_stor_reset_common(us, US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, cmd, sizeof(cmd)); + 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE); } /* This issues a Bulk-only Reset to the device in question, including @@ -1106,7 +1107,7 @@ */ int usb_stor_Bulk_reset(struct us_data *us) { - US_DEBUGP("Bulk reset requested\n"); + US_DEBUGP("%s called\n", __FUNCTION__); return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, USB_TYPE_CLASS | USB_RECIP_INTERFACE, diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c --- a/drivers/usb/storage/usb.c Tue Jul 1 14:24:13 2003 +++ b/drivers/usb/storage/usb.c Tue Jul 1 14:24:13 2003 @@ -743,17 +743,21 @@ int p; /* Allocate the USB control blocks */ - US_DEBUGP("Allocating usb_ctrlrequest\n"); us->dr = kmalloc(sizeof(*us->dr), GFP_KERNEL); if (!us->dr) { - US_DEBUGP("allocation failed\n"); + US_DEBUGP("usb_ctrlrequest allocation failed\n"); return -ENOMEM; } - US_DEBUGP("Allocating URB\n"); us->current_urb = usb_alloc_urb(0, GFP_KERNEL); if (!us->current_urb) { - US_DEBUGP("allocation failed\n"); + US_DEBUGP("URB allocation failed\n"); + return -ENOMEM; + } + + us->iobuf = kmalloc(US_IOBUF_SIZE, GFP_KERNEL); + if (!us->iobuf) { + US_DEBUGP("I/O buffer allocation failed\n"); return -ENOMEM; } @@ -852,6 +856,8 @@ } /* Free the USB control blocks */ + if (us->iobuf) + kfree(us->iobuf); if (us->current_urb) usb_free_urb(us->current_urb); if (us->dr) diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h --- a/drivers/usb/storage/usb.h Tue Jul 1 14:24:13 2003 +++ b/drivers/usb/storage/usb.h Tue Jul 1 14:24:13 2003 @@ -92,6 +92,8 @@ #define USB_STOR_STRING_LEN 32 +#define US_IOBUF_SIZE 32 /* Big enough for bulk-only CBW */ + typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*); typedef int (*trans_reset)(struct us_data*); typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); @@ -139,13 +141,11 @@ int pid; /* control thread */ int sm_state; /* what we are doing */ - /* interrupt communications data */ - unsigned char irqdata[2]; /* data from USB IRQ */ - /* control and bulk communications data */ struct urb *current_urb; /* non-int USB requests */ struct usb_ctrlrequest *dr; /* control requests */ struct usb_sg_request current_sg; /* scatter-gather USB */ + unsigned char *iobuf; /* I/O buffer */ /* the semaphore for sleeping the control thread */ struct semaphore sema; /* to sleep thread on */