All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support
@ 2015-09-23 16:18 Frederic Danis
  2015-09-23 16:18 ` [PATCH v5 1/5] Bluetooth: Add BT_WARN and bt_dev_warn logging macros Frederic Danis
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Frederic Danis @ 2015-09-23 16:18 UTC (permalink / raw)
  To: linux-bluetooth

Add wake-up capabilities by retrieveing interruption used by BCM device in ACPI
table.
Add PM runtime support.

v4->v5:
- Add bt_warn to to unify Bluetooth traces in BT_WARN
- Change bcm_suspend_device/bcm_resume_device prototype to be usable directly
  in SET_RUNTIME_PM_OPS. This allows to remove bcm_runtime_suspend/bcm_runtime_resume
  which just call bcm_suspend_device/bcm_resume_device.
- Update commit message and add comment in hci_uart_tty_receive to explain 
  why spin_lock is not requested

v3->v4:
- Add new BT_WARN and bt_dev_warn logging macros
- Use bt_dev_warn for T100 irq polarity fix
- Rename __bcm_suspend to bcm_suspend_device,
    and __bcm_resume to bcm_resume_device
- Remove useless rx_lock spinlock. It is only used in hci_uart_tty_receive() which
    is the receive_buf ldisc callback. This is already protected by flush_to_ldisc()
    in drivers/tty/tty_buffer.c.
    This allows to use mutex in bcm_recv() and call pm_runtime_* directly
- Remove pm_work Work queue which is now useless
- Delay auto-suspend only when reception of a packet is completed

v2->v3:
- Use DMI_EXACT_MATCH instead of DMI_MATCH
- Fix IRQ polarity for T100TA in driver_data of dmi_system_id struct
- Use dmi_first_match() instead of dmi_check_system()

v1->v2:
- Split 1st patch between general wake-up capability and T100TA IRQ fix
- Replace multiple "if ... else if" by switch in bcm_resource()
- Move code to limit number of #ifdef
- Use DMI info to restrict IRQ to T100TA
- Split 2nd patch to prepare PM runtime support in separated patch
- Tested with and without CONFIG_PM_SLEEP and CONFIG_PM.

Frederic Danis (5):
  Bluetooth: Add BT_WARN and bt_dev_warn logging macros
  Bluetooth: hci_bcm: Fix IRQ polarity for T100
  Bluetooth: hci_bcm: Prepare PM runtime support
  Bluetooth: Remove useless rx_lock spinlock
  Bluetooth: hci_bcm: Add suspend/resume runtime PM functions

 drivers/bluetooth/hci_bcm.c       | 171 +++++++++++++++++++++++++++++++-------
 drivers/bluetooth/hci_ldisc.c     |   8 +-
 drivers/bluetooth/hci_uart.h      |   1 -
 include/net/bluetooth/bluetooth.h |   5 ++
 net/bluetooth/lib.c               |  16 ++++
 5 files changed, 164 insertions(+), 37 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v5 1/5] Bluetooth: Add BT_WARN and bt_dev_warn logging macros
  2015-09-23 16:18 [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Frederic Danis
@ 2015-09-23 16:18 ` Frederic Danis
  2015-09-23 16:18 ` [PATCH v5 2/5] Bluetooth: hci_bcm: Fix IRQ polarity for T100 Frederic Danis
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Frederic Danis @ 2015-09-23 16:18 UTC (permalink / raw)
  To: linux-bluetooth

Add warning logging macros to bluetooth subsystem logs.

Signed-off-by: Frederic Danis <frederic.danis@linux.intel.com>
---
 include/net/bluetooth/bluetooth.h |  5 +++++
 net/bluetooth/lib.c               | 16 ++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index f5ade85..c4defef 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -122,11 +122,14 @@ struct bt_voice {
 __printf(1, 2)
 void bt_info(const char *fmt, ...);
 __printf(1, 2)
+void bt_warn(const char *fmt, ...);
+__printf(1, 2)
 void bt_err(const char *fmt, ...);
 __printf(1, 2)
 void bt_err_ratelimited(const char *fmt, ...);
 
 #define BT_INFO(fmt, ...)	bt_info(fmt "\n", ##__VA_ARGS__)
+#define BT_WARN(fmt, ...)	bt_warn(fmt "\n", ##__VA_ARGS__)
 #define BT_ERR(fmt, ...)	bt_err(fmt "\n", ##__VA_ARGS__)
 #define BT_DBG(fmt, ...)	pr_debug(fmt "\n", ##__VA_ARGS__)
 
@@ -134,6 +137,8 @@ void bt_err_ratelimited(const char *fmt, ...);
 
 #define bt_dev_info(hdev, fmt, ...)				\
 	BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
+#define bt_dev_warn(hdev, fmt, ...)				\
+	BT_WARN("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
 #define bt_dev_err(hdev, fmt, ...)				\
 	BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
 #define bt_dev_dbg(hdev, fmt, ...)				\
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c
index 8b4cdce..aa4cf64 100644
--- a/net/bluetooth/lib.c
+++ b/net/bluetooth/lib.c
@@ -151,6 +151,22 @@ void bt_info(const char *format, ...)
 }
 EXPORT_SYMBOL(bt_info);
 
+void bt_warn(const char *format, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, format);
+
+	vaf.fmt = format;
+	vaf.va = &args;
+
+	pr_warn("%pV", &vaf);
+
+	va_end(args);
+}
+EXPORT_SYMBOL(bt_warn);
+
 void bt_err(const char *format, ...)
 {
 	struct va_format vaf;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v5 2/5] Bluetooth: hci_bcm: Fix IRQ polarity for T100
  2015-09-23 16:18 [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Frederic Danis
  2015-09-23 16:18 ` [PATCH v5 1/5] Bluetooth: Add BT_WARN and bt_dev_warn logging macros Frederic Danis
