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 |
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)
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 --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)