Commit 808ba4b3 authored by Matthew Dharm's avatar Matthew Dharm Committed by Greg Kroah-Hartman

[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.
parent 02925ecf
...@@ -786,9 +786,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -786,9 +786,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
} }
/* STATUS STAGE */ /* 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_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) if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
...@@ -804,7 +804,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -804,7 +804,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->cmnd[0] == INQUIRY) srb->cmnd[0] == INQUIRY)
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
else { else {
if (us->irqdata[0]) if (us->iobuf[0])
return USB_STOR_TRANSPORT_FAILED; return USB_STOR_TRANSPORT_FAILED;
else else
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
...@@ -815,13 +815,13 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -815,13 +815,13 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
* The first byte should always be a 0x0 * The first byte should always be a 0x0
* The second byte & 0x0F should be 0x0 for good, otherwise error * 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_DEBUGP("CBI IRQ data showed reserved bType %d\n",
us->irqdata[0]); us->iobuf[0]);
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
switch (us->irqdata[1] & 0x0F) { switch (us->iobuf[1] & 0x0F) {
case 0x00: case 0x00:
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
case 0x01: case 0x01:
...@@ -889,7 +889,6 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -889,7 +889,6 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* Determine what the maximum LUN supported is */ /* Determine what the maximum LUN supported is */
int usb_stor_Bulk_max_lun(struct us_data *us) int usb_stor_Bulk_max_lun(struct us_data *us)
{ {
unsigned char data;
int result; int result;
/* issue the command */ /* issue the command */
...@@ -897,14 +896,14 @@ int usb_stor_Bulk_max_lun(struct us_data *us) ...@@ -897,14 +896,14 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
US_BULK_GET_MAX_LUN, US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS | USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE, 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", 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 we have a successful request, return the result */
if (result == 1) if (result == 1)
return data; return us->iobuf[0];
/* return the default -- no LUNs */ /* return the default -- no LUNs */
return 0; return 0;
...@@ -912,33 +911,34 @@ int usb_stor_Bulk_max_lun(struct us_data *us) ...@@ -912,33 +911,34 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
{ {
struct bulk_cb_wrap bcb; struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
struct bulk_cs_wrap bcs; struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
unsigned int transfer_length = srb->request_bufflen; unsigned int transfer_length = srb->request_bufflen;
int result; int result;
int fake_sense = 0; int fake_sense = 0;
/* set up the command wrapper */ /* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb.DataTransferLength = cpu_to_le32(transfer_length); bcb->DataTransferLength = cpu_to_le32(transfer_length);
bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number; bcb->Tag = srb->serial_number;
bcb.Lun = srb->device->lun; bcb->Lun = srb->device->lun;
if (us->flags & US_FL_SCM_MULT_TARG) if (us->flags & US_FL_SCM_MULT_TARG)
bcb.Lun |= srb->device->id << 4; bcb->Lun |= srb->device->id << 4;
bcb.Length = srb->cmd_len; bcb->Length = srb->cmd_len;
/* copy the command payload */ /* copy the command payload */
memset(bcb.CDB, 0, sizeof(bcb.CDB)); memset(bcb->CDB, 0, sizeof(bcb->CDB));
memcpy(bcb.CDB, srb->cmnd, bcb.Length); memcpy(bcb->CDB, srb->cmnd, bcb->Length);
/* send it to out endpoint */ /* 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", 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, le32_to_cpu(bcb->Signature), bcb->Tag,
(bcb.Lun >> 4), (bcb.Lun & 0x0F), (bcb->Lun >> 4), (bcb->Lun & 0x0F),
le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length); le32_to_cpu(bcb->DataTransferLength),
bcb->Flags, bcb->Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, 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); US_DEBUGP("Bulk command transfer result=%d\n", result);
if (result != USB_STOR_XFER_GOOD) if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
...@@ -972,7 +972,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -972,7 +972,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get CSW for device status */ /* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n"); US_DEBUGP("Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, 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? */ /* did the attempt to read the CSW fail? */
if (result == USB_STOR_XFER_STALLED) { if (result == USB_STOR_XFER_STALLED) {
...@@ -980,7 +980,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -980,7 +980,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get the status again */ /* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n"); US_DEBUGP("Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, 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 */ /* if we still have a failure at this point, we're in trouble */
...@@ -990,17 +990,18 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -990,17 +990,18 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* check bulk status */ /* check bulk status */
US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n", US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
le32_to_cpu(bcs.Signature), bcs.Tag, le32_to_cpu(bcs->Signature), bcs->Tag,
bcs.Residue, bcs.Status); bcs->Residue, bcs->Status);
if ((bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs.Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
bcs.Tag != bcb.Tag || bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
bcs.Status > US_BULK_STAT_PHASE) { bcs->Tag != srb->serial_number ||
bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n"); US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
/* based on the status code, we report good or bad */ /* based on the status code, we report good or bad */
switch (bcs.Status) { switch (bcs->Status) {
case US_BULK_STAT_OK: case US_BULK_STAT_OK:
/* device babbled -- return fake sense data */ /* device babbled -- return fake sense data */
if (fake_sense) { if (fake_sense) {
...@@ -1087,18 +1088,18 @@ static int usb_stor_reset_common(struct us_data *us, ...@@ -1087,18 +1088,18 @@ static int usb_stor_reset_common(struct us_data *us,
/* This issues a CB[I] Reset to the device in question /* 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) int usb_stor_CB_reset(struct us_data *us)
{ {
unsigned char cmd[12]; US_DEBUGP("%s called\n", __FUNCTION__);
US_DEBUGP("CB_reset() called\n");
memset(cmd, 0xFF, sizeof(cmd)); memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
cmd[0] = SEND_DIAGNOSTIC; us->iobuf[0] = SEND_DIAGNOSTIC;
cmd[1] = 4; us->iobuf[1] = 4;
return usb_stor_reset_common(us, US_CBI_ADSC, return usb_stor_reset_common(us, US_CBI_ADSC,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, 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 /* This issues a Bulk-only Reset to the device in question, including
...@@ -1106,7 +1107,7 @@ int usb_stor_CB_reset(struct us_data *us) ...@@ -1106,7 +1107,7 @@ int usb_stor_CB_reset(struct us_data *us)
*/ */
int usb_stor_Bulk_reset(struct us_data *us) 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, return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
......
...@@ -743,17 +743,21 @@ static int usb_stor_acquire_resources(struct us_data *us) ...@@ -743,17 +743,21 @@ static int usb_stor_acquire_resources(struct us_data *us)
int p; int p;
/* Allocate the USB control blocks */ /* Allocate the USB control blocks */
US_DEBUGP("Allocating usb_ctrlrequest\n");
us->dr = kmalloc(sizeof(*us->dr), GFP_KERNEL); us->dr = kmalloc(sizeof(*us->dr), GFP_KERNEL);
if (!us->dr) { if (!us->dr) {
US_DEBUGP("allocation failed\n"); US_DEBUGP("usb_ctrlrequest allocation failed\n");
return -ENOMEM; return -ENOMEM;
} }
US_DEBUGP("Allocating URB\n");
us->current_urb = usb_alloc_urb(0, GFP_KERNEL); us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!us->current_urb) { 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; return -ENOMEM;
} }
...@@ -852,6 +856,8 @@ void usb_stor_release_resources(struct us_data *us) ...@@ -852,6 +856,8 @@ void usb_stor_release_resources(struct us_data *us)
} }
/* Free the USB control blocks */ /* Free the USB control blocks */
if (us->iobuf)
kfree(us->iobuf);
if (us->current_urb) if (us->current_urb)
usb_free_urb(us->current_urb); usb_free_urb(us->current_urb);
if (us->dr) if (us->dr)
......
...@@ -92,6 +92,8 @@ struct us_unusual_dev { ...@@ -92,6 +92,8 @@ struct us_unusual_dev {
#define USB_STOR_STRING_LEN 32 #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_cmnd)(Scsi_Cmnd*, struct us_data*);
typedef int (*trans_reset)(struct us_data*); typedef int (*trans_reset)(struct us_data*);
typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
...@@ -139,13 +141,11 @@ struct us_data { ...@@ -139,13 +141,11 @@ struct us_data {
int pid; /* control thread */ int pid; /* control thread */
int sm_state; /* what we are doing */ int sm_state; /* what we are doing */
/* interrupt communications data */
unsigned char irqdata[2]; /* data from USB IRQ */
/* control and bulk communications data */ /* control and bulk communications data */
struct urb *current_urb; /* non-int USB requests */ struct urb *current_urb; /* non-int USB requests */
struct usb_ctrlrequest *dr; /* control requests */ struct usb_ctrlrequest *dr; /* control requests */
struct usb_sg_request current_sg; /* scatter-gather USB */ struct usb_sg_request current_sg; /* scatter-gather USB */
unsigned char *iobuf; /* I/O buffer */
/* the semaphore for sleeping the control thread */ /* the semaphore for sleeping the control thread */
struct semaphore sema; /* to sleep thread on */ struct semaphore sema; /* to sleep thread on */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment