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:
Родитель
8b07d2fe38
Коммит
81a71bad40
|
@ -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:
|
||||
|
|
Загрузка…
Ссылка в новой задаче