*/
#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
int status;
/* don't submit URBs during abort/disconnect processing */
- if (us->flags & DONT_SUBMIT)
+ if (us->flags & ABORTING_OR_DISCONNECTING)
return -EIO;
/* set up data structures for the wakeup system */
set_bit(US_FLIDX_URB_ACTIVE, &us->flags);
/* did an abort/disconnect occur during the submission? */
- if (us->flags & DONT_SUBMIT) {
+ if (us->flags & ABORTING_OR_DISCONNECTING) {
/* cancel the URB, if it hasn't been cancelled already */
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
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);
int result;
/* don't submit s-g requests during abort/disconnect processing */
- if (us->flags & DONT_SUBMIT)
+ if (us->flags & ABORTING_OR_DISCONNECTING)
return USB_STOR_XFER_ERROR;
/* initialize the scatter-gather request block */
set_bit(US_FLIDX_SG_ACTIVE, &us->flags);
/* did an abort/disconnect occur during the submission? */
- if (us->flags & DONT_SUBMIT) {
+ if (us->flags & ABORTING_OR_DISCONNECTING) {
/* cancel the request, if it hasn't been cancelled already */
if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
* 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;
/* 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;
}
* 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;
}
/* 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;
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;
}
srb->sense_buffer[0] = 0x0;
}
}
+
+ /* Did we transfer less than the minimum amount required? */
+ if (srb->result == SAM_STAT_GOOD &&
+ srb->request_bufflen - srb->resid < srb->underflow)
+ srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);
+
return;
/* abort processing: the bulk-only transport requires a reset
* following an abort */
- Handle_Abort:
+ Handle_Abort:
srb->result = DID_ABORT << 16;
- if (us->protocol == US_PR_BULK) {
-
- /* permit the reset transfer to take place */
- clear_bit(US_FLIDX_ABORTING, &us->flags);
+ if (us->protocol == US_PR_BULK)
us->transport_reset(us);
- }
}
/* Stop the current URB transfer */
* 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;
/* 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,
/*
* 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;
/* 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,
result, us->iobuf[0]);
/* if we have a successful request, return the result */
- if (result == 1)
+ if (result > 0)
return us->iobuf[0];
- /* return the default -- no LUNs */
+ /*
+ * Some devices (i.e. Iomega Zip100) need this -- apparently
+ * the bulk pipes get STALLed when the GetMaxLUN request is
+ * processed. This is, in theory, harmless to all other devices
+ * (regardless of if they stall or not).
+ */
+ if (result == -EPIPE) {
+ usb_stor_clear_halt(us, us->recv_bulk_pipe);
+ usb_stor_clear_halt(us, us->send_bulk_pipe);
+ }
+
+ /*
+ * 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;
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)
(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,
/* 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) {
{
int result;
int result2;
+ int rc = FAILED;
- /* Let the SCSI layer know we are doing a reset */
+ /* Let the SCSI layer know we are doing a reset, set the
+ * RESETTING bit, and clear the ABORTING bit so that the reset
+ * may proceed.
+ */
+ scsi_lock(us->host);
usb_stor_report_device_reset(us);
+ set_bit(US_FLIDX_RESETTING, &us->flags);
+ clear_bit(US_FLIDX_ABORTING, &us->flags);
+ scsi_unlock(us->host);
/* A 20-second timeout may seem rather long, but a LaCie
- * StudioDrive USB2 device takes 16+ seconds to get going
- * following a powerup or USB attach event. */
-
+ * StudioDrive USB2 device takes 16+ seconds to get going
+ * following a powerup or USB attach event.
+ */
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
request, requesttype, value, index, data, size,
20*HZ);
if (result < 0) {
US_DEBUGP("Soft reset failed: %d\n", result);
- return FAILED;
+ goto Done;
}
- /* long wait for reset, so unlock to allow disconnects */
- up(&us->dev_semaphore);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ*6);
- down(&us->dev_semaphore);
+ /* Give the device some time to recover from the reset,
+ * but don't delay disconnect processing. */
+ wait_event_interruptible_timeout(us->dev_reset_wait,
+ test_bit(US_FLIDX_DISCONNECTING, &us->flags),
+ HZ*6);
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
US_DEBUGP("Reset interrupted by disconnect\n");
- return FAILED;
+ goto Done;
}
- /* permit the clear-halt transfers to take place */
- clear_bit(US_FLIDX_ABORTING, &us->flags);
-
US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
/* return a result code based on the result of the control message */
if (result < 0 || result2 < 0) {
US_DEBUGP("Soft reset failed\n");
- return FAILED;
+ goto Done;
}
US_DEBUGP("Soft reset done\n");
- return SUCCESS;
+ rc = SUCCESS;
+
+ Done:
+ clear_bit(US_FLIDX_RESETTING, &us->flags);
+ return rc;
}
/* This issues a CB[I] Reset to the device in question