diff mbox series

[1/4] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding

Message ID 43b68b1f48c20b1dfcd7e6663c3dcb38e4e0648c.1663020936.git.objelf@gmail.com (mailing list archive)
State New, archived
Headers show
Series [1/4] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding | expand

Commit Message

Sean Wang Sept. 12, 2022, 10:18 p.m. UTC
From: Sean Wang <sean.wang@mediatek.com>

Use readx_poll_timeout instead of open coding to poll the hardware reset
status until it is done.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/bluetooth/btusb.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

Comments

AngeloGioacchino Del Regno Sept. 13, 2022, 7:47 a.m. UTC | #1
Il 13/09/22 00:18, sean.wang@mediatek.com ha scritto:
> From: Sean Wang <sean.wang@mediatek.com>
> 
> Use readx_poll_timeout instead of open coding to poll the hardware reset
> status until it is done.
> 
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>

Hello Sean, thanks for the patch!
However, there's something to improve...

> ---
>   drivers/bluetooth/btusb.c | 32 ++++++++++++++++++--------------
>   1 file changed, 18 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index c3daba17de7f..4dc9cae3e937 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c

..snip..

> @@ -2910,18 +2918,14 @@ static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
>   	btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
>   	btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
>   
> -	/* Poll the register until reset is completed */
> -	do {
> -		btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
> -		if (val & MTK_BT_RST_DONE) {
> -			bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
> -			break;
> -		}
> +	err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
> +				 val & MTK_BT_RST_DONE,
> +				 100000, 1000000);

I agree with using readx_poll_timeout() instead of open coding the same, but
there's a catch: this macro uses usleep_range(), which is meant to be used
for sleeping less than ~20ms.

Even the kerneldoc at include/linux/iopoll.h advertises that:

  * @sleep_us: Maximum time to sleep between reads in us (0
  *            tight-loops).  Should be less than ~20ms since usleep_range
  *            is used (see Documentation/timers/timers-howto.rst).

So, if there's any reason for which you can't sleep for less than 100ms
per iteration, I'm afraid that you can't use readx_poll_timeout()...
...otherwise, please change sleep_us to 20000 and keep the timeout at 1 sec.

Regards,
Angelo

> +	if (err < 0)
> +		bt_dev_err(hdev, "Reset timeout");
>   
> -		bt_dev_dbg(hdev, "Polling Bluetooth Reset CR");
> -		retry++;
> -		msleep(MTK_BT_RESET_WAIT_MS);
> -	} while (retry < MTK_BT_RESET_NUM_TRIES);
> +	if (val & MTK_BT_RST_DONE)
> +		bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
>   
>   	btusb_mtk_id_get(data, 0x70010200, &val);
>   	if (!val)
Sean Wang Sept. 14, 2022, 10:59 p.m. UTC | #2
HI Angelo,

On Tue, Sep 13, 2022 at 1:04 AM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Il 13/09/22 00:18, sean.wang@mediatek.com ha scritto:
> > From: Sean Wang <sean.wang@mediatek.com>
> >
> > Use readx_poll_timeout instead of open coding to poll the hardware reset
> > status until it is done.
> >
> > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
>
> Hello Sean, thanks for the patch!
> However, there's something to improve...
>
> > ---
> >   drivers/bluetooth/btusb.c | 32 ++++++++++++++++++--------------
> >   1 file changed, 18 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> > index c3daba17de7f..4dc9cae3e937 100644
> > --- a/drivers/bluetooth/btusb.c
> > +++ b/drivers/bluetooth/btusb.c
>
> ..snip..
>
> > @@ -2910,18 +2918,14 @@ static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
> >       btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
> >       btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
> >
> > -     /* Poll the register until reset is completed */
> > -     do {
> > -             btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
> > -             if (val & MTK_BT_RST_DONE) {
> > -                     bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
> > -                     break;
> > -             }
> > +     err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
> > +                              val & MTK_BT_RST_DONE,
> > +                              100000, 1000000);
>
> I agree with using readx_poll_timeout() instead of open coding the same, but
> there's a catch: this macro uses usleep_range(), which is meant to be used
> for sleeping less than ~20ms.
>
> Even the kerneldoc at include/linux/iopoll.h advertises that:
>
>   * @sleep_us: Maximum time to sleep between reads in us (0
>   *            tight-loops).  Should be less than ~20ms since usleep_range
>   *            is used (see Documentation/timers/timers-howto.rst).
>
> So, if there's any reason for which you can't sleep for less than 100ms
> per iteration, I'm afraid that you can't use readx_poll_timeout()...
> ...otherwise, please change sleep_us to 20000 and keep the timeout at 1 sec.
>

It should be able to be done with polling in 20ms until 1 sec expires
or it is done. It increases some cost in the bus transaction
interacting with the device, but it seemed fine for me because the
code path is cold, it is only working in the device reset which should
rarely happen, and only involves when it is really necessary. That is
a nice catch. I was trying not to break the existing logic
but overlooked the requirements of the API.

    Sean

> Regards,
> Angelo
>
> > +     if (err < 0)
> > +             bt_dev_err(hdev, "Reset timeout");
> >
> > -             bt_dev_dbg(hdev, "Polling Bluetooth Reset CR");
> > -             retry++;
> > -             msleep(MTK_BT_RESET_WAIT_MS);
> > -     } while (retry < MTK_BT_RESET_NUM_TRIES);
> > +     if (val & MTK_BT_RST_DONE)
> > +             bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
> >
> >       btusb_mtk_id_get(data, 0x70010200, &val);
> >       if (!val)
>
diff mbox series

Patch

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index c3daba17de7f..4dc9cae3e937 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2318,8 +2318,6 @@  static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
 #define MTK_EP_RST_OPT		0x74011890
 #define MTK_EP_RST_IN_OUT_OPT	0x00010001
 #define MTK_BT_RST_DONE		0x00000100
-#define MTK_BT_RESET_WAIT_MS	100
-#define MTK_BT_RESET_NUM_TRIES	10
 
 static void btusb_mtk_wmt_recv(struct urb *urb)
 {
@@ -2690,6 +2688,16 @@  static int btusb_mtk_id_get(struct btusb_data *data, u32 reg, u32 *id)
 	return btusb_mtk_reg_read(data, reg, id);
 }
 
+static u32 btusb_mtk_reset_done(struct hci_dev *hdev)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+	u32 val = 0;
+
+	btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
+
+	return val;
+}
+
 static int btusb_mtk_setup(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -2879,7 +2887,7 @@  static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
 	u32 val;
-	int err, retry = 0;
+	int err;
 
 	/* It's MediaTek specific bluetooth reset mechanism via USB */
 	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
@@ -2910,18 +2918,14 @@  static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
 	btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
 	btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
 
-	/* Poll the register until reset is completed */
-	do {
-		btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
-		if (val & MTK_BT_RST_DONE) {
-			bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
-			break;
-		}
+	err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
+				 val & MTK_BT_RST_DONE,
+				 100000, 1000000);
+	if (err < 0)
+		bt_dev_err(hdev, "Reset timeout");
 
-		bt_dev_dbg(hdev, "Polling Bluetooth Reset CR");
-		retry++;
-		msleep(MTK_BT_RESET_WAIT_MS);
-	} while (retry < MTK_BT_RESET_NUM_TRIES);
+	if (val & MTK_BT_RST_DONE)
+		bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
 
 	btusb_mtk_id_get(data, 0x70010200, &val);
 	if (!val)