diff options
Diffstat (limited to 'drivers/usb/core/message.c')
-rw-r--r-- | drivers/usb/core/message.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index de51667dd64d..31fb204f44c6 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -1039,14 +1039,15 @@ static void remove_intf_ep_devs(struct usb_interface *intf) | |||
1039 | * @dev: the device whose endpoint is being disabled | 1039 | * @dev: the device whose endpoint is being disabled |
1040 | * @epaddr: the endpoint's address. Endpoint number for output, | 1040 | * @epaddr: the endpoint's address. Endpoint number for output, |
1041 | * endpoint number + USB_DIR_IN for input | 1041 | * endpoint number + USB_DIR_IN for input |
1042 | * @reset_hardware: flag to erase any endpoint state stored in the | ||
1043 | * controller hardware | ||
1042 | * | 1044 | * |
1043 | * Deallocates hcd/hardware state for this endpoint ... and nukes all | 1045 | * Disables the endpoint for URB submission and nukes all pending URBs. |
1044 | * pending urbs. | 1046 | * If @reset_hardware is set then also deallocates hcd/hardware state |
1045 | * | 1047 | * for the endpoint. |
1046 | * If the HCD hasn't registered a disable() function, this sets the | ||
1047 | * endpoint's maxpacket size to 0 to prevent further submissions. | ||
1048 | */ | 1048 | */ |
1049 | void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | 1049 | void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr, |
1050 | bool reset_hardware) | ||
1050 | { | 1051 | { |
1051 | unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; | 1052 | unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; |
1052 | struct usb_host_endpoint *ep; | 1053 | struct usb_host_endpoint *ep; |
@@ -1056,15 +1057,18 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | |||
1056 | 1057 | ||
1057 | if (usb_endpoint_out(epaddr)) { | 1058 | if (usb_endpoint_out(epaddr)) { |
1058 | ep = dev->ep_out[epnum]; | 1059 | ep = dev->ep_out[epnum]; |
1059 | dev->ep_out[epnum] = NULL; | 1060 | if (reset_hardware) |
1061 | dev->ep_out[epnum] = NULL; | ||
1060 | } else { | 1062 | } else { |
1061 | ep = dev->ep_in[epnum]; | 1063 | ep = dev->ep_in[epnum]; |
1062 | dev->ep_in[epnum] = NULL; | 1064 | if (reset_hardware) |
1065 | dev->ep_in[epnum] = NULL; | ||
1063 | } | 1066 | } |
1064 | if (ep) { | 1067 | if (ep) { |
1065 | ep->enabled = 0; | 1068 | ep->enabled = 0; |
1066 | usb_hcd_flush_endpoint(dev, ep); | 1069 | usb_hcd_flush_endpoint(dev, ep); |
1067 | usb_hcd_disable_endpoint(dev, ep); | 1070 | if (reset_hardware) |
1071 | usb_hcd_disable_endpoint(dev, ep); | ||
1068 | } | 1072 | } |
1069 | } | 1073 | } |
1070 | 1074 | ||
@@ -1072,17 +1076,21 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | |||
1072 | * usb_disable_interface -- Disable all endpoints for an interface | 1076 | * usb_disable_interface -- Disable all endpoints for an interface |
1073 | * @dev: the device whose interface is being disabled | 1077 | * @dev: the device whose interface is being disabled |
1074 | * @intf: pointer to the interface descriptor | 1078 | * @intf: pointer to the interface descriptor |
1079 | * @reset_hardware: flag to erase any endpoint state stored in the | ||
1080 | * controller hardware | ||
1075 | * | 1081 | * |
1076 | * Disables all the endpoints for the interface's current altsetting. | 1082 | * Disables all the endpoints for the interface's current altsetting. |
1077 | */ | 1083 | */ |
1078 | void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf) | 1084 | void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf, |
1085 | bool reset_hardware) | ||
1079 | { | 1086 | { |
1080 | struct usb_host_interface *alt = intf->cur_altsetting; | 1087 | struct usb_host_interface *alt = intf->cur_altsetting; |
1081 | int i; | 1088 | int i; |
1082 | 1089 | ||
1083 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) { | 1090 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) { |
1084 | usb_disable_endpoint(dev, | 1091 | usb_disable_endpoint(dev, |
1085 | alt->endpoint[i].desc.bEndpointAddress); | 1092 | alt->endpoint[i].desc.bEndpointAddress, |
1093 | reset_hardware); | ||
1086 | } | 1094 | } |
1087 | } | 1095 | } |
1088 | 1096 | ||
@@ -1103,8 +1111,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
1103 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, | 1111 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, |
1104 | skip_ep0 ? "non-ep0" : "all"); | 1112 | skip_ep0 ? "non-ep0" : "all"); |
1105 | for (i = skip_ep0; i < 16; ++i) { | 1113 | for (i = skip_ep0; i < 16; ++i) { |
1106 | usb_disable_endpoint(dev, i); | 1114 | usb_disable_endpoint(dev, i, true); |
1107 | usb_disable_endpoint(dev, i + USB_DIR_IN); | 1115 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); |
1108 | } | 1116 | } |
1109 | dev->toggle[0] = dev->toggle[1] = 0; | 1117 | dev->toggle[0] = dev->toggle[1] = 0; |
1110 | 1118 | ||
@@ -1274,7 +1282,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
1274 | remove_intf_ep_devs(iface); | 1282 | remove_intf_ep_devs(iface); |
1275 | usb_remove_sysfs_intf_files(iface); | 1283 | usb_remove_sysfs_intf_files(iface); |
1276 | } | 1284 | } |
1277 | usb_disable_interface(dev, iface); | 1285 | usb_disable_interface(dev, iface, true); |
1278 | 1286 | ||
1279 | iface->cur_altsetting = alt; | 1287 | iface->cur_altsetting = alt; |
1280 | 1288 | ||
@@ -1353,8 +1361,8 @@ int usb_reset_configuration(struct usb_device *dev) | |||
1353 | */ | 1361 | */ |
1354 | 1362 | ||
1355 | for (i = 1; i < 16; ++i) { | 1363 | for (i = 1; i < 16; ++i) { |
1356 | usb_disable_endpoint(dev, i); | 1364 | usb_disable_endpoint(dev, i, true); |
1357 | usb_disable_endpoint(dev, i + USB_DIR_IN); | 1365 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); |
1358 | } | 1366 | } |
1359 | 1367 | ||
1360 | config = dev->actconfig; | 1368 | config = dev->actconfig; |