Revert "Bluetooth: hci_bcm: Streamline runtime PM code"
authorHans de Goede <hdegoede@redhat.com>
Wed, 14 Mar 2018 22:06:02 +0000 (23:06 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 15 Mar 2018 18:39:37 +0000 (19:39 +0100)
This reverts commit 43fff7683468 ("Bluetooth: hci_bcm: Streamline runtime
PM code"). The commit msg for this commit states "No functional change
intended.", but replacing:

 pm_runtime_get();
 pm_runtime_mark_last_busy();
 pm_runtime_put_autosuspend();

with:

 pm_request_resume();

Does result in a functional change, pm_request_resume() only calls
pm_runtime_mark_last_busy() if the device was suspended before the call.

This results in the following happening:

1) Device is runtime suspended
2) Device drives host_wake IRQ logically high as it starts receiving data
3) bcm_host_wake() gets called, causes the device to runtime-resume,
   current time gets marked as last_busy time
4) After 5 seconds the autosuspend timer expires and the dev autosuspends
   as no one has been calling pm_runtime_mark_last_busy(), the device was
   resumed during those 5 seconds, so all the pm_request_resume() calls
   while receiving data and/or bcm_host_wake() calls were nops
5) If 4) happens while the device has (just received) data in its buffer to
   be read by the host the IRQ line is *already* / still logically high
   when we autosuspend and since we use an edge triggered IRQ, the IRQ
   will never trigger, causing the device to get stuck in suspend

Therefor this commit has to be reverted, so that we avoid the device
getting stuck in suspend.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/bluetooth/hci_bcm.c

index 6314dfb02969a9191940e8dcf8b0d0fc987453c1..af5658121601062d56c7a4c093b6c317c6c565ec 100644 (file)
@@ -244,7 +244,9 @@ static irqreturn_t bcm_host_wake(int irq, void *data)
 
        bt_dev_dbg(bdev, "Host wake IRQ");
 
-       pm_request_resume(bdev->dev);
+       pm_runtime_get(bdev->dev);
+       pm_runtime_mark_last_busy(bdev->dev);
+       pm_runtime_put_autosuspend(bdev->dev);
 
        return IRQ_HANDLED;
 }
@@ -586,8 +588,11 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
        } 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_request_resume(bcm->dev->dev);
+               if (bcm->dev && bcm_device_exists(bcm->dev)) {
+                       pm_runtime_get(bcm->dev->dev);
+                       pm_runtime_mark_last_busy(bcm->dev->dev);
+                       pm_runtime_put_autosuspend(bcm->dev->dev);
+               }
                mutex_unlock(&bcm_device_lock);
        }