rpms/kernel/F-12 kernel.spec, 1.1872, 1.1873 linux-2.6-bluetooth-autosuspend.diff, 1.2, 1.3

Chuck Ebbert cebbert at fedoraproject.org
Sat Oct 17 12:53:09 UTC 2009


Author: cebbert

Update of /cvs/pkgs/rpms/kernel/F-12
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv15041

Modified Files:
	kernel.spec linux-2.6-bluetooth-autosuspend.diff 
Log Message:
Replace linux-2.6-bluetooth-autosuspend.diff with upstream version.


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-12/kernel.spec,v
retrieving revision 1.1872
retrieving revision 1.1873
diff -u -p -r1.1872 -r1.1873
--- kernel.spec	16 Oct 2009 17:04:02 -0000	1.1872
+++ kernel.spec	17 Oct 2009 12:53:08 -0000	1.1873
@@ -2067,6 +2067,9 @@ fi
 # and build.
 
 %changelog
+* Sat Oct 17 2009 Chuck Ebbert <cebbert at redhat.com>
+- Replace linux-2.6-bluetooth-autosuspend.diff with upstream version.
+
 * Fri Oct 16 2009 Josef Bacik <josef at toxicpanda.com>
 - Update btrfs to latest upstream
 

linux-2.6-bluetooth-autosuspend.diff:
 btusb.c |  194 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 174 insertions(+), 20 deletions(-)

Index: linux-2.6-bluetooth-autosuspend.diff
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-12/linux-2.6-bluetooth-autosuspend.diff,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -p -r1.2 -r1.3
--- linux-2.6-bluetooth-autosuspend.diff	10 Aug 2009 04:13:28 -0000	1.2
+++ linux-2.6-bluetooth-autosuspend.diff	17 Oct 2009 12:53:08 -0000	1.3
@@ -1,7 +1,43 @@
+From: Oliver Neukum <oliver at neukum.org>
+Date: Mon, 24 Aug 2009 21:44:59 +0000 (+0200)
+Subject: Bluetooth: Add USB autosuspend support to btusb driver
+X-Git-Tag: v2.6.32-rc1~703^2~221^2~4
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=7bee549e197c9c0e92b89857a409675c1d5e9dff
+
+Bluetooth: Add USB autosuspend support to btusb driver
+
+This patch adds support of USB autosuspend to the btusb driver.
+
+If the device doesn't support remote wakeup, simple support based on
+up/down is provided. If the device supports remote wakeup, additional
+support for autosuspend while the interface is up is provided. This is
+done by queueing URBs in an anchor structure and waking the device up
+from a work queue on sending. Reception triggers remote wakeup.
+
+The last busy facility of the USB autosuspend code is used. To close
+a race between autosuspend and transmission, a counter of ongoing
+transmissions is maintained.
+
+Add #ifdefs for CONFIG_PM as necessary.
+
+Signed-off-by: Oliver Neukum <oliver at neukum.org>
+Tested-by: Sarah Sharp <sarah.a.sharp at linux.intel.com>
+Signed-off-by: Marcel Holtmann <marcel at holtmann.org>
+---
+
 diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
-index e70c57e..ac94f91 100644
+index 124db8c..7ba91aa 100644
 --- a/drivers/bluetooth/btusb.c
 +++ b/drivers/bluetooth/btusb.c
