Message ID | 91dfa736b7629cdb94bd2029f05717eeae77b07d.1640334021.git.sean.wang@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v4,1/3] Bluetooth: mt7921s: Support wake on bluetooth | expand |
Hi Mark, > Enable wake on bluetooth on mt7921s that can be supported since the > firmware with version 20211129211059 was added, and the patch would > not cause any harm even when the old firmware is applied. > > The patch was tested by setting up an HID or HOGP profile to connect a > Bluetooth keyboard and mouse, then putting the system to suspend, then > trying to wake up the system by moving the Bluetooth keyboard or mouse, > and then checking if the system can wake up and be brought back to > the normal state. > > Co-developed-by: Sean Wang <sean.wang@mediatek.com> > Signed-off-by: Sean Wang <sean.wang@mediatek.com> > Signed-off-by: Mark Chen <mark-yw.chen@mediatek.com> > --- > v2: refine the git message > v3: > 1. fit to single line as possible > 2. move the skb variable into local scope > 3. free skb after calling __hci_cmd_sync > 4. make bt_awake as const struct btmtk_wakeon > v4: 1. drop __func__ in error messages > 2. make hdev->wakeup assignment aligned to hdev->send > --- > drivers/bluetooth/btmtk.h | 8 ++++++++ > drivers/bluetooth/btmtksdio.c | 33 ++++++++++++++++++++++++++++++++- > 2 files changed, 40 insertions(+), 1 deletion(-) > > diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h > index 6e7b0c7567c0..2be1d2680ad8 100644 > --- a/drivers/bluetooth/btmtk.h > +++ b/drivers/bluetooth/btmtk.h > @@ -68,6 +68,14 @@ struct btmtk_tci_sleep { > u8 time_compensation; > } __packed; > > +struct btmtk_wakeon { > + u8 mode; > + u8 gpo; > + u8 active_high; > + __le16 enable_delay; > + __le16 wakeup_delay; > +} __packed; > + > struct btmtk_hci_wmt_params { > u8 op; > u8 flag; > diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c > index b5ea8d3bffaa..89bd70651e9e 100644 > --- a/drivers/bluetooth/btmtksdio.c > +++ b/drivers/bluetooth/btmtksdio.c > @@ -958,6 +958,32 @@ static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) > return 0; > } > > +static bool btmtk_sdio_wakeup(struct hci_dev *hdev) > +{ > + struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); > + bool may_wakeup = device_may_wakeup(bdev->dev); > + const struct btmtk_wakeon bt_awake = { > + .mode = 0x1, > + .gpo = 0, > + .active_high = 0x1, > + .enable_delay = cpu_to_le16(0xc80), > + .wakeup_delay = cpu_to_le16(0x20) so we normally add the , at the end here as well. That means extending the sturct requires one less line to change. > + }; > + > + if (may_wakeup && bdev->data->chipid == 0x7921) { > + struct sk_buff *skb; > + > + skb = __hci_cmd_sync(hdev, 0xfc27, sizeof(bt_awake), > + &bt_awake, HCI_CMD_TIMEOUT); > + if (IS_ERR(skb)) > + may_wakeup = false; > + > + kfree_skb(skb); > + } > + > + return may_wakeup; > +} > + > static int btmtksdio_probe(struct sdio_func *func, > const struct sdio_device_id *id) > { > @@ -998,6 +1024,7 @@ static int btmtksdio_probe(struct sdio_func *func, > hdev->shutdown = btmtksdio_shutdown; > hdev->send = btmtksdio_send_frame; > hdev->set_bdaddr = btmtk_set_bdaddr; > + hdev->wakeup = btmtk_sdio_wakeup; Just move this one after ->send. > > SET_HCIDEV_DEV(hdev, &func->dev); > > @@ -1032,7 +1059,11 @@ static int btmtksdio_probe(struct sdio_func *func, > */ > pm_runtime_put_noidle(bdev->dev); > > - return 0; > + err = device_init_wakeup(bdev->dev, true); > + if (err) > + bt_dev_err(hdev, "failed to init_wakeup"); Don’t use function names in the error message. Make it descriptive. > + > + return err; > } > Regards Marcel
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h index 6e7b0c7567c0..2be1d2680ad8 100644 --- a/drivers/bluetooth/btmtk.h +++ b/drivers/bluetooth/btmtk.h @@ -68,6 +68,14 @@ struct btmtk_tci_sleep { u8 time_compensation; } __packed; +struct btmtk_wakeon { + u8 mode; + u8 gpo; + u8 active_high; + __le16 enable_delay; + __le16 wakeup_delay; +} __packed; + struct btmtk_hci_wmt_params { u8 op; u8 flag; diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index b5ea8d3bffaa..89bd70651e9e 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -958,6 +958,32 @@ static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) return 0; } +static bool btmtk_sdio_wakeup(struct hci_dev *hdev) +{ + struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); + bool may_wakeup = device_may_wakeup(bdev->dev); + const struct btmtk_wakeon bt_awake = { + .mode = 0x1, + .gpo = 0, + .active_high = 0x1, + .enable_delay = cpu_to_le16(0xc80), + .wakeup_delay = cpu_to_le16(0x20) + }; + + if (may_wakeup && bdev->data->chipid == 0x7921) { + struct sk_buff *skb; + + skb = __hci_cmd_sync(hdev, 0xfc27, sizeof(bt_awake), + &bt_awake, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) + may_wakeup = false; + + kfree_skb(skb); + } + + return may_wakeup; +} + static int btmtksdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { @@ -998,6 +1024,7 @@ static int btmtksdio_probe(struct sdio_func *func, hdev->shutdown = btmtksdio_shutdown; hdev->send = btmtksdio_send_frame; hdev->set_bdaddr = btmtk_set_bdaddr; + hdev->wakeup = btmtk_sdio_wakeup; SET_HCIDEV_DEV(hdev, &func->dev); @@ -1032,7 +1059,11 @@ static int btmtksdio_probe(struct sdio_func *func, */ pm_runtime_put_noidle(bdev->dev); - return 0; + err = device_init_wakeup(bdev->dev, true); + if (err) + bt_dev_err(hdev, "failed to init_wakeup"); + + return err; } static void btmtksdio_remove(struct sdio_func *func)