@@ -400,6 +400,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
400
400
struct bce_vhci_urb * vurb ;
401
401
unsigned long flags ;
402
402
int ret ;
403
+ enum bce_vhci_urb_state old_state ;
403
404
404
405
spin_lock_irqsave (& q -> urb_lock , flags );
405
406
if ((ret = usb_hcd_check_unlink_urb (q -> vhci -> hcd , urb , status ))) {
@@ -408,8 +409,19 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
408
409
}
409
410
410
411
vurb = urb -> hcpriv ;
412
+
413
+ old_state = vurb -> state ; /* save old state to use later because we'll set state as cancelled */
414
+
415
+ if (old_state == BCE_VHCI_URB_CANCELLED ) {
416
+ spin_unlock_irqrestore (& q -> urb_lock , flags );
417
+ pr_debug ("bce-vhci: URB %p is already cancelled, skipping\n" , urb );
418
+ return 0 ;
419
+ }
420
+
421
+ vurb -> state = BCE_VHCI_URB_CANCELLED ;
422
+
411
423
/* If the URB wasn't posted to the device yet, we can still remove it on the host without pausing the queue. */
412
- if (vurb -> state != BCE_VHCI_URB_INIT_PENDING ) {
424
+ if (old_state != BCE_VHCI_URB_INIT_PENDING ) {
413
425
pr_debug ("bce-vhci: [%02x] Cancelling URB\n" , q -> endp_addr );
414
426
415
427
spin_unlock_irqrestore (& q -> urb_lock , flags );
@@ -425,7 +437,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
425
437
426
438
usb_hcd_giveback_urb (q -> vhci -> hcd , urb , status );
427
439
428
- if (vurb -> state != BCE_VHCI_URB_INIT_PENDING )
440
+ if (old_state != BCE_VHCI_URB_INIT_PENDING )
429
441
bce_vhci_transfer_queue_resume (q , BCE_VHCI_PAUSE_INTERNAL_WQ );
430
442
431
443
kfree (vurb );
0 commit comments