Return-Path: Message-ID: <1412676071.1926.1.camel@linux-0dmf.site> Subject: Re: btusb_intr_complete returns -EPIPE From: Oliver Neukum To: Naveen Kumar Parna Cc: "linux-bluetooth@vger.kernel.org" , linux-usb@vger.kernel.org, acho@suse.com Date: Tue, 07 Oct 2014 12:01:11 +0200 In-Reply-To: References: <1412598268.1132.15.camel@linux-0dmf.site> <1412600108.28177.0.camel@linux-0dmf.site> <1412602169.28177.2.camel@linux-0dmf.site> <1412607050.1743.1.camel@linux-0dmf.site> Content-Type: multipart/mixed; boundary="=-qkGcsr9gj8O6hqRRVOH8" Mime-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org List-ID: --=-qkGcsr9gj8O6hqRRVOH8 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit On Tue, 2014-10-07 at 12:14 +0530, Naveen Kumar Parna wrote: > > + err = usb_clear_halt(data->udev, > > + usb_rcvbulkpipe(data->udev, > > + data->intr_ep->bEndpointAddress)); > > EPIPE occurred for INT in endpoint, so we should use usb_rcvintpipe() > instead of usb_rcvbulkpipe() right? Yes. And I noticed a copy and past error. > Does the “lsusb –v” gives any clue about the reason for getting -EPIPE? No. Could you nevertheless test the attached version? Regards Oliver --=-qkGcsr9gj8O6hqRRVOH8 Content-Disposition: attachment; filename="0001-btusb-clear-halt-if-intr-in-stalls.patch" Content-Type: text/x-patch; name="0001-btusb-clear-halt-if-intr-in-stalls.patch"; charset="UTF-8" Content-Transfer-Encoding: 7bit >From b8109554277bde9da4275e7a9ce1ef76b43ebd59 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 6 Oct 2014 15:27:54 +0200 Subject: [PATCH] btusb: clear halt if intr in stalls Use a work queue for clearing a halt. Signed-off-by: Oliver Neukum --- drivers/bluetooth/btusb.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 292c38e..716c37a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -273,6 +273,7 @@ struct btusb_data { struct work_struct work; struct work_struct waker; + struct work_struct intr_in_work; struct usb_anchor tx_anchor; struct usb_anchor intr_anchor; @@ -314,14 +315,15 @@ static void btusb_intr_complete(struct urb *urb) struct hci_dev *hdev = urb->context; struct btusb_data *data = hci_get_drvdata(hdev); int err; + int status = urb->status; BT_DBG("%s urb %p status %d count %d", hdev->name, - urb, urb->status, urb->actual_length); + urb, status, urb->actual_length); if (!test_bit(HCI_RUNNING, &hdev->flags)) return; - if (urb->status == 0) { + if (status == 0) { hdev->stat.byte_rx += urb->actual_length; if (hci_recv_fragment(hdev, HCI_EVENT_PKT, @@ -330,6 +332,10 @@ static void btusb_intr_complete(struct urb *urb) BT_ERR("%s corrupted event packet", hdev->name); hdev->stat.err_rx++; } + } else if (status == -EPIPE) { + usb_mark_last_busy(data->udev); + schedule_work(&data->intr_in_work); + return; } if (!test_bit(BTUSB_INTR_RUNNING, &data->flags)) @@ -971,6 +977,29 @@ static void btusb_waker(struct work_struct *work) usb_autopm_put_interface(data->intf); } +static void clear_halt_intr_in(struct work_struct *work) +{ + struct btusb_data *data = container_of(work, struct btusb_data, intr_in_work); + int err; + + err = usb_autopm_get_interface(data->intf); + if (err < 0) + return; + + err = usb_clear_halt(data->udev, + usb_rcvintpipe(data->udev, + data->intr_ep->bEndpointAddress)); + if (err < 0) + return; + + if (!test_bit(BTUSB_INTR_RUNNING, &data->flags)) + return; + + btusb_submit_intr_urb(data->hdev, GFP_NOIO); + + usb_autopm_put_interface(data->intf); +} + static int btusb_setup_bcm92035(struct hci_dev *hdev) { struct sk_buff *skb; @@ -1759,6 +1788,7 @@ static int btusb_probe(struct usb_interface *intf, INIT_WORK(&data->work, btusb_work); INIT_WORK(&data->waker, btusb_waker); + INIT_WORK(&data->intr_in_work, clear_halt_intr_in); spin_lock_init(&data->txlock); init_usb_anchor(&data->tx_anchor); -- 1.8.4.5 --=-qkGcsr9gj8O6hqRRVOH8--