@ 2015-09-23 16:18 ` Frederic Danis
  2015-09-23 16:18 ` [PATCH v5 3/5] Bluetooth: hci_bcm: Prepare PM runtime support Frederic Danis
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Frederic Danis @ 2015-09-23 16:18 UTC (permalink / raw)
  To: linux-bluetooth

ACPI table for BCM2E39 of T100TA is not correct.
Set correct irq_polarity for this device.

Signed-off-by: Frederic Danis <frederic.danis@linux.intel.com>
---
 drivers/bluetooth/hci_bcm.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index f306541..2cb5089 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -32,6 +32,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/tty.h>
 #include <linux/interrupt.h>
+#include <linux/dmi.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -513,6 +514,22 @@ static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = {
 };
 
 #ifdef CONFIG_ACPI
+static u8 acpi_active_low = ACPI_ACTIVE_LOW;
+
+/* IRQ polarity of some chipsets are not defined correctly in ACPI table. */
+static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
+	{
+		.ident = "Asus T100TA",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR,
+					"ASUSTeK COMPUTER INC."),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+		},
+		.driver_data = &acpi_active_low,
+	},
+	{ }
+};
+
 static int bcm_resource(struct acpi_resource *ares, void *data)
 {
 	struct bcm_device *dev = data;
@@ -552,6 +569,7 @@ static int bcm_acpi_probe(struct bcm_device *dev)
 	const struct acpi_device_id *id;
 	struct acpi_device *adev;
 	LIST_HEAD(resources);
+	const struct dmi_system_id *dmi_id;
 	int ret;
 
 	id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
@@ -608,6 +626,13 @@ static int bcm_acpi_probe(struct bcm_device *dev)
 
 	acpi_dev_get_resources(adev, &resources, bcm_resource, dev);
 
+	dmi_id = dmi_first_match(bcm_wrong_irq_dmi_table);
+	if (dmi_id) {
+		bt_dev_warn(dev, "%s: Overwriting IRQ polarity to active low",
+			    dmi_id->ident);
+		dev->irq_polarity = *(u8 *)dmi_id->driver_data;
+	}
+
 	return 0;
 }
 #else
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v5 3/5] Bluetooth: hci_bcm: Prepare PM runtime support
  2015-09-23 16:18 [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Frederic Danis
  2015-09-23 16:18 ` [PATCH v5 1/5] Bluetooth: Add BT_WARN and bt_dev_warn logging macros Frederic Danis
  2015-09-23 16:18 ` [PATCH v5 2/5] Bluetooth: hci_bcm: Fix IRQ polarity for T100 Frederic Danis
@ 2015-09-23 16:18 ` Frederic Danis
  2015-09-23 16:18 ` [PATCH v5 4/5] Bluetooth: Remove useless rx_lock spinlock Frederic Danis
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Frederic Danis @ 2015-09-23 16:18 UTC (permalink / raw)
  To: linux-bluetooth

Change some CONFIG_PM_SLEEP to CONFIG_PM as hu and is_suspended parameters
will be used during PM runtime callbacks.

Add bcm_suspend_device() and bcm_resume_device() which performs link
management for PM callbacks.
These functions will be used for runtime management.

Signed-off-by: Frederic Danis <frederic.danis@linux.intel.com>
---
 drivers/bluetooth/hci_bcm.c | 88 ++++++++++++++++++++++++++++++---------------
 1 file changed, 60 insertions(+), 28 deletions(-)

diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 2cb5089..fc5ca95 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -56,7 +56,7 @@ struct bcm_device {
 	int			irq;
 	u8			irq_polarity;
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 	struct hci_uart		*hu;
 	bool			is_suspended; /* suspend/resume flag */
 #endif
@@ -153,7 +153,7 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static irqreturn_t bcm_host_wake(int irq, void *data)
 {
 	struct bcm_device *bdev = data;
@@ -259,7 +259,7 @@ static int bcm_open(struct hci_uart *hu)
 		if (hu->tty->dev->parent == dev->pdev->dev.parent) {
 			bcm->dev = dev;
 			hu->init_speed = dev->init_speed;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 			dev->hu = hu;
 #endif
 			bcm_gpio_set_power(bcm->dev, true);
@@ -283,7 +283,7 @@ static int bcm_close(struct hci_uart *hu)
 	mutex_lock(&bcm_device_lock);
 	if (bcm_device_exists(bdev)) {
 		bcm_gpio_set_power(bdev, false);
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 		if (device_can_wakeup(&bdev->pdev->dev)) {
 			devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev);
 			device_init_wakeup(&bdev->pdev->dev, false);
@@ -425,24 +425,17 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
 	return skb_dequeue(&bcm->txq);
 }
 
-#ifdef CONFIG_PM_SLEEP
-/* Platform suspend callback */
-static int bcm_suspend(struct device *dev)
+#ifdef CONFIG_PM
+static int bcm_suspend_device(struct device *dev)
 {
 	struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
-	int error;
 
-	bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
-
-	mutex_lock(&bcm_device_lock);
-
-	if (!bdev->hu)
-		goto unlock;
+	bt_dev_dbg(bdev, "");
 
-	if (!bdev->is_suspended) {
+	if (!bdev->is_suspended && bdev->hu) {
 		hci_uart_set_flow_control(bdev->hu, true);
 
-		/* Once this callback returns, driver suspends BT via GPIO */
+		/* Once this returns, driver suspends BT via GPIO */
 		bdev->is_suspended = true;
 	}
 
@@ -453,6 +446,52 @@ static int bcm_suspend(struct device *dev)
 		mdelay(15);
 	}
 
+	return 0;
+}
+
+static int bcm_resume_device(struct device *dev)
+{
+	struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
+
+	bt_dev_dbg(bdev, "");
+
+	if (bdev->device_wakeup) {
+		gpiod_set_value(bdev->device_wakeup, true);
+		bt_dev_dbg(bdev, "resume, delaying 15 ms");
+		mdelay(15);
+	}
+
+	/* When this executes, the device has woken up already */
+	if (bdev->is_suspended && bdev->hu) {
+		bdev->is_suspended = false;
+
+		hci_uart_set_flow_control(bdev->hu, false);
+	}
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+/* Platform suspend callback */
+static int bcm_suspend(struct device *dev)
+{
+	struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
+	int error;
+
+	bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
+
+	/* bcm_suspend can be called at any time as long as platform device is
+	 * bound, so it should use bcm_device_lock to protect access to hci_uart
+	 * and device_wake-up GPIO.
+	 */
+	mutex_lock(&bcm_device_lock);
+
+	if (!bdev->hu)
+		goto unlock;
+
+	bcm_suspend_device(dev);
+
 	if (device_may_wakeup(&bdev->pdev->dev)) {
 		error = enable_irq_wake(bdev->irq);
 		if (!error)
@@ -472,6 +511,10 @@ static int bcm_resume(struct device *dev)
 
 	bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
 
+	/* bcm_resume can be called at any time as long as platform device is
+	 * bound, so it should use bcm_device_lock to protect access to hci_uart
+	 * and device_wake-up GPIO.
+	 */
 	mutex_lock(&bcm_device_lock);
 
 	if (!bdev->hu)
@@ -482,18 +525,7 @@ static int bcm_resume(struct device *dev)
 		bt_dev_dbg(bdev, "BCM irq: disabled");
 	}
 
-	if (bdev->device_wakeup) {
-		gpiod_set_value(bdev->device_wakeup, true);
-		bt_dev_dbg(bdev, "resume, delaying 15 ms");
-		mdelay(15);
-	}
-
-	/* When this callback executes, the device has woken up already */
-	if (bdev->is_suspended) {
-		bdev->is_suspended = false;
-
-		hci_uart_set_flow_control(bdev->hu, false);
-	}
+	bcm_resume_device(dev);
 
 unlock:
 	mutex_unlock(&bcm_device_lock);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v5 4/5] Bluetooth: Remove useless rx_lock spinlock
  2015-09-23 16:18 [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Frederic Danis
                   ` (2 preceding siblings ...)
  2015-09-23 16:18 ` [PATCH v5 3/5] Bluetooth: hci_bcm: Prepare PM runtime support Frederic Danis
@ 2015-09-23 16:18 ` Frederic Danis
  2015-09-23 16:18 ` [PATCH v5 5/5] Bluetooth: hci_bcm: Add suspend/resume runtime PM functions Frederic Danis
  2015-09-24 14:35 ` [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Marcel Holtmann
  5 siblings, 0 replies; 7+ messages in thread
From: Frederic Danis @ 2015-09-23 16:18 UTC (permalink / raw)
  To: linux-bluetooth

rx_lock spinlock is only used in hci_uart_tty_receive() which is the
receive_buf ldisc callback.

hci_uart_tty_receive() is protected from re-entrance by its only
caller (flush_to_ldisc() in drivers/tty/tty_buffer.c) which held a
mutex (buf->lock) for this section.
This lock allows "safe use of the line discipline's receive_buf()
method by excluding the buffer work and any pending flush from using
the flip buffer." (comments from tty_buffer_lock_exclusive() in
drivers/tty/tty_buffer.c)

So, no need to double protect this resource with rx_lock.

Signed-off-by: Frederic Danis <frederic.danis@linux.intel.com>
---
 drivers/bluetooth/hci_ldisc.c | 8 +++-----
 drivers/bluetooth/hci_uart.h  | 1 -
 2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 0d5a05a..ad66c69 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -470,8 +470,6 @@ static int hci_uart_tty_open(struct tty_struct *tty)
 	INIT_WORK(&hu->init_ready, hci_uart_init_work);
 	INIT_WORK(&hu->write_work, hci_uart_write_work);
 
-	spin_lock_init(&hu->rx_lock);
-
 	/* Flush any pending characters in the driver and line discipline. */
 
 	/* FIXME: why is this needed. Note don't use ldisc_ref here as the
@@ -569,14 +567,14 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
 	if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
 		return;
 
-	spin_lock(&hu->rx_lock);
+	/* It does not need a lock here as it is already protected by a mutex in
+	 * tty caller
+	 */
 	hu->proto->recv(hu, data, count);
 
 	if (hu->hdev)
 		hu->hdev->stat.byte_rx += count;
 
-	spin_unlock(&hu->rx_lock);
-
 	tty_unthrottle(tty);
 }
 
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 495b9ef..2f7bb35 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -85,7 +85,6 @@ struct hci_uart {
 
 	struct sk_buff		*tx_skb;
 	unsigned long		tx_state;
-	spinlock_t		rx_lock;
 
 	unsigned int init_speed;
 	unsigned int oper_speed;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v5 5/5] Bluetooth: hci_bcm: Add suspend/resume runtime PM functions
  2015-09-23 16:18 [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Frederic Danis
                   ` (3 preceding siblings ...)
  2015-09-23 16:18 ` [PATCH v5 4/5] Bluetooth: Remove useless rx_lock spinlock Frederic Danis
@ 2015-09-23 16:18 ` Frederic Danis
  2015-09-24 14:35 ` [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Marcel Holtmann
  5 siblings, 0 replies; 7+ messages in thread
From: Frederic Danis @ 2015-09-23 16:18 UTC (permalink / raw)
  To: linux-bluetooth

Adds autosuspend runtime functionality to BCM UART driver.
Autosuspend is enabled at end of bcm_setup.

bcm_device_lock is used for system sleep functions as they can be
called at any time.
bcm_device_lock is not held for runtime suspend functions as this
is only enabled as long as platform device is opened.

Signed-off-by: Frederic Danis <frederic.danis@linux.intel.com>
---
 drivers/bluetooth/hci_bcm.c | 60 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 56 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index fc5ca95..0c791ac 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -33,6 +33,7 @@
 #include <linux/tty.h>
 #include <linux/interrupt.h>
 #include <linux/dmi.h>
+#include <linux/pm_runtime.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -40,6 +41,8 @@
 #include "btbcm.h"
 #include "hci_uart.h"
 
+#define BCM_AUTOSUSPEND_DELAY	5000 /* default autosleep delay */
+
 struct bcm_device {
 	struct list_head	list;
 
@@ -160,6 +163,10 @@ static irqreturn_t bcm_host_wake(int irq, void *data)
 
 	bt_dev_dbg(bdev, "Host wake IRQ");
 
+	pm_runtime_get(&bdev->pdev->dev);
+	pm_runtime_mark_last_busy(&bdev->pdev->dev);
+	pm_runtime_put_autosuspend(&bdev->pdev->dev);
+
 	return IRQ_HANDLED;
 }
 
@@ -183,6 +190,12 @@ static int bcm_request_irq(struct bcm_data *bcm)
 			goto unlock;
 
 		device_init_wakeup(&bdev->pdev->dev, true);
+
+		pm_runtime_set_autosuspend_delay(&bdev->pdev->dev,
+						 BCM_AUTOSUSPEND_DELAY);
+		pm_runtime_use_autosuspend(&bdev->pdev->dev);
+		pm_runtime_set_active(&bdev->pdev->dev);
+		pm_runtime_enable(&bdev->pdev->dev);
 	}
 
 unlock:
@@ -198,7 +211,7 @@ static const struct bcm_set_sleep_mode default_sleep_params = {
 	.bt_wake_active = 1,	/* BT_WAKE active mode: 1 = high, 0 = low */
 	.host_wake_active = 0,	/* HOST_WAKE active mode: 1 = high, 0 = low */
 	.allow_host_sleep = 1,	/* Allow host sleep in SCO flag */
-	.combine_modes = 0,	/* Combine sleep and LPM flag */
+	.combine_modes = 1,	/* Combine sleep and LPM flag */
 	.tristate_control = 0,	/* Allow tri-state control of UART tx flag */
 	/* Irrelevant USB flags */
 	.usb_auto_sleep = 0,
@@ -284,6 +297,9 @@ static int bcm_close(struct hci_uart *hu)
 	if (bcm_device_exists(bdev)) {
 		bcm_gpio_set_power(bdev, false);
 #ifdef CONFIG_PM
+		pm_runtime_disable(&bdev->pdev->dev);
+		pm_runtime_set_suspended(&bdev->pdev->dev);
+
 		if (device_can_wakeup(&bdev->pdev->dev)) {
 			devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev);
 			device_init_wakeup(&bdev->pdev->dev, false);
@@ -400,6 +416,15 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
 		bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
 		bcm->rx_skb = NULL;
 		return err;
+	} else if (!bcm->rx_skb) {
+		/* Delay auto-suspend when receiving completed packet */
+		mutex_lock(&bcm_device_lock);
+		if (bcm->dev && bcm_device_exists(bcm->dev)) {
+			pm_runtime_get(&bcm->dev->pdev->dev);
+			pm_runtime_mark_last_busy(&bcm->dev->pdev->dev);
+			pm_runtime_put_autosuspend(&bcm->dev->pdev->dev);
+		}
+		mutex_unlock(&bcm_device_lock);
 	}
 
 	return count;
@@ -421,8 +446,27 @@ static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
 static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
 {
 	struct bcm_data *bcm = hu->priv;
+	struct sk_buff *skb = NULL;
+	struct bcm_device *bdev = NULL;
+
+	mutex_lock(&bcm_device_lock);
+
+	if (bcm_device_exists(bcm->dev)) {
+		bdev = bcm->dev;
+		pm_runtime_get_sync(&bdev->pdev->dev);
+		/* Shall be resumed here */
+	}
+
+	skb = skb_dequeue(&bcm->txq);
+
+	if (bdev) {
+		pm_runtime_mark_last_busy(&bdev->pdev->dev);
+		pm_runtime_put_autosuspend(&bdev->pdev->dev);
+	}
 
-	return skb_dequeue(&bcm->txq);
+	mutex_unlock(&bcm_device_lock);
+
+	return skb;
 }
 
 #ifdef CONFIG_PM
@@ -490,7 +534,8 @@ static int bcm_suspend(struct device *dev)
 	if (!bdev->hu)
 		goto unlock;
 
-	bcm_suspend_device(dev);
+	if (pm_runtime_active(dev))
+		bcm_suspend_device(dev);
 
 	if (device_may_wakeup(&bdev->pdev->dev)) {
 		error = enable_irq_wake(bdev->irq);
@@ -530,6 +575,10 @@ static int bcm_resume(struct device *dev)
 unlock:
 	mutex_unlock(&bcm_device_lock);
 
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
 	return 0;
 }
 #endif
@@ -750,7 +799,10 @@ MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
 #endif
 
 /* Platform suspend and resume callbacks */
-static SIMPLE_DEV_PM_OPS(bcm_pm_ops, bcm_suspend, bcm_resume);
+static const struct dev_pm_ops bcm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(bcm_suspend, bcm_resume)
+	SET_RUNTIME_PM_OPS(bcm_suspend_device, bcm_resume_device, NULL)
+};
 
 static struct platform_driver bcm_driver = {
 	.probe = bcm_probe,
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support
  2015-09-23 16:18 [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Frederic Danis
                   ` (4 preceding siblings ...)
  2015-09-23 16:18 ` [PATCH v5 5/5] Bluetooth: hci_bcm: Add suspend/resume runtime PM functions Frederic Danis
@ 2015-09-24 14:35 ` Marcel Holtmann
  5 siblings, 0 replies; 7+ messages in thread
From: Marcel Holtmann @ 2015-09-24 14:35 UTC (permalink / raw)
  To: Frederic Danis; +Cc: linux-bluetooth

Hi Fred,

> Add wake-up capabilities by retrieveing interruption used by BCM device in ACPI
> table.
> Add PM runtime support.
> 
> v4->v5:
> - Add bt_warn to to unify Bluetooth traces in BT_WARN
> - Change bcm_suspend_device/bcm_resume_device prototype to be usable directly
>  in SET_RUNTIME_PM_OPS. This allows to remove bcm_runtime_suspend/bcm_runtime_resume
>  which just call bcm_suspend_device/bcm_resume_device.
> - Update commit message and add comment in hci_uart_tty_receive to explain 
>  why spin_lock is not requested
> 
> v3->v4:
> - Add new BT_WARN and bt_dev_warn logging macros
> - Use bt_dev_warn for T100 irq polarity fix
> - Rename __bcm_suspend to bcm_suspend_device,
>    and __bcm_resume to bcm_resume_device
> - Remove useless rx_lock spinlock. It is only used in hci_uart_tty_receive() which
>    is the receive_buf ldisc callback. This is already protected by flush_to_ldisc()
>    in drivers/tty/tty_buffer.c.
>    This allows to use mutex in bcm_recv() and call pm_runtime_* directly
> - Remove pm_work Work queue which is now useless
> - Delay auto-suspend only when reception of a packet is completed
> 
> v2->v3:
> - Use DMI_EXACT_MATCH instead of DMI_MATCH
> - Fix IRQ polarity for T100TA in driver_data of dmi_system_id struct
> - Use dmi_first_match() instead of dmi_check_system()
> 
> v1->v2:
> - Split 1st patch between general wake-up capability and T100TA IRQ fix
> - Replace multiple "if ... else if" by switch in bcm_resource()
> - Move code to limit number of #ifdef
> - Use DMI info to restrict IRQ to T100TA
> - Split 2nd patch to prepare PM runtime support in separated patch
> - Tested with and without CONFIG_PM_SLEEP and CONFIG_PM.
> 
> Frederic Danis (5):
>  Bluetooth: Add BT_WARN and bt_dev_warn logging macros
>  Bluetooth: hci_bcm: Fix IRQ polarity for T100
>  Bluetooth: hci_bcm: Prepare PM runtime support
>  Bluetooth: Remove useless rx_lock spinlock
>  Bluetooth: hci_bcm: Add suspend/resume runtime PM functions
> 
> drivers/bluetooth/hci_bcm.c       | 171 +++++++++++++++++++++++++++++++-------
> drivers/bluetooth/hci_ldisc.c     |   8 +-
> drivers/bluetooth/hci_uart.h      |   1 -
> include/net/bluetooth/bluetooth.h |   5 ++
> net/bluetooth/lib.c               |  16 ++++
> 5 files changed, 164 insertions(+), 37 deletions(-)

all 5 patches have been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-09-24 14:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-23 16:18 [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Frederic Danis
2015-09-23 16:18 ` [PATCH v5 1/5] Bluetooth: Add BT_WARN and bt_dev_warn logging macros Frederic Danis
2015-09-23 16:18 ` [PATCH v5 2/5] Bluetooth: hci_bcm: Fix IRQ polarity for T100 Frederic Danis
2015-09-23 16:18 ` [PATCH v5 3/5] Bluetooth: hci_bcm: Prepare PM runtime support Frederic Danis
2015-09-23 16:18 ` [PATCH v5 4/5] Bluetooth: Remove useless rx_lock spinlock Frederic Danis
2015-09-23 16:18 ` [PATCH v5 5/5] Bluetooth: hci_bcm: Add suspend/resume runtime PM functions Frederic Danis
2015-09-24 14:35 ` [PATCH v5 0/5] Bluetooth: hci_bcm: Add wake-up and PM runtime support Marcel Holtmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.