diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1775ad471edd..5480352f984d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -5177,6 +5177,7 @@ int usb_reset_device(struct usb_device *udev) | |||
5177 | { | 5177 | { |
5178 | int ret; | 5178 | int ret; |
5179 | int i; | 5179 | int i; |
5180 | unsigned int noio_flag; | ||
5180 | struct usb_host_config *config = udev->actconfig; | 5181 | struct usb_host_config *config = udev->actconfig; |
5181 | 5182 | ||
5182 | if (udev->state == USB_STATE_NOTATTACHED || | 5183 | if (udev->state == USB_STATE_NOTATTACHED || |
@@ -5186,6 +5187,17 @@ int usb_reset_device(struct usb_device *udev) | |||
5186 | return -EINVAL; | 5187 | return -EINVAL; |
5187 | } | 5188 | } |
5188 | 5189 | ||
5190 | /* | ||
5191 | * Don't allocate memory with GFP_KERNEL in current | ||
5192 | * context to avoid possible deadlock if usb mass | ||
5193 | * storage interface or usbnet interface(iSCSI case) | ||
5194 | * is included in current configuration. The easist | ||
5195 | * approach is to do it for every device reset, | ||
5196 | * because the device 'memalloc_noio' flag may have | ||
5197 | * not been set before reseting the usb device. | ||
5198 | */ | ||
5199 | noio_flag = memalloc_noio_save(); | ||
5200 | |||
5189 | /* Prevent autosuspend during the reset */ | 5201 | /* Prevent autosuspend during the reset */ |
5190 | usb_autoresume_device(udev); | 5202 | usb_autoresume_device(udev); |
5191 | 5203 | ||
@@ -5230,6 +5242,7 @@ int usb_reset_device(struct usb_device *udev) | |||
5230 | } | 5242 | } |
5231 | 5243 | ||
5232 | usb_autosuspend_device(udev); | 5244 | usb_autosuspend_device(udev); |
5245 | memalloc_noio_restore(noio_flag); | ||
5233 | return ret; | 5246 | return ret; |
5234 | } | 5247 | } |
5235 | EXPORT_SYMBOL_GPL(usb_reset_device); | 5248 | EXPORT_SYMBOL_GPL(usb_reset_device); |