patch-2.4.0-test10 linux/drivers/usb/storage/transport.c
Next file: linux/drivers/usb/storage/transport.h
Previous file: linux/drivers/usb/storage/sddr09.c
Back to the patch index
Back to the overall index
- Lines: 261
- Date:
Fri Oct 27 11:02:15 2000
- Orig file:
v2.4.0-test9/linux/drivers/usb/storage/transport.c
- Orig date:
Sun Oct 8 10:50:30 2000
diff -u --recursive --new-file v2.4.0-test9/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: transport.c,v 1.27 2000/09/28 21:54:30 mdharm Exp $
+ * $Id: transport.c,v 1.30 2000/10/24 02:01:18 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -61,7 +61,7 @@
/* Calculate the length of the data transfer (not the command) for any
* given SCSI command
*/
-static unsigned int us_transfer_length(Scsi_Cmnd *srb)
+unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
{
int i;
int doDefault = 0;
@@ -412,6 +412,9 @@
FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) dr, data, size,
usb_stor_blocking_completion, &wqh);
+ us->current_urb->actual_length = 0;
+ us->current_urb->error_count = 0;
+ us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
/* submit the URB */
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -426,7 +429,7 @@
/* wait for the completion of the URB */
up(&(us->current_urb_sem));
- if (us->current_urb->status == -EINPROGRESS)
+ while (us->current_urb->status == -EINPROGRESS)
schedule();
down(&(us->current_urb_sem));
@@ -466,6 +469,9 @@
/* fill the URB */
FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len,
usb_stor_blocking_completion, &wqh);
+ us->current_urb->actual_length = 0;
+ us->current_urb->error_count = 0;
+ us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
/* submit the URB */
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -479,7 +485,7 @@
/* wait for the completion of the URB */
up(&(us->current_urb_sem));
- if (us->current_urb->status == -EINPROGRESS)
+ while (us->current_urb->status == -EINPROGRESS)
schedule();
down(&(us->current_urb_sem));
@@ -506,7 +512,7 @@
* timeout limit. Thus we don't have to worry about it for individual
* packets.
*/
-static int us_transfer_partial(struct us_data *us, char *buf, int length)
+int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
{
int result;
int partial;
@@ -519,7 +525,7 @@
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
/* transfer the data */
- US_DEBUGP("us_transfer_partial(): xfer %d bytes\n", length);
+ US_DEBUGP("usb_stor_transfer_partial(): xfer %d bytes\n", length);
result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",
result, partial, length);
@@ -532,7 +538,7 @@
/* did we send all the data? */
if (partial == length) {
- US_DEBUGP("us_transfer_partial(): transfer complete\n");
+ US_DEBUGP("usb_stor_transfer_partial(): transfer complete\n");
return US_BULK_TRANSFER_GOOD;
}
@@ -540,18 +546,18 @@
if (result) {
/* NAK - that means we've retried a few times allready */
if (result == -ETIMEDOUT) {
- US_DEBUGP("us_transfer_partial(): device NAKed\n");
+ US_DEBUGP("usb_stor_transfer_partial(): device NAKed\n");
return US_BULK_TRANSFER_FAILED;
}
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
- US_DEBUGP("us_transfer_partial(): transfer aborted\n");
+ US_DEBUGP("usb_stor_transfer_partial(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
/* the catch-all case */
- US_DEBUGP("us_transfer_partial(): unknown error\n");
+ US_DEBUGP("usb_stor_transfer_partial(): unknown error\n");
return US_BULK_TRANSFER_FAILED;
}
@@ -564,7 +570,7 @@
* Transfer an entire SCSI command's worth of data payload over the bulk
* pipe.
*
- * Note that this uses us_transfer_partial to achieve it's goals -- this
+ * Note that this uses usb_stor_transfer_partial to achieve it's goals -- this
* function simply determines if we're going to use scatter-gather or not,
* and acts appropriately. For now, it also re-interprets the error codes.
*/
@@ -577,7 +583,7 @@
unsigned int transfer_amount;
/* calculate how much we want to transfer */
- transfer_amount = us_transfer_length(srb);
+ transfer_amount = usb_stor_transfer_length(srb);
/* was someone foolish enough to request more data than available
* buffer space? */
@@ -597,11 +603,12 @@
* remaining data */
if (transfer_amount - total_transferred >=
sg[i].length) {
- result = us_transfer_partial(us, sg[i].address,
- sg[i].length);
+ result = usb_stor_transfer_partial(us,
+ sg[i].address, sg[i].length);
total_transferred += sg[i].length;
} else
- result = us_transfer_partial(us, sg[i].address,
+ result = usb_stor_transfer_partial(us,
+ sg[i].address,
transfer_amount - total_transferred);
/* if we get an error, end the loop here */
@@ -611,7 +618,7 @@
}
else
/* no scatter-gather, just make the request */
- result = us_transfer_partial(us, srb->request_buffer,
+ result = usb_stor_transfer_partial(us, srb->request_buffer,
transfer_amount);
/* return the result in the data structure itself */
@@ -824,8 +831,9 @@
/* was this a wanted interrupt? */
- if (us->ip_wanted) {
- us->ip_wanted = 0;
+ if (atomic_read(us->ip_wanted)) {
+ atomic_set(us->ip_wanted, 0);
+ US_DEBUGP("-- Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count));
up(&(us->ip_waitq));
} else
US_DEBUGP("ERROR: Unwanted interrupt received!\n");
@@ -838,7 +846,11 @@
int result;
/* Set up for status notification */
- us->ip_wanted = 1;
+ atomic_set(us->ip_wanted, 1);
+
+ /* re-initialize the mutex so that we avoid any races with
+ * early/late IRQs from previous commands */
+ init_MUTEX_LOCKED(&(us->ip_waitq));
/* COMMAND STAGE */
/* let's send the command via the control pipe */
@@ -851,7 +863,7 @@
US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
if (result < 0) {
/* Reset flag for status notification */
- us->ip_wanted = 0;
+ atomic_set(us->ip_wanted, 0);
/* if the command was aborted, indicate that */
if (result == -ENOENT)
@@ -873,15 +885,12 @@
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
- if (us_transfer_length(srb)) {
+ if (usb_stor_transfer_length(srb)) {
us_transfer(srb, us);
US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);
/* if it was aborted, we need to indicate that */
if (srb->result == USB_STOR_TRANSPORT_ABORTED) {
- /* we need to reset the state of this semaphore */
- down(&(us->ip_waitq));
-
return USB_STOR_TRANSPORT_ABORTED;
}
}
@@ -889,12 +898,13 @@
/* STATUS STAGE */
/* go to sleep until we get this interrupt */
+ US_DEBUGP("Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count));
down(&(us->ip_waitq));
/* if we were woken up by an abort instead of the actual interrupt */
- if (us->ip_wanted) {
+ if (atomic_read(us->ip_wanted)) {
US_DEBUGP("Did not get interrupt on CBI\n");
- us->ip_wanted = 0;
+ atomic_set(us->ip_wanted, 0);
return USB_STOR_TRANSPORT_ABORTED;
}
@@ -978,7 +988,7 @@
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
- if (us_transfer_length(srb)) {
+ if (usb_stor_transfer_length(srb)) {
us_transfer(srb, us);
US_DEBUGP("CB data stage result is 0x%x\n", srb->result);
@@ -1039,10 +1049,14 @@
int result;
int pipe;
int partial;
+
+ /* if the device was removed, then we're already reset */
+ if (!us->pusb_dev)
+ return SUCCESS;
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
- bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb));
+ bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));
bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number;
bcb.Lun = srb->cmnd[1] >> 5;
@@ -1182,6 +1196,10 @@
US_DEBUGP("CB_reset() called\n");
+ /* if the device was removed, then we're already reset */
+ if (!us->pusb_dev)
+ return SUCCESS;
+
memset(cmd, 0xFF, sizeof(cmd));
cmd[0] = SEND_DIAGNOSTIC;
cmd[1] = 4;
@@ -1219,6 +1237,10 @@
int result;
US_DEBUGP("Bulk reset requested\n");
+
+ /* if the device was removed, then we're already reset */
+ if (!us->pusb_dev)
+ return SUCCESS;
result = usb_control_msg(us->pusb_dev,
usb_sndctrlpipe(us->pusb_dev,0),
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)