aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2011-09-08 11:27:33 -0400
committerFelipe Balbi <balbi@ti.com>2011-09-09 06:05:29 -0400
commit55f3fba6c822f05b02f06070efaadf0300b5f9f1 (patch)
tree1ba2067f9f1ada811eab75008e54ea8d527626e5 /drivers
parentd742220b357769fa0a764d238373b8667116cf64 (diff)
usb: dwc3: ep0: introduce ep0_expect_in flag
This flag will tell us which direction we're expecting on the next (data or status) phase. It will help us catching errors of host going crazy and requesting data of the wrong direction. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/dwc3/core.h2
-rw-r--r--drivers/usb/dwc3/ep0.c16
2 files changed, 18 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 92673fd5314d..07d20186e46d 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -529,6 +529,7 @@ static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat)
529 * @three_stage_setup: set if we perform a three phase setup 529 * @three_stage_setup: set if we perform a three phase setup
530 * @ep0_status_pending: ep0 status response without a req is pending 530 * @ep0_status_pending: ep0 status response without a req is pending
531 * @ep0_bounced: true when we used bounce buffer 531 * @ep0_bounced: true when we used bounce buffer
532 * @ep0_expect_in: true when we expect a DATA IN transfer
532 * @ep0_next_event: hold the next expected event 533 * @ep0_next_event: hold the next expected event
533 * @ep0state: state of endpoint zero 534 * @ep0state: state of endpoint zero
534 * @link_state: link state 535 * @link_state: link state
@@ -575,6 +576,7 @@ struct dwc3 {
575 unsigned three_stage_setup:1; 576 unsigned three_stage_setup:1;
576 unsigned ep0_status_pending:1; 577 unsigned ep0_status_pending:1;
577 unsigned ep0_bounced:1; 578 unsigned ep0_bounced:1;
579 unsigned ep0_expect_in:1;
578 580
579 enum dwc3_ep0_next ep0_next_event; 581 enum dwc3_ep0_next ep0_next_event;
580 enum dwc3_ep0_state ep0state; 582 enum dwc3_ep0_state ep0state;
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 4cc72fdc0575..b66d96905728 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -545,6 +545,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
545 dwc->ep0_next_event = DWC3_EP0_NRDY_DATA; 545 dwc->ep0_next_event = DWC3_EP0_NRDY_DATA;
546 } 546 }
547 547
548 dwc->ep0_expect_in = !!(ctrl->bRequestType & USB_DIR_IN);
549
548 if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) 550 if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
549 ret = dwc3_ep0_std_request(dwc, ctrl); 551 ret = dwc3_ep0_std_request(dwc, ctrl);
550 else 552 else
@@ -758,6 +760,20 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
758 return; 760 return;
759 } 761 }
760 762
763 /*
764 * One of the possible error cases is when Host _does_
765 * request for Data Phase, but it does so on the wrong
766 * direction.
767 *
768 * Here, we already know ep0_next_event is DATA (see above),
769 * so we only need to check for direction.
770 */
771 if (dwc->ep0_expect_in != event->endpoint_number) {
772 dev_vdbg(dwc->dev, "Wrong direction for Data phase\n");
773 dwc3_ep0_stall_and_restart(dwc);
774 return;
775 }
776
761 dwc3_ep0_do_control_data(dwc, event); 777 dwc3_ep0_do_control_data(dwc, event);
762 break; 778 break;
763 779