diff options
author | David Vrabel <david.vrabel@csr.com> | 2009-04-08 13:36:31 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-04-17 13:50:27 -0400 |
commit | f720af91ec2c67e9a1abbd935570f4b4e1f0dd54 (patch) | |
tree | af1dfd698dedced7944dcce7dcb84ed6fd8860aa /drivers/usb | |
parent | 7f0406db5fe4dd3ad3cbd53830239a87d68156fd (diff) |
USB: whci-hcd: check return value of usb_hcd_link_urb_to_ep()
Check the return value of usb_hcd_link_urb_to_ep() and do not add the
urb to the ASL/PZL if it returns an error.
Omitting the check results in urbs that appear to be submitted
successfully but then cannot be unliked (because
usb_hcd_check_unlink_urb() returns an error). This can cause khubd (for
example) to block forever in usb_kill_urb().
Signed-off-by: David Vrabel <david.vrabel@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/whci/asl.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/whci/pzl.c | 12 |
2 files changed, 18 insertions, 6 deletions
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index be753f664993..c2050785a819 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
@@ -255,23 +255,29 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) | |||
255 | 255 | ||
256 | spin_lock_irqsave(&whc->lock, flags); | 256 | spin_lock_irqsave(&whc->lock, flags); |
257 | 257 | ||
258 | err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); | ||
259 | if (err < 0) { | ||
260 | spin_unlock_irqrestore(&whc->lock, flags); | ||
261 | return err; | ||
262 | } | ||
263 | |||
258 | qset = get_qset(whc, urb, GFP_ATOMIC); | 264 | qset = get_qset(whc, urb, GFP_ATOMIC); |
259 | if (qset == NULL) | 265 | if (qset == NULL) |
260 | err = -ENOMEM; | 266 | err = -ENOMEM; |
261 | else | 267 | else |
262 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); | 268 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); |
263 | if (!err) { | 269 | if (!err) { |
264 | usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); | ||
265 | if (!qset->in_sw_list) | 270 | if (!qset->in_sw_list) |
266 | asl_qset_insert_begin(whc, qset); | 271 | asl_qset_insert_begin(whc, qset); |
267 | } | 272 | } else |
273 | usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); | ||
268 | 274 | ||
269 | spin_unlock_irqrestore(&whc->lock, flags); | 275 | spin_unlock_irqrestore(&whc->lock, flags); |
270 | 276 | ||
271 | if (!err) | 277 | if (!err) |
272 | queue_work(whc->workqueue, &whc->async_work); | 278 | queue_work(whc->workqueue, &whc->async_work); |
273 | 279 | ||
274 | return 0; | 280 | return err; |
275 | } | 281 | } |
276 | 282 | ||
277 | /** | 283 | /** |
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index 0c40022a6b2f..ff4ef9e910d9 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c | |||
@@ -283,23 +283,29 @@ int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) | |||
283 | 283 | ||
284 | spin_lock_irqsave(&whc->lock, flags); | 284 | spin_lock_irqsave(&whc->lock, flags); |
285 | 285 | ||
286 | err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); | ||
287 | if (err < 0) { | ||
288 | spin_unlock_irqrestore(&whc->lock, flags); | ||
289 | return err; | ||
290 | } | ||
291 | |||
286 | qset = get_qset(whc, urb, GFP_ATOMIC); | 292 | qset = get_qset(whc, urb, GFP_ATOMIC); |
287 | if (qset == NULL) | 293 | if (qset == NULL) |
288 | err = -ENOMEM; | 294 | err = -ENOMEM; |
289 | else | 295 | else |
290 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); | 296 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); |
291 | if (!err) { | 297 | if (!err) { |
292 | usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); | ||
293 | if (!qset->in_sw_list) | 298 | if (!qset->in_sw_list) |
294 | qset_insert_in_sw_list(whc, qset); | 299 | qset_insert_in_sw_list(whc, qset); |
295 | } | 300 | } else |
301 | usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); | ||
296 | 302 | ||
297 | spin_unlock_irqrestore(&whc->lock, flags); | 303 | spin_unlock_irqrestore(&whc->lock, flags); |
298 | 304 | ||
299 | if (!err) | 305 | if (!err) |
300 | queue_work(whc->workqueue, &whc->periodic_work); | 306 | queue_work(whc->workqueue, &whc->periodic_work); |
301 | 307 | ||
302 | return 0; | 308 | return err; |
303 | } | 309 | } |
304 | 310 | ||
305 | /** | 311 | /** |