aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea/udc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea/udc.c')
-rw-r--r--drivers/usb/chipidea/udc.c84
1 files changed, 44 insertions, 40 deletions
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index a637da25dda0..8223fe73ea85 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -656,6 +656,44 @@ __acquires(hwep->lock)
656 return 0; 656 return 0;
657} 657}
658 658
659static int _ep_set_halt(struct usb_ep *ep, int value, bool check_transfer)
660{
661 struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep);
662 int direction, retval = 0;
663 unsigned long flags;
664
665 if (ep == NULL || hwep->ep.desc == NULL)
666 return -EINVAL;
667
668 if (usb_endpoint_xfer_isoc(hwep->ep.desc))
669 return -EOPNOTSUPP;
670
671 spin_lock_irqsave(hwep->lock, flags);
672
673 if (value && hwep->dir == TX && check_transfer &&
674 !list_empty(&hwep->qh.queue) &&
675 !usb_endpoint_xfer_control(hwep->ep.desc)) {
676 spin_unlock_irqrestore(hwep->lock, flags);
677 return -EAGAIN;
678 }
679
680 direction = hwep->dir;
681 do {
682 retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);
683
684 if (!value)
685 hwep->wedge = 0;
686
687 if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
688 hwep->dir = (hwep->dir == TX) ? RX : TX;
689
690 } while (hwep->dir != direction);
691
692 spin_unlock_irqrestore(hwep->lock, flags);
693 return retval;
694}
695
696
659/** 697/**
660 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts 698 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
661 * @gadget: gadget 699 * @gadget: gadget
@@ -1051,7 +1089,7 @@ __acquires(ci->lock)
1051 num += ci->hw_ep_max / 2; 1089 num += ci->hw_ep_max / 2;
1052 1090
1053 spin_unlock(&ci->lock); 1091 spin_unlock(&ci->lock);
1054 err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep); 1092 err = _ep_set_halt(&ci->ci_hw_ep[num].ep, 1, false);
1055 spin_lock(&ci->lock); 1093 spin_lock(&ci->lock);
1056 if (!err) 1094 if (!err)
1057 isr_setup_status_phase(ci); 1095 isr_setup_status_phase(ci);
@@ -1117,8 +1155,8 @@ delegate:
1117 1155
1118 if (err < 0) { 1156 if (err < 0) {
1119 spin_unlock(&ci->lock); 1157 spin_unlock(&ci->lock);
1120 if (usb_ep_set_halt(&hwep->ep)) 1158 if (_ep_set_halt(&hwep->ep, 1, false))
1121 dev_err(ci->dev, "error: ep_set_halt\n"); 1159 dev_err(ci->dev, "error: _ep_set_halt\n");
1122 spin_lock(&ci->lock); 1160 spin_lock(&ci->lock);
1123 } 1161 }
1124} 1162}
@@ -1149,9 +1187,9 @@ __acquires(ci->lock)
1149 err = isr_setup_status_phase(ci); 1187 err = isr_setup_status_phase(ci);
1150 if (err < 0) { 1188 if (err < 0) {
1151 spin_unlock(&ci->lock); 1189 spin_unlock(&ci->lock);
1152 if (usb_ep_set_halt(&hwep->ep)) 1190 if (_ep_set_halt(&hwep->ep, 1, false))
1153 dev_err(ci->dev, 1191 dev_err(ci->dev,
1154 "error: ep_set_halt\n"); 1192 "error: _ep_set_halt\n");
1155 spin_lock(&ci->lock); 1193 spin_lock(&ci->lock);
1156 } 1194 }
1157 } 1195 }
@@ -1397,41 +1435,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
1397 */ 1435 */
1398static int ep_set_halt(struct usb_ep *ep, int value) 1436static int ep_set_halt(struct usb_ep *ep, int value)
1399{ 1437{
1400 struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); 1438 return _ep_set_halt(ep, value, true);
1401 int direction, retval = 0;
1402 unsigned long flags;
1403
1404 if (ep == NULL || hwep->ep.desc == NULL)
1405 return -EINVAL;
1406
1407 if (usb_endpoint_xfer_isoc(hwep->ep.desc))
1408 return -EOPNOTSUPP;
1409
1410 spin_lock_irqsave(hwep->lock, flags);
1411
1412#ifndef STALL_IN
1413 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
1414 if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX &&
1415 !list_empty(&hwep->qh.queue)) {
1416 spin_unlock_irqrestore(hwep->lock, flags);
1417 return -EAGAIN;
1418 }
1419#endif
1420
1421 direction = hwep->dir;
1422 do {
1423 retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);
1424
1425 if (!value)
1426 hwep->wedge = 0;
1427
1428 if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
1429 hwep->dir = (hwep->dir == TX) ? RX : TX;
1430
1431 } while (hwep->dir != direction);
1432
1433 spin_unlock_irqrestore(hwep->lock, flags);
1434 return retval;
1435} 1439}
1436 1440
1437/** 1441/**