On Mon, 2014-10-06 at 18:33 +0530, Naveen Kumar Parna wrote: > Thank you very much. I will try that patch. Then please try. Regards Oliver
>From f9f74591abed07ee71c46d443dd10176d05096c5 Mon Sep 17 00:00:00 2001 From: Oliver Neukum <oneukum@xxxxxxx> 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 <oneukum@xxxxxxx> --- 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..65a2c6b 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, waker); + int err; + + err = usb_autopm_get_interface(data->intf); + if (err < 0) + return; + + err = usb_clear_halt(data->udev, + usb_rcvbulkpipe(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_ATOMIC); + + 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