staging: octeon-usb: move control transfer handling into separate function

Move control transfer handling into a separate function to
avoid deep indentation.

Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Aaro Koskinen 2016-02-26 02:14:00 +02:00 committed by Greg Kroah-Hartman
parent 8b07d2fe38
commit 81a71bad40
1 changed files with 88 additions and 86 deletions

View File

@ -2383,6 +2383,90 @@ static int cvmx_usb_get_frame_number(struct octeon_hcd *usb)
return frame_number;
}
static void cvmx_usb_transfer_control(struct octeon_hcd *usb,
struct cvmx_usb_pipe *pipe,
struct cvmx_usb_transaction *transaction,
union cvmx_usbcx_hccharx usbc_hcchar,
int buffer_space_left,
int bytes_in_last_packet)
{
switch (transaction->stage) {
case CVMX_USB_STAGE_NON_CONTROL:
case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
/* This should be impossible */
cvmx_usb_complete(usb, pipe, transaction,
CVMX_USB_STATUS_ERROR);
break;
case CVMX_USB_STAGE_SETUP:
pipe->pid_toggle = 1;
if (cvmx_usb_pipe_needs_split(usb, pipe)) {
transaction->stage =
CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE;
} else {
struct usb_ctrlrequest *header =
cvmx_phys_to_ptr(transaction->control_header);
if (header->wLength)
transaction->stage = CVMX_USB_STAGE_DATA;
else
transaction->stage = CVMX_USB_STAGE_STATUS;
}
break;
case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
{
struct usb_ctrlrequest *header =
cvmx_phys_to_ptr(transaction->control_header);
if (header->wLength)
transaction->stage = CVMX_USB_STAGE_DATA;
else
transaction->stage = CVMX_USB_STAGE_STATUS;
}
break;
case CVMX_USB_STAGE_DATA:
if (cvmx_usb_pipe_needs_split(usb, pipe)) {
transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE;
/*
* For setup OUT data that are splits,
* the hardware doesn't appear to count
* transferred data. Here we manually
* update the data transferred
*/
if (!usbc_hcchar.s.epdir) {
if (buffer_space_left < pipe->max_packet)
transaction->actual_bytes +=
buffer_space_left;
else
transaction->actual_bytes +=
pipe->max_packet;
}
} else if ((buffer_space_left == 0) ||
(bytes_in_last_packet < pipe->max_packet)) {
pipe->pid_toggle = 1;
transaction->stage = CVMX_USB_STAGE_STATUS;
}
break;
case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
if ((buffer_space_left == 0) ||
(bytes_in_last_packet < pipe->max_packet)) {
pipe->pid_toggle = 1;
transaction->stage = CVMX_USB_STAGE_STATUS;
} else {
transaction->stage = CVMX_USB_STAGE_DATA;
}
break;
case CVMX_USB_STAGE_STATUS:
if (cvmx_usb_pipe_needs_split(usb, pipe))
transaction->stage =
CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE;
else
cvmx_usb_complete(usb, pipe, transaction,
CVMX_USB_STATUS_OK);
break;
case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_OK);
break;
}
}
/**
* Poll a channel for status
*
@ -2656,92 +2740,10 @@ static int cvmx_usb_poll_channel(struct octeon_hcd *usb, int channel)
switch (transaction->type) {
case CVMX_USB_TRANSFER_CONTROL:
switch (transaction->stage) {
case CVMX_USB_STAGE_NON_CONTROL:
case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
/* This should be impossible */
cvmx_usb_complete(usb, pipe, transaction,
CVMX_USB_STATUS_ERROR);
break;
case CVMX_USB_STAGE_SETUP:
pipe->pid_toggle = 1;
if (cvmx_usb_pipe_needs_split(usb, pipe))
transaction->stage =
CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE;
else {
struct usb_ctrlrequest *header =
cvmx_phys_to_ptr(transaction->control_header);
if (header->wLength)
transaction->stage =
CVMX_USB_STAGE_DATA;
else
transaction->stage =
CVMX_USB_STAGE_STATUS;
}
break;
case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
{
struct usb_ctrlrequest *header =
cvmx_phys_to_ptr(transaction->control_header);
if (header->wLength)
transaction->stage =
CVMX_USB_STAGE_DATA;
else
transaction->stage =
CVMX_USB_STAGE_STATUS;
}
break;
case CVMX_USB_STAGE_DATA:
if (cvmx_usb_pipe_needs_split(usb, pipe)) {
transaction->stage =
CVMX_USB_STAGE_DATA_SPLIT_COMPLETE;
/*
* For setup OUT data that are splits,
* the hardware doesn't appear to count
* transferred data. Here we manually
* update the data transferred
*/
if (!usbc_hcchar.s.epdir) {
if (buffer_space_left < pipe->max_packet)
transaction->actual_bytes +=
buffer_space_left;
else
transaction->actual_bytes +=
pipe->max_packet;
}
} else if ((buffer_space_left == 0) ||
(bytes_in_last_packet <
pipe->max_packet)) {
pipe->pid_toggle = 1;
transaction->stage =
CVMX_USB_STAGE_STATUS;
}
break;
case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
if ((buffer_space_left == 0) ||
(bytes_in_last_packet < pipe->max_packet)) {
pipe->pid_toggle = 1;
transaction->stage =
CVMX_USB_STAGE_STATUS;
} else {
transaction->stage =
CVMX_USB_STAGE_DATA;
}
break;
case CVMX_USB_STAGE_STATUS:
if (cvmx_usb_pipe_needs_split(usb, pipe))
transaction->stage =
CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE;
else
cvmx_usb_complete(usb, pipe,
transaction,
CVMX_USB_STATUS_OK);
break;
case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
cvmx_usb_complete(usb, pipe, transaction,
CVMX_USB_STATUS_OK);
break;
}
cvmx_usb_transfer_control(usb, pipe, transaction,
usbc_hcchar,
buffer_space_left,
bytes_in_last_packet);
break;
case CVMX_USB_TRANSFER_BULK:
case CVMX_USB_TRANSFER_INTERRUPT: