diff mbox

[15/31] usb: usbssp: added device controller error, transfer and SETUP completion event.

Message ID 1532023084-28083-16-git-send-email-pawell@cadence.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pawel Laszczak July 19, 2018, 5:57 p.m. UTC
Patch adds some other completion events used in driver.

The Device Controller Error event is used for detecting
Event Ring Full error.

Transfer event will be implemented in later patches.

SETUP event handles SETUP packet received from host. In interrupt context
driver only preserve the SETUP packet, then postpone handling
it for later. We can't handle all Setup packet in interrupt
context because some of them needs to call command that take some time.

Signed-off-by: Pawel Laszczak <pawell@cadence.com>
---
 drivers/usb/usbssp/gadget-ring.c | 57 ++++++++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/drivers/usb/usbssp/gadget-ring.c b/drivers/usb/usbssp/gadget-ring.c
index c704b939b48a..eab7676fa744 100644
--- a/drivers/usb/usbssp/gadget-ring.c
+++ b/drivers/usb/usbssp/gadget-ring.c
@@ -1070,6 +1070,18 @@  struct usbssp_segment *usbssp_trb_in_td(struct usbssp_udc *usbssp_data,
 	return NULL;
 }
 
+/*
+ * If this function returns an error condition, it means it got a Transfer
+ * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address.
+ * At this point, the USBSSP controller is probably hosed and should be reset.
+ */
+static int handle_tx_event(struct usbssp_udc *usbssp_data,
+			   struct usbssp_transfer_event *event)
+{
+	/*TODO: implement function handling transfer event*/
+	return 0;
+}
+
 /*
  * This function handles all events on the event ring.
  * Function can defers handling of some events to kernel thread.
@@ -1080,7 +1092,9 @@  int usbssp_handle_event(struct usbssp_udc *usbssp_data)
 {
 	union usbssp_trb *event;
 	int update_ptrs = 1;
+	int ret = 0;
 	__le32 cycle_bit;
+	unsigned int trb_comp_code;
 
 	if (!usbssp_data->event_ring || !usbssp_data->event_ring->dequeue) {
 		dev_err(usbssp_data->dev, "ERROR event ring not ready\n");
@@ -1110,6 +1124,45 @@  int usbssp_handle_event(struct usbssp_udc *usbssp_data)
 		handle_port_status(usbssp_data, event);
 		update_ptrs = 0;
 		break;
+	case TRB_TYPE(TRB_TRANSFER):
+		ret = handle_tx_event(usbssp_data, &event->trans_event);
+
+		if (ret >= 0)
+			update_ptrs = 0;
+		break;
+	case TRB_TYPE(TRB_SETUP): {
+		usbssp_data->ep0state = USBSSP_EP0_SETUP_PHASE;
+		usbssp_data->setupId = TRB_SETUPID_TO_TYPE(event->trans_event.flags);
+		usbssp_data->setup_speed = TRB_SETUP_SPEEDID(event->trans_event.flags);
+
+		usbssp_data->setup = *((struct usb_ctrlrequest *)&event->trans_event.buffer);
+
+		dev_dbg(usbssp_data->dev,
+			"Setup packet (id: %d) defered to thread\n",
+			usbssp_data->setupId);
+
+		usbssp_data->defered_event |= EVENT_SETUP_PACKET;
+		queue_work(usbssp_data->bottom_irq_wq,
+				&usbssp_data->bottom_irq);
+		break;
+	}
+
+	case TRB_TYPE(TRB_HC_EVENT):
+		trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->generic.field[2]));
+		dev_warn(usbssp_data->dev,
+			"Device Controller Error detected with error code 0x%02x\n",
+			trb_comp_code);
+		/* Look for common error cases */
+		switch (trb_comp_code) {
+		case COMP_EVENT_RING_FULL_ERROR:
+			dev_dbg(usbssp_data->dev,
+				"Error: Event Ring Full\n");
+			break;
+		default:
+			dev_dbg(usbssp_data->dev,
+				"Not supported completion code\n");
+		}
+		break;
 	default:
 		dev_warn(usbssp_data->dev, "ERROR unknown event type %ld\n",
 			TRB_FIELD_TO_TYPE(
@@ -1123,8 +1176,8 @@  int usbssp_handle_event(struct usbssp_udc *usbssp_data)
 	 * non-responsive.
 	 */
 	if (usbssp_data->usbssp_state & USBSSP_STATE_DYING) {
-		dev_dbg(usbssp_data->dev, "USBSSP device dying, returning from "
-			"event handle.\n");
+		dev_dbg(usbssp_data->dev,
+			"USBSSP device dying, returning from event handle.\n");
 		return 0;
 	}