Commit 77212fff authored by Matthew Dharm's avatar Matthew Dharm Committed by Greg Kroah-Hartman

[PATCH] usb-storage: code consolidation

This patch puts all the code to interpret the result code from an URB into
a single place, instead of copying it everywhere throughout transport.c
parent c0f800ef
......@@ -479,7 +479,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
usb_stor_blocking_completion, NULL);
status = usb_stor_msg_common(us);
/* return the actual length of the data transferred if no error*/
/* return the actual length of the data transferred if no error */
if (status >= 0)
status = us->current_urb->actual_length;
return status;
......@@ -543,47 +543,91 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
return 0;
}
/*
* Transfer one control message
* Interpret the results of a URB transfer
*
* This function does basically the same thing as usb_stor_control_msg()
* above, except that return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
* This function prints appropriate debugging messages, clears halts on
* bulk endpoints, and translates the status to the corresponding
* USB_STOR_XFER_xxx return code.
*/
int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size) {
int result;
static int interpret_urb_result(struct us_data *us, unsigned int pipe,
unsigned int length, int result, unsigned int partial) {
US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x "
"value=%04x index=%02x len=%u\n",
request, requesttype, value, index, size);
result = usb_stor_control_msg(us, pipe, request, requesttype,
value, index, data, size);
US_DEBUGP("usb_stor_control_msg returned %d\n", result);
US_DEBUGP("Status code %d; transferred %u/%u\n",
result, partial, length);
/* a stall indicates a protocol error */
/* stalled */
if (result == -EPIPE) {
/* for non-bulk (i.e., control) endpoints, a stall indicates
* a protocol error */
if (!usb_pipebulk(pipe)) {
US_DEBUGP("-- stall on control pipe\n");
return USB_STOR_XFER_ERROR;
}
/* some other serious problem here */
/* for a bulk endpoint, clear the stall */
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
}
/* NAK - that means we've retried this a few times already */
if (result == -ETIMEDOUT) {
US_DEBUGP("-- device NAKed\n");
return USB_STOR_XFER_ERROR;
}
/* the transfer was cancelled, presumably by an abort */
if (result == -ENODEV) {
US_DEBUGP("-- transfer cancelled\n");
return USB_STOR_XFER_ERROR;
}
/* the catch-all error case */
if (result < 0) {
US_DEBUGP("-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
/* was the entire command transferred? */
if (result < size) {
US_DEBUGP("-- transferred only %d bytes\n", result);
/* no error code; did we send all the data? */
if (partial != length) {
US_DEBUGP("-- transferred only %u bytes\n", partial);
return USB_STOR_XFER_SHORT;
}
US_DEBUGP("-- transfer completed successfully\n");
US_DEBUGP("-- transfer complete\n");
return USB_STOR_XFER_GOOD;
}
/*
* Transfer one control message
*
* This function does basically the same thing as usb_stor_control_msg()
* above, except that return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
*/
int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size) {
int result;
unsigned int partial = 0;
US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x "
"value=%04x index=%02x len=%u\n",
request, requesttype, value, index, size);
result = usb_stor_control_msg(us, pipe, request, requesttype,
value, index, data, size);
if (result > 0) { /* Separate out the amount transferred */
partial = result;
result = 0;
}
return interpret_urb_result(us, pipe, size, result, partial);
}
/*
* Transfer one buffer via bulk transfer
*
......@@ -604,42 +648,9 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
/* transfer the data */
US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %u bytes\n", length);
result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %u/%u\n",
result, partial, length);
if (act_len)
*act_len = partial;
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x,"
" stalled at %u bytes\n", pipe, partial);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
}
/* NAK - that means we've retried a few times already */
if (result == -ETIMEDOUT) {
US_DEBUGP("-- device NAKed\n");
return USB_STOR_XFER_ERROR;
}
/* the catch-all error case */
if (result) {
US_DEBUGP("-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
/* did we send all the data? */
if (partial == length) {
US_DEBUGP("-- transfer complete\n");
return USB_STOR_XFER_GOOD;
}
/* no error code, so we must have transferred some data,
* just not all of it */
US_DEBUGP("-- transferred only %u bytes\n", partial);
return USB_STOR_XFER_SHORT;
return interpret_urb_result(us, pipe, length, result, partial);
}
/*
......@@ -653,7 +664,7 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
unsigned int *act_len)
{
int result;
int partial;
unsigned int partial;
/* initialize the scatter-gather request block */
US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %u bytes, "
......@@ -685,42 +696,9 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
result = us->current_sg->status;
partial = us->current_sg->bytes;
US_DEBUGP("usb_sg_wait() returned %d xferred %u/%u\n",
result, partial, length);
if (act_len)
*act_len = partial;
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x, "
"stalled at %u bytes\n", pipe, partial);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
}
/* NAK - that means we've retried this a few times already */
if (result == -ETIMEDOUT) {
US_DEBUGP("-- device NAKed\n");
return USB_STOR_XFER_ERROR;
}
/* the catch-all error case */
if (result) {
US_DEBUGP("-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
/* did we send all the data? */
if (partial == length) {
US_DEBUGP("-- transfer complete\n");
return USB_STOR_XFER_GOOD;
}
/* no error code, so we must have transferred some data,
* just not all of it */
US_DEBUGP("-- transferred only %u bytes\n", partial);
return USB_STOR_XFER_SHORT;
return interpret_urb_result(us, pipe, length, result, partial);
}
/*
......
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