Matthew Garrett 2b89a04
commit 6aa42966dea9a1fc02a714211ea489c3278bf8d4
Matthew Garrett 2b89a04
Author: Matthew Garrett <mjg@redhat.com>
Matthew Garrett 2b89a04
Date:   Thu Sep 16 13:34:55 2010 -0400
Matthew Garrett 2b89a04
Matthew Garrett 2b89a04
    bluetooth: Take a runtime pm reference on hid connections
Matthew Garrett 2b89a04
    
Matthew Garrett 2b89a04
    Bluetooth runtime PM interacts badly with input devices - the connection
Matthew Garrett 2b89a04
    will be dropped if the device becomes idle, resulting in noticable lag when
Matthew Garrett 2b89a04
    the user interacts with the input device again. Bump the pm runtime count
Matthew Garrett 2b89a04
    when the device is associated and release it when it's disassociated in
Matthew Garrett 2b89a04
    order to avoid this.
Matthew Garrett 2b89a04
    
Matthew Garrett 2b89a04
    Signed-off-by: Matthew Garrett <mjg@redhat.com>
Matthew Garrett 2b89a04
Matthew Garrett 2b89a04
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
Matthew Garrett 2b89a04
index bfe641b..a4489a7 100644
Matthew Garrett 2b89a04
--- a/net/bluetooth/hidp/core.c
Matthew Garrett 2b89a04
+++ b/net/bluetooth/hidp/core.c
Matthew Garrett 2b89a04
@@ -36,6 +36,7 @@
Matthew Garrett 2b89a04
 #include <linux/file.h>
Matthew Garrett 2b89a04
 #include <linux/init.h>
Matthew Garrett 2b89a04
 #include <linux/wait.h>
Matthew Garrett 2b89a04
+#include <linux/pm_runtime.h>
Matthew Garrett 2b89a04
 #include <net/sock.h>
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 #include <linux/input.h>
Matthew Garrett 2b89a04
@@ -622,6 +623,14 @@ static int hidp_session(void *arg)
Matthew Garrett 2b89a04
 	return 0;
Matthew Garrett 2b89a04
 }
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
+static struct hci_dev *hidp_get_hci(struct hidp_session *session)
Matthew Garrett 2b89a04
+{
Matthew Garrett 2b89a04
+	bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
Matthew Garrett 2b89a04
+	bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Matthew Garrett 2b89a04
+
Matthew Garrett 2b89a04
+	return hci_get_route(dst, src);
Matthew Garrett 2b89a04
+}
Matthew Garrett 2b89a04
+
Matthew Garrett 2b89a04
 static struct device *hidp_get_device(struct hidp_session *session)
Matthew Garrett 2b89a04
 {
Matthew Garrett 2b89a04
 	bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
Matthew Garrett 2b89a04
@@ -819,6 +828,7 @@ fault:
Matthew Garrett 2b89a04
 int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
Matthew Garrett 2b89a04
 {
Matthew Garrett 2b89a04
 	struct hidp_session *session, *s;
Matthew Garrett 2b89a04
+	struct hci_dev *hdev;
Matthew Garrett 2b89a04
 	int err;
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 	BT_DBG("");
Matthew Garrett 2b89a04
@@ -889,6 +899,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
Matthew Garrett 2b89a04
 		hidp_input_event(session->input, EV_LED, 0, 0);
Matthew Garrett 2b89a04
 	}
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
+	hdev = hidp_get_hci(session);
Matthew Garrett 2b89a04
+	pm_runtime_get(hdev->parent);
Matthew Garrett 2b89a04
+	hci_dev_put(hdev);
Matthew Garrett 2b89a04
+
Matthew Garrett 2b89a04
 	up_write(&hidp_session_sem);
Matthew Garrett 2b89a04
 	return 0;
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
@@ -925,6 +939,7 @@ failed:
Matthew Garrett 2b89a04
 int hidp_del_connection(struct hidp_conndel_req *req)
Matthew Garrett 2b89a04
 {
Matthew Garrett 2b89a04
 	struct hidp_session *session;
Matthew Garrett 2b89a04
+	struct hci_dev *hdev;
Matthew Garrett 2b89a04
 	int err = 0;
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 	BT_DBG("");
Matthew Garrett 2b89a04
@@ -952,6 +967,9 @@ int hidp_del_connection(struct hidp_conndel_req *req)
Matthew Garrett 2b89a04
 	} else
Matthew Garrett 2b89a04
 		err = -ENOENT;
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
+	hdev = hidp_get_hci(session);
Matthew Garrett 2b89a04
+	pm_runtime_put(hdev->parent);
Matthew Garrett 2b89a04
+	hci_dev_put(hdev);
Matthew Garrett 2b89a04
 	up_read(&hidp_session_sem);
Matthew Garrett 2b89a04
 	return err;
Matthew Garrett 2b89a04
 }
Matthew Garrett 2b89a04
Matthew Garrett 2b89a04
commit 482eca592615e85b048753750b101d051b77fde9
Matthew Garrett 2b89a04
Author: Matthew Garrett <mjg@redhat.com>
Matthew Garrett 2b89a04
Date:   Thu Sep 16 13:49:24 2010 -0400
Matthew Garrett 2b89a04
Matthew Garrett 2b89a04
    bluetooth: Remove some unnecessary error messages
