vserver 1.9.5.x5
[linux-2.6.git] / drivers / usb / storage / transport.c
index 2321558..ddc1e3b 100644 (file)
  */
 
 #include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "scsiglue.h"
 #include "usb.h"
 #include "debug.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 /***********************************************************************
  * Data transfer routines
@@ -260,9 +265,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
                USB_ENDPOINT_HALT, endp,
                NULL, 0, 3*HZ);
 
-       /* reset the toggles and endpoint flags */
-       usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),
-               usb_pipeout(pipe));
+       /* reset the endpoint toggle */
        usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
                usb_pipeout(pipe), 0);
 
@@ -522,7 +525,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
  * This is used by the protocol layers to actually send the message to
  * the device and receive the response.
  */
-void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
        int need_auto_sense;
        int result;
@@ -534,7 +537,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
        /* if the command gets aborted by the higher layers, we need to
         * short-circuit all other processing
         */
-       if (us->sm_state == US_STATE_ABORTING) {
+       if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
                US_DEBUGP("-- command was aborted\n");
                goto Handle_Abort;
        }
@@ -569,7 +572,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
         * can signal most data-in errors by stalling the bulk-in pipe.
         */
        if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
-                       srb->sc_data_direction != SCSI_DATA_READ) {
+                       srb->sc_data_direction != DMA_FROM_DEVICE) {
                US_DEBUGP("-- CB transport device requiring auto-sense\n");
                need_auto_sense = 1;
        }
@@ -629,7 +632,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
 
                /* set the transfer direction */
                old_sc_data_direction = srb->sc_data_direction;
-               srb->sc_data_direction = SCSI_DATA_READ;
+               srb->sc_data_direction = DMA_FROM_DEVICE;
 
                /* use the new buffer we have */
                old_request_buffer = srb->request_buffer;
@@ -662,7 +665,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
                srb->cmd_len = old_cmd_len;
                memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
 
-               if (us->sm_state == US_STATE_ABORTING) {
+               if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
                        US_DEBUGP("-- auto-sense aborted\n");
                        goto Handle_Abort;
                }
@@ -749,7 +752,7 @@ void usb_stor_stop_transport(struct us_data *us)
  * Control/Bulk/Interrupt transport
  */
 
-int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
        unsigned int transfer_length = srb->request_bufflen;
        unsigned int pipe = 0;
@@ -778,7 +781,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
        /* DATA STAGE */
        /* transfer the data payload for this command, if one exists*/
        if (transfer_length) {
-               pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+               pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
                                us->recv_bulk_pipe : us->send_bulk_pipe;
                result = usb_stor_bulk_transfer_sg(us, pipe,
                                        srb->request_buffer, transfer_length,
@@ -849,7 +852,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
 /*
  * Control/Bulk transport
  */
-int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
        unsigned int transfer_length = srb->request_bufflen;
        int result;
@@ -877,7 +880,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
        /* DATA STAGE */
        /* transfer the data payload for this command, if one exists*/
        if (transfer_length) {
-               unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+               unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
                                us->recv_bulk_pipe : us->send_bulk_pipe;
                result = usb_stor_bulk_transfer_sg(us, pipe,
                                        srb->request_buffer, transfer_length,
@@ -918,7 +921,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
                  result, us->iobuf[0]);
 
        /* if we have a successful request, return the result */
-       if (result == 1)
+       if (result > 0)
                return us->iobuf[0];
 
        /* 
@@ -930,16 +933,19 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
        if (result == -EPIPE) {
                usb_stor_clear_halt(us, us->recv_bulk_pipe);
                usb_stor_clear_halt(us, us->send_bulk_pipe);
-               /* return the default -- no LUNs */
-               return 0;
        }
 
-       /* An answer or a STALL are the only valid responses.  If we get
-        * something else, return an indication of error */
-       return -1;
+       /*
+        * Some devices don't like GetMaxLUN.  They may STALL the control
+        * pipe, they may return a zero-length result, they may do nothing at
+        * all and timeout, or they may fail in even more bizarrely creative
+        * ways.  In these cases the best approach is to use the default
+        * value: only one LUN.
+        */
+       return 0;
 }
 
-int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
        struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
        struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
@@ -948,11 +954,18 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
        int result;
        int fake_sense = 0;
        unsigned int cswlen;
+       unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
+
+       /* Take care of BULK32 devices; set extra byte to 0 */
+       if ( unlikely(us->flags & US_FL_BULK32)) {
+               cbwlen = 32;
+               us->iobuf[31] = 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->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
        bcb->Tag = srb->serial_number;
        bcb->Lun = srb->device->lun;
        if (us->flags & US_FL_SCM_MULT_TARG)
@@ -970,15 +983,22 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
                        (bcb->Lun >> 4), (bcb->Lun & 0x0F), 
                        bcb->Length);
        result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-                               bcb, US_BULK_CB_WRAP_LEN, NULL);
+                               bcb, cbwlen, NULL);
        US_DEBUGP("Bulk command transfer result=%d\n", result);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
        /* DATA STAGE */
        /* send/receive data payload, if there is any */
+
+       /* Genesys Logic interface chips need a 100us delay between the
+        * command phase and the data phase.  Some devices need a little
+        * more than that, probably because of clock rate inaccuracies. */
+       if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS)
+               udelay(110);
+
        if (transfer_length) {
-               unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+               unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
                                us->recv_bulk_pipe : us->send_bulk_pipe;
                result = usb_stor_bulk_transfer_sg(us, pipe,
                                        srb->request_buffer, transfer_length,
@@ -1045,8 +1065,13 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
 
        /* try to compute the actual residue, based on how much data
         * was really transferred and what the device tells us */
-       residue = min(residue, transfer_length);
-       srb->resid = max(srb->resid, (int) residue);
+       if (residue) {
+               if (!(us->flags & US_FL_IGNORE_RESIDUE) ||
+                               srb->sc_data_direction == DMA_TO_DEVICE) {
+                       residue = min(residue, transfer_length);
+                       srb->resid = max(srb->resid, (int) residue);
+               }
+       }
 
        /* based on the status code, we report good or bad */
        switch (bcs->Status) {