+@@ -35,7 +35,7 @@
+ #include <net/bluetooth/bluetooth.h>
+ #include <net/bluetooth/hci_core.h>
+ 
+-#define VERSION "0.5"
++#define VERSION "0.6"
+ 
+ static int ignore_dga;
+ static int ignore_csr;
 @@ -145,6 +145,7 @@ static struct usb_device_id blacklist_table[] = {
  #define BTUSB_INTR_RUNNING	0
  #define BTUSB_BULK_RUNNING	1
@@ -10,7 +46,7 @@ index e70c57e..ac94f91 100644
  
  struct btusb_data {
  	struct hci_dev       *hdev;
-@@ -157,11 +158,13 @@ struct btusb_data {
+@@ -157,11 +158,15 @@ struct btusb_data {
  	unsigned long flags;
  
  	struct work_struct work;
@@ -21,47 +57,44 @@ index e70c57e..ac94f91 100644
  	struct usb_anchor bulk_anchor;
  	struct usb_anchor isoc_anchor;
 +	struct usb_anchor deferred;
++	int tx_in_flight;
++	spinlock_t txlock;
  
  	struct usb_endpoint_descriptor *intr_ep;
  	struct usb_endpoint_descriptor *bulk_tx_ep;
-@@ -174,6 +177,7 @@ struct btusb_data {
+@@ -174,8 +179,23 @@ struct btusb_data {
  	unsigned int sco_num;
  	int isoc_altsetting;
  	int suspend_count;
 +	int did_iso_resume:1;
  };
  
++static int inc_tx(struct btusb_data *data)
++{
++	unsigned long flags;
++	int rv;
++
++	spin_lock_irqsave(&data->txlock, flags);
++	rv = test_bit(BTUSB_SUSPENDING, &data->flags);
++	if (!rv)
++		data->tx_in_flight++;
++	spin_unlock_irqrestore(&data->txlock, flags);
++
++	return rv;
++}
++
  static void btusb_intr_complete(struct urb *urb)
-@@ -202,6 +206,10 @@ static void btusb_intr_complete(struct urb *urb)
+ {
+ 	struct hci_dev *hdev = urb->context;
+@@ -202,6 +222,7 @@ static void btusb_intr_complete(struct urb *urb)
  	if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
  		return;
  
-+	if (test_bit(BTUSB_SUSPENDING, &data->flags))
-+		return;
-+
 +	usb_mark_last_busy(data->udev);
  	usb_anchor_urb(urb, &data->intr_anchor);
  
  	err = usb_submit_urb(urb, GFP_ATOMIC);
-@@ -285,6 +293,9 @@ static void btusb_bulk_complete(struct urb *urb)
- 	if (!test_bit(BTUSB_BULK_RUNNING, &data->flags))
- 		return;
- 
-+	if (test_bit(BTUSB_SUSPENDING, &data->flags))
-+		return;
-+
- 	usb_anchor_urb(urb, &data->bulk_anchor);
- 
- 	err = usb_submit_urb(urb, GFP_ATOMIC);
-@@ -320,6 +331,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
- 		return -ENOMEM;
- 	}
- 
-+	usb_mark_last_busy(data->udev);
- 	pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
- 
- 	usb_fill_bulk_urb(urb, data->udev, pipe,
-@@ -327,6 +339,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
+@@ -325,6 +346,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
  
  	urb->transfer_flags |= URB_FREE_BUFFER;
  
@@ -69,30 +102,72 @@ index e70c57e..ac94f91 100644
  	usb_anchor_urb(urb, &data->bulk_anchor);
  
  	err = usb_submit_urb(urb, mem_flags);
-@@ -375,6 +388,9 @@ static void btusb_isoc_complete(struct urb *urb)
- 	if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
- 		return;
- 
-+	if (test_bit(BTUSB_SUSPENDING, &data->flags))
-+		return;
+@@ -463,6 +485,33 @@ static void btusb_tx_complete(struct urb *urb)
+ {
+ 	struct sk_buff *skb = urb->context;
+ 	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
++	struct btusb_data *data = hdev->driver_data;
++
++	BT_DBG("%s urb %p status %d count %d", hdev->name,
++					urb, urb->status, urb->actual_length);
++
++	if (!test_bit(HCI_RUNNING, &hdev->flags))
++		goto done;
++
++	if (!urb->status)
++		hdev->stat.byte_tx += urb->transfer_buffer_length;
++	else
++		hdev->stat.err_tx++;
++
++done:
++	spin_lock(&data->txlock);
++	data->tx_in_flight--;
++	spin_unlock(&data->txlock);
++
++	kfree(urb->setup_packet);
++
++	kfree_skb(skb);
++}
 +
- 	usb_anchor_urb(urb, &data->isoc_anchor);
++static void btusb_isoc_tx_complete(struct urb *urb)
++{
++	struct sk_buff *skb = urb->context;
++	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
  
- 	err = usb_submit_urb(urb, GFP_ATOMIC);
-@@ -490,6 +506,12 @@ static int btusb_open(struct hci_dev *hdev)
+ 	BT_DBG("%s urb %p status %d count %d", hdev->name,
+ 					urb, urb->status, urb->actual_length);
+@@ -488,11 +537,17 @@ static int btusb_open(struct hci_dev *hdev)
  
  	BT_DBG("%s", hdev->name);
  
 +	err = usb_autopm_get_interface(data->intf);
 +	if (err < 0)
 +		return err;
++
 +	data->intf->needs_remote_wakeup = 1;
-+	usb_autopm_put_interface(data->intf);
 +
  	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- 		return 0;
+-		return 0;
++		goto done;
+ 
+ 	if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
+-		return 0;
++		goto done;
+ 
+ 	err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
+ 	if (err < 0)
+@@ -507,17 +562,28 @@ static int btusb_open(struct hci_dev *hdev)
+ 	set_bit(BTUSB_BULK_RUNNING, &data->flags);
+ 	btusb_submit_bulk_urb(hdev, GFP_KERNEL);
+ 
++done:
++	usb_autopm_put_interface(data->intf);
+ 	return 0;
  
-@@ -517,9 +539,17 @@ failed:
+ failed:
+ 	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+ 	clear_bit(HCI_RUNNING, &hdev->flags);
++	usb_autopm_put_interface(data->intf);
  	return err;
  }
  
@@ -110,7 +185,7 @@ index e70c57e..ac94f91 100644
  
  	BT_DBG("%s", hdev->name);
  
-@@ -529,13 +559,15 @@ static int btusb_close(struct hci_dev *hdev)
+@@ -527,13 +593,16 @@ static int btusb_close(struct hci_dev *hdev)
  	cancel_work_sync(&data->work);
  
  	clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
@@ -121,82 +196,84 @@ index e70c57e..ac94f91 100644
 -
  	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
 -	usb_kill_anchored_urbs(&data->intr_anchor);
-+	btusb_stop_traffic(data);
 +
++	btusb_stop_traffic(data);
 +	err = usb_autopm_get_interface(data->intf);
-+	if (!err) {
-+		data->intf->needs_remote_wakeup = 0;
-+		usb_autopm_put_interface(data->intf);
-+	}
++	if (err < 0)
++		return 0;
++
++	data->intf->needs_remote_wakeup = 0;
++	usb_autopm_put_interface(data->intf);
  
  	return 0;
  }
-@@ -558,7 +590,7 @@ static int btusb_send_frame(struct sk_buff *skb)
- 	struct usb_ctrlrequest *dr;
- 	struct urb *urb;
- 	unsigned int pipe;
--	int err;
-+	int err, susp;
- 
- 	BT_DBG("%s", hdev->name);
+@@ -620,7 +689,7 @@ static int btusb_send_frame(struct sk_buff *skb)
+ 		urb->dev      = data->udev;
+ 		urb->pipe     = pipe;
+ 		urb->context  = skb;
+-		urb->complete = btusb_tx_complete;
++		urb->complete = btusb_isoc_tx_complete;
+ 		urb->interval = data->isoc_tx_ep->bInterval;
+ 
+ 		urb->transfer_flags  = URB_ISO_ASAP;
+@@ -631,12 +700,21 @@ static int btusb_send_frame(struct sk_buff *skb)
+ 				le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
+ 
+ 		hdev->stat.sco_tx++;
+-		break;
++		goto skip_waking;
  
-@@ -567,6 +599,7 @@ static int btusb_send_frame(struct sk_buff *skb)
- 
- 	switch (bt_cb(skb)->pkt_type) {
- 	case HCI_COMMAND_PKT:
-+		BT_DBG("HCI_COMMAND_PKT");
- 		urb = usb_alloc_urb(0, GFP_ATOMIC);
- 		if (!urb)
- 			return -ENOMEM;
-@@ -592,6 +625,7 @@ static int btusb_send_frame(struct sk_buff *skb)
- 		break;
- 
- 	case HCI_ACLDATA_PKT:
-+		BT_DBG("HCI_ACLDATA_PKT");
- 		if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1)
- 			return -ENODEV;
- 
-@@ -609,6 +643,7 @@ static int btusb_send_frame(struct sk_buff *skb)
- 		break;
- 
- 	case HCI_SCODATA_PKT:
-+		BT_DBG("HCI_SCODATA_PKT");
- 		if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1)
- 			return -ENODEV;
- 
-@@ -639,17 +674,22 @@ static int btusb_send_frame(struct sk_buff *skb)
+ 	default:
  		return -EILSEQ;
  	}
  
-+	spin_lock(&data->lock);
-+	susp = test_bit(BTUSB_SUSPENDING, &data->flags);
- 	usb_anchor_urb(urb, &data->tx_anchor);
--
--	err = usb_submit_urb(urb, GFP_ATOMIC);
--	if (err < 0) {
--		BT_ERR("%s urb %p submission failed", hdev->name, urb);
--		kfree(urb->setup_packet);
--		usb_unanchor_urb(urb);
-+	if (susp) {
++	err = inc_tx(data);
++	if (err) {
++		usb_anchor_urb(urb, &data->deferred);
 +		schedule_work(&data->waker);
 +		err = 0;
++		goto done;
++	}
++
++skip_waking:
+ 	usb_anchor_urb(urb, &data->tx_anchor);
+ 
+ 	err = usb_submit_urb(urb, GFP_ATOMIC);
+@@ -644,10 +722,13 @@ static int btusb_send_frame(struct sk_buff *skb)
+ 		BT_ERR("%s urb %p submission failed", hdev->name, urb);
+ 		kfree(urb->setup_packet);
+ 		usb_unanchor_urb(urb);
 +	} else {
-+		err = usb_submit_urb(urb, GFP_ATOMIC);
-+		if (err < 0) {
-+			BT_ERR("%s urb %p submission failed", hdev->name, urb);
-+			kfree(urb->setup_packet);
-+			usb_unanchor_urb(urb);
-+		}
-+		usb_free_urb(urb);
++		usb_mark_last_busy(data->udev);
  	}
--
--	usb_free_urb(urb);
--
-+	spin_unlock(&data->lock);
+ 
+ 	usb_free_urb(urb);
+ 
++done:
  	return err;
  }
  
-@@ -742,9 +782,26 @@ static void btusb_work(struct work_struct *work)
+@@ -719,8 +800,19 @@ static void btusb_work(struct work_struct *work)
+ {
+ 	struct btusb_data *data = container_of(work, struct btusb_data, work);
+ 	struct hci_dev *hdev = data->hdev;
++	int err;
+ 
+ 	if (hdev->conn_hash.sco_num > 0) {
++		if (!data->did_iso_resume) {
++			err = usb_autopm_get_interface(data->isoc);
++			if (err < 0) {
++				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
++				usb_kill_anchored_urbs(&data->isoc_anchor);
++				return;
++			}
++
++			data->did_iso_resume = 1;
++		}
+ 		if (data->isoc_altsetting != 2) {
+ 			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ 			usb_kill_anchored_urbs(&data->isoc_anchor);
+@@ -740,9 +832,25 @@ static void btusb_work(struct work_struct *work)
  		usb_kill_anchored_urbs(&data->isoc_anchor);
  
  		__set_isoc_interface(hdev, 0);
@@ -212,22 +289,22 @@ index e70c57e..ac94f91 100644
 +	struct btusb_data *data = container_of(work, struct btusb_data, waker);
 +	int err;
 +
-+	BUG_ON(data == NULL);
-+	BT_DBG("about to resume");
-+	BUG_ON(data->intf == NULL);
 +	err = usb_autopm_get_interface(data->intf);
-+	if (!err)
-+		usb_autopm_put_interface(data->intf);
++	if (err < 0)
++		return;
++
++	usb_autopm_put_interface(data->intf);
 +}
 +
  static int btusb_probe(struct usb_interface *intf,
  				const struct usb_device_id *id)
  {
-@@ -814,11 +871,13 @@ static int btusb_probe(struct usb_interface *intf,
+@@ -812,11 +920,14 @@ static int btusb_probe(struct usb_interface *intf,
  	spin_lock_init(&data->lock);
  
  	INIT_WORK(&data->work, btusb_work);
 +	INIT_WORK(&data->waker, btusb_waker);
++	spin_lock_init(&data->txlock);
  
  	init_usb_anchor(&data->tx_anchor);
  	init_usb_anchor(&data->intr_anchor);
@@ -237,15 +314,7 @@ index e70c57e..ac94f91 100644
  
  	hdev = hci_alloc_dev();
  	if (!hdev) {
-@@ -908,6 +967,7 @@ static int btusb_probe(struct usb_interface *intf,
- 	}
- 
- 	usb_set_intfdata(intf, data);
-+	usb_device_autosuspend_enable(data->udev);
- 
- 	return 0;
- }
-@@ -943,73 +1003,118 @@ static void btusb_disconnect(struct usb_interface *intf)
+@@ -941,6 +1052,7 @@ static void btusb_disconnect(struct usb_interface *intf)
  	hci_free_dev(hdev);
  }
  
@@ -253,129 +322,106 @@ index e70c57e..ac94f91 100644
  static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
  {
  	struct btusb_data *data = usb_get_intfdata(intf);
- 
--	BT_DBG("intf %p", intf);
-+	BT_DBG("%s called\n", __func__);
- 
+@@ -950,22 +1062,44 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
  	if (data->suspend_count++)
  		return 0;
  
--	cancel_work_sync(&data->work);
-+	spin_lock_irq(&data->lock);
-+	if (interface_to_usbdev(intf)->auto_pm &&
-+		!usb_anchor_empty(&data->tx_anchor)) {
-+		spin_unlock_irq(&data->lock);
++	spin_lock_irq(&data->txlock);
++	if (!(interface_to_usbdev(intf)->auto_pm && data->tx_in_flight)) {
++		set_bit(BTUSB_SUSPENDING, &data->flags);
++		spin_unlock_irq(&data->txlock);
++	} else {
++		spin_unlock_irq(&data->txlock);
++		data->suspend_count--;
 +		return -EBUSY;
 +	}
 +
-+	set_bit(BTUSB_SUSPENDING, &data->flags);
-+	spin_unlock_irq(&data->lock);
+ 	cancel_work_sync(&data->work);
  
-+	cancel_work_sync(&data->work);
 +	btusb_stop_traffic(data);
  	usb_kill_anchored_urbs(&data->tx_anchor);
-+	return 0;
-+}
  
 -	usb_kill_anchored_urbs(&data->isoc_anchor);
 -	usb_kill_anchored_urbs(&data->bulk_anchor);
 -	usb_kill_anchored_urbs(&data->intr_anchor);
-+static int play_deferred(struct btusb_data *data)
+-
+ 	return 0;
+ }
+ 
++static void play_deferred(struct btusb_data *data)
 +{
 +	struct urb *urb;
-+	int err = 0;
- 
--	return 0;
-+	while ((urb = usb_get_from_anchor(&data->tx_anchor))) {
++	int err;
++
++	while ((urb = usb_get_from_anchor(&data->deferred))) {
 +		err = usb_submit_urb(urb, GFP_ATOMIC);
 +		if (err < 0)
 +			break;
-+	}
 +
-+	usb_scuttle_anchored_urbs(&data->tx_anchor);
-+	return err;
- }
- 
++		data->tx_in_flight++;
++	}
++	usb_scuttle_anchored_urbs(&data->deferred);
++}
 +
  static int btusb_resume(struct usb_interface *intf)
  {
  	struct btusb_data *data = usb_get_intfdata(intf);
  	struct hci_dev *hdev = data->hdev;
 -	int err;
--
--	BT_DBG("intf %p", intf);
-+	int ret = 0;
++	int err = 0;
  
- 	if (--data->suspend_count)
+ 	BT_DBG("intf %p", intf);
+ 
+@@ -973,13 +1107,13 @@ static int btusb_resume(struct usb_interface *intf)
  		return 0;
  
--	if (!test_bit(HCI_RUNNING, &hdev->flags))
+ 	if (!test_bit(HCI_RUNNING, &hdev->flags))
 -		return 0;
-+	if (test_bit(HCI_RUNNING, &hdev->flags)) {
-+		spin_lock_irq(&data->lock);
-+		ret = play_deferred(data);
-+		clear_bit(BTUSB_SUSPENDING, &data->flags);
-+		spin_unlock_irq(&data->lock);
- 
--	if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
--		err = btusb_submit_intr_urb(hdev, GFP_NOIO);
--		if (err < 0) {
--			clear_bit(BTUSB_INTR_RUNNING, &data->flags);
++		goto done;
+ 
+ 	if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
+ 		err = btusb_submit_intr_urb(hdev, GFP_NOIO);
+ 		if (err < 0) {
+ 			clear_bit(BTUSB_INTR_RUNNING, &data->flags);
 -			return err;
-+		if (ret < 0) {
-+			clear_bit(HCI_RUNNING, &hdev->flags);
-+			return ret;
++			goto failed;
  		}
-+
-+		ret = btusb_submit_intr_urb(hdev, GFP_NOIO);
-+		if (ret < 0) {
-+			clear_bit(HCI_RUNNING, &hdev->flags);
-+			return ret;
-+		}
-+	} else {
-+		spin_lock_irq(&data->lock);
-+		clear_bit(BTUSB_SUSPENDING, &data->flags);
-+		spin_unlock_irq(&data->lock);
  	}
  
--	if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) {
--		err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
--		if (err < 0) {
-+	if (hdev->conn_hash.acl_num > 0) {
-+		ret = btusb_submit_bulk_urb(hdev, GFP_NOIO);
-+		if (ret < 0) {
+@@ -987,9 +1121,10 @@ static int btusb_resume(struct usb_interface *intf)
+ 		err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
+ 		if (err < 0) {
  			clear_bit(BTUSB_BULK_RUNNING, &data->flags);
 -			return err;
 -		} else
 -			btusb_submit_bulk_urb(hdev, GFP_NOIO);
-+			return ret;
-+		} else {
-+			ret = btusb_submit_bulk_urb(hdev, GFP_NOIO);
-+			if (ret < 0) {
-+				clear_bit(BTUSB_BULK_RUNNING, &data->flags);
-+				usb_kill_anchored_urbs(&data->bulk_anchor);
-+				return ret;
-+			}
++			goto failed;
 +		}
++
++		btusb_submit_bulk_urb(hdev, GFP_NOIO);
  	}
  
--	if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
--		if (btusb_submit_isoc_urb(hdev, GFP_NOIO) < 0)
--			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
--		else
--			btusb_submit_isoc_urb(hdev, GFP_NOIO);
-+	if (data->isoc) {
-+		if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
-+			ret = btusb_submit_isoc_urb(hdev, GFP_NOIO);
-+			if (ret < 0)
-+				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
-+			else
-+				btusb_submit_isoc_urb(hdev, GFP_NOIO);
-+		}
+ 	if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+@@ -999,16 +1134,35 @@ static int btusb_resume(struct usb_interface *intf)
+ 			btusb_submit_isoc_urb(hdev, GFP_NOIO);
  	}
  
++	spin_lock_irq(&data->txlock);
++	play_deferred(data);
++	clear_bit(BTUSB_SUSPENDING, &data->flags);
++	spin_unlock_irq(&data->txlock);
 +	schedule_work(&data->work);
++
  	return 0;
++
++failed:
++	usb_scuttle_anchored_urbs(&data->deferred);
++done:
++	spin_lock_irq(&data->txlock);
++	clear_bit(BTUSB_SUSPENDING, &data->flags);
++	spin_unlock_irq(&data->txlock);
++
++	return err;
  }
 +#endif
  
@@ -386,8 +432,9 @@ index e70c57e..ac94f91 100644
 +#ifdef CONFIG_PM
  	.suspend	= btusb_suspend,
  	.resume		= btusb_resume,
-+	.supports_autosuspend = 1,
 +#endif
  	.id_table	= btusb_table,
++	.supports_autosuspend = 1,
  };
  
+ static int __init btusb_init(void)




More information about the fedora-extras-commits mailing list