Matthew Garrett 2b89a04
    
Matthew Garrett 2b89a04
    The main reason for these urbs to error out on submission is that runtime
Matthew Garrett 2b89a04
    pm has kicked in, which is unnecessary noise. Let's just drop them.
Matthew Garrett 2b89a04
    
Matthew Garrett 2b89a04
    Signed-off-by: Matthew Garrett <mjg@redhat.com>
Matthew Garrett 2b89a04
Matthew Garrett 2b89a04
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
Matthew Garrett 2b89a04
index d22ce3c..3ace025 100644
Matthew Garrett 2b89a04
--- a/drivers/bluetooth/btusb.c
Matthew Garrett 2b89a04
+++ b/drivers/bluetooth/btusb.c
Matthew Garrett 2b89a04
@@ -229,11 +229,8 @@ static void btusb_intr_complete(struct urb *urb)
Matthew Garrett 2b89a04
 	usb_anchor_urb(urb, &data->intr_anchor);
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 	err = usb_submit_urb(urb, GFP_ATOMIC);
Matthew Garrett 2b89a04
-	if (err < 0) {
Matthew Garrett 2b89a04
-		BT_ERR("%s urb %p failed to resubmit (%d)",
Matthew Garrett 2b89a04
-						hdev->name, urb, -err);
Matthew Garrett 2b89a04
+	if (err < 0)
Matthew Garrett 2b89a04
 		usb_unanchor_urb(urb);
Matthew Garrett 2b89a04
-	}
Matthew Garrett 2b89a04
 }
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
Matthew Garrett 2b89a04
@@ -313,11 +310,8 @@ static void btusb_bulk_complete(struct urb *urb)
Matthew Garrett 2b89a04
 	usb_mark_last_busy(data->udev);
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 	err = usb_submit_urb(urb, GFP_ATOMIC);
Matthew Garrett 2b89a04
-	if (err < 0) {
Matthew Garrett 2b89a04
-		BT_ERR("%s urb %p failed to resubmit (%d)",
Matthew Garrett 2b89a04
-						hdev->name, urb, -err);
Matthew Garrett 2b89a04
+	if (err < 0)
Matthew Garrett 2b89a04
 		usb_unanchor_urb(urb);
Matthew Garrett 2b89a04
-	}
Matthew Garrett 2b89a04
 }
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
Matthew Garrett 2b89a04
@@ -402,11 +396,8 @@ static void btusb_isoc_complete(struct urb *urb)
Matthew Garrett 2b89a04
 	usb_anchor_urb(urb, &data->isoc_anchor);
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 	err = usb_submit_urb(urb, GFP_ATOMIC);
Matthew Garrett 2b89a04
-	if (err < 0) {
Matthew Garrett 2b89a04
-		BT_ERR("%s urb %p failed to resubmit (%d)",
Matthew Garrett 2b89a04
-						hdev->name, urb, -err);
Matthew Garrett 2b89a04
+	if (err < 0)
Matthew Garrett 2b89a04
 		usb_unanchor_urb(urb);
Matthew Garrett 2b89a04
-	}
Matthew Garrett 2b89a04
 }
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
Matthew Garrett 2b89a04
Matthew Garrett 2b89a04
commit fd763c5b14ed99ac2401f8e8f1a07c3687ae01cc
Matthew Garrett 2b89a04
Author: Matthew Garrett <mjg@redhat.com>
Matthew Garrett 2b89a04
Date:   Thu Sep 16 13:37:38 2010 -0400
Matthew Garrett 2b89a04
Matthew Garrett 2b89a04
    bluetooth: Enable USB autosuspend by default on btusb
Matthew Garrett 2b89a04
    
Matthew Garrett 2b89a04
    We've done this for a while in Fedora without any obvious problems other
Matthew Garrett 2b89a04
    than some interaction with input devices. Those should be fixed now, so
Matthew Garrett 2b89a04
    let's try this in mainline.
Matthew Garrett 2b89a04
    
Matthew Garrett 2b89a04
    Signed-off-by: Matthew Garrett <mjg@redhat.com>
Matthew Garrett 2b89a04
Matthew Garrett 2b89a04
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
Matthew Garrett 2b89a04
index 3ace025..03b64e4 100644
Matthew Garrett 2b89a04
--- a/drivers/bluetooth/btusb.c
Matthew Garrett 2b89a04
+++ b/drivers/bluetooth/btusb.c
Matthew Garrett 2b89a04
@@ -1014,6 +1014,8 @@ static int btusb_probe(struct usb_interface *intf,
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
 	usb_set_intfdata(intf, data);
Matthew Garrett 2b89a04
 
Matthew Garrett 2b89a04
+	usb_enable_autosuspend(interface_to_usbdev(intf));
Matthew Garrett 2b89a04
+
Matthew Garrett 2b89a04
 	return 0;
Matthew Garrett 2b89a04
 }
Matthew Garrett 2b89a04