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.
Greg, please apply.
Matt
# This is a BitKeeper generated patch for the following project:
# Project Name: greg k-h's linux 2.5 USB kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.719 -> 1.720
# drivers/usb/storage/usb.h 1.38 -> 1.39
# drivers/usb/storage/transport.c 1.87 -> 1.88
# drivers/usb/storage/usb.c 1.78 -> 1.79
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/28 [EMAIL PROTECTED] 1.720
# Switch to private I/O buffer for the 'core' subdrivers. This fixes the
# problem of DMAing to/from the stack and other otherwise improper places.
# --------------------------------------------
#
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c Sat Jun 28 20:32:11 2003
+++ b/drivers/usb/storage/transport.c Sat Jun 28 20:32:11 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 Sat Jun 28 20:32:11 2003
+++ b/drivers/usb/storage/usb.c Sat Jun 28 20:32:11 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 Sat Jun 28 20:32:11 2003
+++ b/drivers/usb/storage/usb.h Sat Jun 28 20:32:11 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 */
--
Matthew Dharm Home: [EMAIL PROTECTED]
Maintainer, Linux USB Mass Storage Driver
You suck Stef.
-- Greg
User Friendly, 11/29/97
pgp00000.pgp
Description: PGP signature
