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

[PATCH] USB: storage: collapse one-use functions

This patch collapses some one-use functions into their callers.  It also
clones some code for control transfers so we can implement abortable
control transfers with timeout.

This patch is from Alan Stern.

 Remove usb_stor_bulk_msg() and usb_stor_interrupt_msg().  Move their
 functionality into usb_stor_bulk_transfer_buf() and
 usb_stor_intr_transfer().

 Move the functionality of usb_stor_control_msg() into
 usb_stor_ctrl_transfer().

 Remove the unused act_len parameter from usb_stor_intr_transfer().
parent 257711d2
...@@ -192,53 +192,6 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, ...@@ -192,53 +192,6 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
return status; return status;
} }
/* This is our function to emulate usb_bulk_msg() with enough control
* to make aborts/resets/timeouts work
*/
int usb_stor_bulk_msg(struct us_data *us, void *data, unsigned int pipe,
unsigned int len, unsigned int *act_len)
{
int status;
/* fill and submit the URB */
usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, data, len,
usb_stor_blocking_completion, NULL);
status = usb_stor_msg_common(us);
/* store the actual length of the data transferred */
*act_len = us->current_urb->actual_length;
return status;
}
/* This is our function to submit interrupt URBs with enough control
* to make aborts/resets/timeouts work
*
* This routine always uses us->recv_intr_pipe as the pipe and
* us->ep_bInterval as the interrupt interval.
*/
int usb_stor_interrupt_msg(struct us_data *us, void *data,
unsigned int len, unsigned int *act_len)
{
unsigned int pipe = us->recv_intr_pipe;
unsigned int maxp;
int status;
/* calculate the max packet size */
maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
if (maxp > len)
maxp = len;
/* fill and submit the URB */
usb_fill_int_urb(us->current_urb, us->pusb_dev, pipe, data,
maxp, usb_stor_blocking_completion, NULL,
us->ep_bInterval);
status = usb_stor_msg_common(us);
/* store the actual length of the data transferred */
*act_len = us->current_urb->actual_length;
return status;
}
/* This is a version of usb_clear_halt() that doesn't read the status from /* This is a version of usb_clear_halt() that doesn't read the status from
* the device -- this is because some devices crash their internal firmware * the device -- this is because some devices crash their internal firmware
* when the status is requested after a halt. * when the status is requested after a halt.
...@@ -282,12 +235,12 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) ...@@ -282,12 +235,12 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
* Interpret the results of a URB transfer * Interpret the results of a URB transfer
* *
* This function prints appropriate debugging messages, clears halts on * This function prints appropriate debugging messages, clears halts on
* bulk endpoints, and translates the status to the corresponding * non-control endpoints, and translates the status to the corresponding
* USB_STOR_XFER_xxx return code. * USB_STOR_XFER_xxx return code.
*/ */
static int interpret_urb_result(struct us_data *us, unsigned int pipe, static int interpret_urb_result(struct us_data *us, unsigned int pipe,
unsigned int length, int result, unsigned int partial) { unsigned int length, int result, unsigned int partial)
{
US_DEBUGP("Status code %d; transferred %u/%u\n", US_DEBUGP("Status code %d; transferred %u/%u\n",
result, partial, length); result, partial, length);
switch (result) { switch (result) {
...@@ -340,77 +293,88 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe, ...@@ -340,77 +293,88 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
} }
/* /*
* Transfer one control message * Transfer one control message, without timeouts, but allowing early
* * termination. Return codes are USB_STOR_XFER_xxx.
* 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, int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index, u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size) { void *data, u16 size)
{
int result; int result;
unsigned int partial = 0;
US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x " US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
"value=%04x index=%02x len=%u\n", __FUNCTION__, request, requesttype,
request, requesttype, value, index, size); value, index, size);
result = usb_stor_control_msg(us, pipe, request, requesttype,
value, index, data, size);
if (result > 0) { /* Separate out the amount transferred */ /* fill in the devrequest structure */
partial = result; us->dr->bRequestType = requesttype;
result = 0; us->dr->bRequest = request;
} us->dr->wValue = cpu_to_le16(value);
return interpret_urb_result(us, pipe, size, result, partial); us->dr->wIndex = cpu_to_le16(index);
us->dr->wLength = cpu_to_le16(size);
/* fill and submit the URB */
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) us->dr, data, size,
usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us);
return interpret_urb_result(us, pipe, size, result,
us->current_urb->actual_length);
} }
/* /*
* Receive one buffer via interrupt transfer * Receive one interrupt buffer, without timeouts, but allowing early
* termination. Return codes are USB_STOR_XFER_xxx.
* *
* This function does basically the same thing as usb_stor_interrupt_msg() * This routine always uses us->recv_intr_pipe as the pipe and
* above, except that return codes are USB_STOR_XFER_xxx rather than the * us->ep_bInterval as the interrupt interval.
* urb status.
*/ */
int usb_stor_intr_transfer(struct us_data *us, void *buf, int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length)
unsigned int length, unsigned int *act_len)
{ {
int result; int result;
unsigned int partial; unsigned int pipe = us->recv_intr_pipe;
unsigned int maxp;
/* transfer the data */ US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
US_DEBUGP("usb_stor_intr_transfer(): xfer %u bytes\n", length);
result = usb_stor_interrupt_msg(us, buf, length, &partial); /* calculate the max packet size */
if (act_len) maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
*act_len = partial; if (maxp > length)
maxp = length;
/* fill and submit the URB */
usb_fill_int_urb(us->current_urb, us->pusb_dev, pipe, buf,
maxp, usb_stor_blocking_completion, NULL,
us->ep_bInterval);
result = usb_stor_msg_common(us);
return interpret_urb_result(us, us->recv_intr_pipe, return interpret_urb_result(us, pipe, length, result,
length, result, partial); us->current_urb->actual_length);
} }
/* /*
* Transfer one buffer via bulk transfer * Transfer one buffer via bulk pipe, without timeouts, but allowing early
* * termination. Return codes are USB_STOR_XFER_xxx. If the bulk pipe
* This function does basically the same thing as usb_stor_bulk_msg() * stalls during the transfer, the halt is automatically cleared.
* above, except that:
*
* 1. If the bulk pipe stalls during the transfer, the halt is
* automatically cleared;
* 2. Return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
*/ */
int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, unsigned int *act_len) void *buf, unsigned int length, unsigned int *act_len)
{ {
int result; int result;
unsigned int partial;
/* transfer the data */ US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %u bytes\n", length);
result = usb_stor_bulk_msg(us, buf, pipe, length, &partial); /* fill and submit the URB */
usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us);
/* store the actual length of the data transferred */
if (act_len) if (act_len)
*act_len = partial; *act_len = us->current_urb->actual_length;
return interpret_urb_result(us, pipe, length, result, partial); return interpret_urb_result(us, pipe, length, result,
us->current_urb->actual_length);
} }
/* /*
...@@ -424,15 +388,14 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, ...@@ -424,15 +388,14 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
unsigned int *act_len) unsigned int *act_len)
{ {
int result; int result;
unsigned int partial;
/* don't submit s-g requests during abort/disconnect processing */ /* don't submit s-g requests during abort/disconnect processing */
if (us->flags & DONT_SUBMIT) if (us->flags & DONT_SUBMIT)
return USB_STOR_XFER_ERROR; return USB_STOR_XFER_ERROR;
/* initialize the scatter-gather request block */ /* initialize the scatter-gather request block */
US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %u bytes, " US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,
"%d entries\n", length, num_sg); length, num_sg);
result = usb_sg_init(us->current_sg, us->pusb_dev, pipe, 0, result = usb_sg_init(us->current_sg, us->pusb_dev, pipe, 0,
sg, num_sg, length, SLAB_NOIO); sg, num_sg, length, SLAB_NOIO);
if (result) { if (result) {
...@@ -459,10 +422,10 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, ...@@ -459,10 +422,10 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
clear_bit(US_FLIDX_SG_ACTIVE, &us->flags); clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);
result = us->current_sg->status; result = us->current_sg->status;
partial = us->current_sg->bytes;
if (act_len) if (act_len)
*act_len = partial; *act_len = us->current_sg->bytes;
return interpret_urb_result(us, pipe, length, result, partial); return interpret_urb_result(us, pipe, length, result,
us->current_sg->bytes);
} }
/* /*
...@@ -775,8 +738,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -775,8 +738,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
} }
/* STATUS STAGE */ /* STATUS STAGE */
result = usb_stor_intr_transfer(us, us->irqdata, result = usb_stor_intr_transfer(us, us->irqdata, sizeof(us->irqdata));
sizeof(us->irqdata), NULL);
US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
us->irqdata[0], us->irqdata[1]); us->irqdata[0], us->irqdata[1]);
if (result != USB_STOR_XFER_GOOD) if (result != USB_STOR_XFER_GOOD)
......
...@@ -158,20 +158,16 @@ extern int usb_stor_Bulk_reset(struct us_data*); ...@@ -158,20 +158,16 @@ extern int usb_stor_Bulk_reset(struct us_data*);
extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*); extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
extern void usb_stor_stop_transport(struct us_data*); extern void usb_stor_stop_transport(struct us_data*);
extern int usb_stor_bulk_msg(struct us_data *us, void *data,
unsigned int pipe, unsigned int len, unsigned int *act_len);
extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index, u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size); void *data, u16 size);
extern int usb_stor_interrupt_msg(struct us_data *us, void *data,
unsigned int len, unsigned int *act_len);
extern int usb_stor_clear_halt(struct us_data*, unsigned int pipe); extern int usb_stor_clear_halt(struct us_data*, unsigned int pipe);
extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index, u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size); void *data, u16 size);
extern int usb_stor_intr_transfer(struct us_data *us, void *buf, extern int usb_stor_intr_transfer(struct us_data *us, void *buf,
unsigned int length, unsigned int *act_len); unsigned int length);
extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, unsigned int *act_len); void *buf, unsigned int length, unsigned int *act_len);
extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
......
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