From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: mnural Date: Mon, 14 Apr 2025 14:44:20 +0530 Subject: Fix freezing on turning off camera Detailed logs and reason behind can be seen here: https://github.com/t2linux/T2-Debian-and-Ubuntu-Kernel/issues/130#issuecomment-2799130835 --- drivers/staging/apple-bce/vhci/transfer.c | 16 ++++++++-- drivers/staging/apple-bce/vhci/transfer.h | 4 ++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/staging/apple-bce/vhci/transfer.c b/drivers/staging/apple-bce/vhci/transfer.c index 111111111111..222222222222 100644 --- a/drivers/staging/apple-bce/vhci/transfer.c +++ b/drivers/staging/apple-bce/vhci/transfer.c @@ -400,6 +400,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u struct bce_vhci_urb *vurb; unsigned long flags; int ret; + enum bce_vhci_urb_state old_state; spin_lock_irqsave(&q->urb_lock, flags); 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 } vurb = urb->hcpriv; + + old_state = vurb->state; /* save old state to use later because we'll set state as cancelled */ + + if (old_state == BCE_VHCI_URB_CANCELLED) { + spin_unlock_irqrestore(&q->urb_lock, flags); + pr_debug("bce-vhci: URB %p is already cancelled, skipping\n", urb); + return 0; + } + + vurb->state = BCE_VHCI_URB_CANCELLED; + /* If the URB wasn't posted to the device yet, we can still remove it on the host without pausing the queue. */ - if (vurb->state != BCE_VHCI_URB_INIT_PENDING) { + if (old_state != BCE_VHCI_URB_INIT_PENDING) { pr_debug("bce-vhci: [%02x] Cancelling URB\n", q->endp_addr); 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 usb_hcd_giveback_urb(q->vhci->hcd, urb, status); - if (vurb->state != BCE_VHCI_URB_INIT_PENDING) + if (old_state != BCE_VHCI_URB_INIT_PENDING) bce_vhci_transfer_queue_resume(q, BCE_VHCI_PAUSE_INTERNAL_WQ); kfree(vurb); diff --git a/drivers/staging/apple-bce/vhci/transfer.h b/drivers/staging/apple-bce/vhci/transfer.h index 111111111111..222222222222 100644 --- a/drivers/staging/apple-bce/vhci/transfer.h +++ b/drivers/staging/apple-bce/vhci/transfer.h @@ -44,7 +44,9 @@ enum bce_vhci_urb_state { BCE_VHCI_URB_CONTROL_WAITING_FOR_SETUP_REQUEST, BCE_VHCI_URB_CONTROL_WAITING_FOR_SETUP_COMPLETION, - BCE_VHCI_URB_CONTROL_COMPLETE + BCE_VHCI_URB_CONTROL_COMPLETE, + + BCE_VHCI_URB_CANCELLED }; struct bce_vhci_urb { struct urb *urb; -- Armbian