2011/2/24 Martin Pitt <martin.p...@ubuntu.com>:
> Hello Lin,
>
> Keng-Yu Lin [2011-02-24 14:49 +0800]:
>> +btusbget() {
>> +    local dev usb
>> +    usb="/sys/bus/usb/devices"
>> +    for dev in "$usb"/*; do
>> +     [[ -f "${dev}/bDeviceClass" ]] || continue
>> +     [[ "$(cat "${dev}/bDeviceClass")" = "e0" ]] || continue # Wireless
>> +     [[ -f "${dev}/bDeviceProtocol" ]] || continue
>> +     [[ "$(cat "${dev}/bDeviceProtocol")" = "01" ]] || continue # Bluetooth
>> +     case $1 in
>> +         vendor) echo "$(cat "${dev}/idVendor")" ;;
>> +         device) echo "$(cat "${dev}/idProduct")" ;;
>> +     esac
>> +     break
>> +    done
>> +}
>
> This should still be improved, as it will run hundreds of cat
> subprocesses, iterate through the device tree twice, and also stop at
> the first bluetooth adapter instead of testing all of them.
>
> A nice trick for this is to use udevadm trigger. This works on my
> system (with a different adapter which I added to $quirks for
> testing):
>
> ---------------- 8< --------------------
> quirks="0a5c:219c 0a5c:21bc 413c:8187"
>
> for usbid in $quirks; do
>    vendor=${usbid%:*}
>    product=${usbid#*:}
>
>    DEVS=$(udevadm trigger --verbose --dry-run \
>        --attr-match=bDeviceClass=e0 --attr-match=bDeviceProtocol=01 \
>        --attr-match=idVendor=$vendor --attr-match=idProduct=$product)
>    if [ -n "$DEVS" ]; then
>        echo add_parameters --quirk-bluetooth-service-off
>    fi
> done
> ---------------- 8< --------------------
>
> This will consider all bluetooth adapters and only do one external
> program call. Can you please confirm that this still works on your
> system? This should also be forwarded upstream, but Michael and I can
> also take care of that.
>

Hi Martin:
  I removed the echo before add_parameters.  It works well.
  I attached the modified patch in this mail.

  Thanks for taking care of this.

-kengyu
From 021a1c5696ec7bdf6434550bb48cca67c1846d82 Mon Sep 17 00:00:00 2001
From: Keng-Yu Lin <keng-yu....@canonical.com>
Date: Fri, 25 Feb 2011 15:59:43 +0800
Subject: [PATCH] Add the quirk support for stoping/restarting bluetooth service

It is found that the bluetooth modules with USB VID/PIDs [0a5c:219c]
[0a5c:21bc] and [413c:8187] are causing random S4 hangs on various
laptops with SandyBridge chipset.

The hangs can be observed by repeating hibernate/resume in a 250
iterations. The successful cycles number before the hang is
usually ranged in tens, though it varies on different types of
laptops.

This patch added a parameter for the use as

	"pm-hibernate --quirk-bluetooth-service-off"

and a couple of USB ID quirks I found with this S4 problem.

Martin Pitt contributed the code to utilize udevadm for matching
the quirk in sysfs.

Signed-off-by: Keng-Yu Lin <keng-yu....@canonical.com>
---
 pm/sleep.d/44bluetooth-known-quirk |   24 +++++++++++++++++++++
 pm/sleep.d/45bluetooth-service     |   41 ++++++++++++++++++++++++++++++++++++
 pm/sleep.d/Makefile.am             |    2 +
 3 files changed, 67 insertions(+), 0 deletions(-)
 create mode 100755 pm/sleep.d/44bluetooth-known-quirk
 create mode 100755 pm/sleep.d/45bluetooth-service

diff --git a/pm/sleep.d/44bluetooth-known-quirk b/pm/sleep.d/44bluetooth-known-quirk
new file mode 100755
index 0000000..f9df8b8
--- /dev/null
+++ b/pm/sleep.d/44bluetooth-known-quirk
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+. "${PM_FUNCTIONS}"
+
+quirks="0a5c:219c 0a5c:21bc 413c:8187"
+
+case "$1" in
+	hibernate|suspend)
+		# known bluetooth devices needing to stop bluetoothd
+		for usbid in $quirks; do
+			vendor=${usbid%:*}
+			product=${usbid#*:}
+
+			DEVS=$(udevadm trigger --verbose --dry-run \
+				--attr-match=bDeviceClass=e0 --attr-match=bDeviceProtocol=01 \
+				--attr-match=idVendor=$vendor --attr-match=idProduct=$product)
+			if [ -n "$DEVS" ]; then
+				add_parameters --quirk-bluetooth-service-off
+			fi
+		done
+		;;
+	thaw|resume)
+		;;
+esac
diff --git a/pm/sleep.d/45bluetooth-service b/pm/sleep.d/45bluetooth-service
new file mode 100755
index 0000000..969ca86
--- /dev/null
+++ b/pm/sleep.d/45bluetooth-service
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+. "${PM_FUNCTIONS}"
+
+for opt in $PM_CMDLINE; do
+	case "${opt##--quirk-}" in # just quirks, please
+		bluetooth-service-off) 	   QUIRK_BLUETOOTH_SERVICE_OFF="true" ;;
+		bluetooth-none) 	   QUIRK_BLUETOOTH_NONE="true" ;;
+		*) continue ;;
+	esac
+done
+
+quirk() { is_set "$1" && [ -z $QUIRK_BLUETOOTH_NONE ]; }
+
+suspend_bluetooth_service()
+{
+	quirk "${QUIRK_BLUETOOTH_SERVICE_OFF}" &&	stopservice bluetooth
+}
+
+resume_bluetooth_service()
+{
+	quirk "${QUIRK_BLUETOOTH_SERVICE_OFF}" &&	restartservice bluetooth
+}
+
+help() {
+	echo  # first echo makes it look nicer.
+	echo "Bluetooth quirk handler options:"
+	echo
+	echo "  --quirk-bluetooth-service-off"
+	echo "  --quirk-bluetooth-none"
+}
+
+case "$1" in
+	hibernate|suspend)
+		suspend_bluetooth_service
+		;;
+	thaw|resume)
+		resume_bluetooth_service
+		;;
+	help) help ;;
+esac
diff --git a/pm/sleep.d/Makefile.am b/pm/sleep.d/Makefile.am
index 2350825..88df79c 100644
--- a/pm/sleep.d/Makefile.am
+++ b/pm/sleep.d/Makefile.am
@@ -4,6 +4,8 @@ sleep_SCRIPTS =			\
 	00logging		\
 	00powersave		\
 	01grub			\
+	44bluetooth-known-quirk	\
+	45bluetooth-service	\
 	49bluetooth		\
 	55NetworkManager	\
 	75modules		\
-- 
1.7.1

Reply via email to