Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81a71bad authored by Aaro Koskinen's avatar Aaro Koskinen Committed by Greg Kroah-Hartman
Browse files

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: default avatarAaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8b07d2fe
Loading
Loading
Loading
Loading
+88 −86
Original line number Original line Diff line number Diff line
@@ -2383,6 +2383,90 @@ static int cvmx_usb_get_frame_number(struct octeon_hcd *usb)
	return frame_number;
	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
 * Poll a channel for status
 *
 *
@@ -2656,92 +2740,10 @@ static int cvmx_usb_poll_channel(struct octeon_hcd *usb, int channel)


		switch (transaction->type) {
		switch (transaction->type) {
		case CVMX_USB_TRANSFER_CONTROL:
		case CVMX_USB_TRANSFER_CONTROL:
			switch (transaction->stage) {
			cvmx_usb_transfer_control(usb, pipe, transaction,
			case CVMX_USB_STAGE_NON_CONTROL:
						  usbc_hcchar,
			case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
						  buffer_space_left,
				/* This should be impossible */
						  bytes_in_last_packet);
				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;
			}
			break;
			break;
		case CVMX_USB_TRANSFER_BULK:
		case CVMX_USB_TRANSFER_BULK:
		case CVMX_USB_TRANSFER_INTERRUPT:
		case CVMX_USB_TRANSFER_INTERRUPT: