diff mbox series

[v5,3/4] Bluetooth: Allow driver specific cmd timeout handling

Message ID 20190123205725.239661-3-rajatja@google.com (mailing list archive)
State New, archived
Headers show
Series [v5,1/4] usb: split code locating ACPI companion into port and device | expand

Commit Message

Rajat Jain Jan. 23, 2019, 8:57 p.m. UTC
Add a hook to allow the BT driver to do device or command specific
handling in case of timeouts. This is to be used by Intel driver to
reset the device after certain number of timeouts.

Signed-off-by: Rajat Jain <rajatja@google.com>
---
v5: Drop the quirk, and rename the hook function to cmd_timeout()
v4: same as v1
v3: same as v1
v2: same as v1

 include/net/bluetooth/hci_core.h |  1 +
 net/bluetooth/hci_core.c         | 10 ++++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

Comments

Marcel Holtmann Jan. 24, 2019, 9:36 a.m. UTC | #1
Hi Rajat,

> Add a hook to allow the BT driver to do device or command specific
> handling in case of timeouts. This is to be used by Intel driver to
> reset the device after certain number of timeouts.
> 
> Signed-off-by: Rajat Jain <rajatja@google.com>
> ---
> v5: Drop the quirk, and rename the hook function to cmd_timeout()
> v4: same as v1
> v3: same as v1
> v2: same as v1
> 
> include/net/bluetooth/hci_core.h |  1 +
> net/bluetooth/hci_core.c         | 10 ++++++++--
> 2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index e5ea633ea368..624d5f2b1f36 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -437,6 +437,7 @@ struct hci_dev {
> 	int (*post_init)(struct hci_dev *hdev);
> 	int (*set_diag)(struct hci_dev *hdev, bool enable);
> 	int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
> +	void (*cmd_timeout)(struct hci_dev *hdev, struct hci_command_hdr *cmd);
> };
> 
> #define HCI_PHY_HANDLE(handle)	(handle & 0xff)
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 7352fe85674b..c6917f57581a 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -2568,16 +2568,22 @@ static void hci_cmd_timeout(struct work_struct *work)
> {
> 	struct hci_dev *hdev = container_of(work, struct hci_dev,
> 					    cmd_timer.work);
> +	struct hci_command_hdr *sent = NULL;
> 
> 	if (hdev->sent_cmd) {
> -		struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data;
> -		u16 opcode = __le16_to_cpu(sent->opcode);
> +		u16 opcode;
> +
> +		sent = (void *) hdev->sent_cmd->data;
> +		opcode = __le16_to_cpu(sent->opcode);
> 
> 		bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
> 	} else {
> 		bt_dev_err(hdev, "command tx timeout");
> 	}
> 
> +	if (hdev->cmd_timeout)
> +		hdev->cmd_timeout(hdev, sent);
> +

drop the sent parameter. You are not using it and if at some point in the future you might want to use it, then we add it and fix up all users.

And frankly, I would move the hdev->cmd_timeout call into the hdev->sent_cmd block since I do not even know if it makes sense to deal with the fallback case where hdev->sent_cmd is not available. Unless you have that kind of error case, but that is only possible if you have external injection of HCI commands.

Regards

Marcel
Rajat Jain Jan. 24, 2019, 8:10 p.m. UTC | #2
Hi Marcel,

On Thu, Jan 24, 2019 at 1:36 AM Marcel Holtmann <marcel@holtmann.org> wrote:
>
> Hi Rajat,
>
> > Add a hook to allow the BT driver to do device or command specific
> > handling in case of timeouts. This is to be used by Intel driver to
> > reset the device after certain number of timeouts.
> >
> > Signed-off-by: Rajat Jain <rajatja@google.com>
> > ---
> > v5: Drop the quirk, and rename the hook function to cmd_timeout()
> > v4: same as v1
> > v3: same as v1
> > v2: same as v1
> >
> > include/net/bluetooth/hci_core.h |  1 +
> > net/bluetooth/hci_core.c         | 10 ++++++++--
> > 2 files changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index e5ea633ea368..624d5f2b1f36 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -437,6 +437,7 @@ struct hci_dev {
> >       int (*post_init)(struct hci_dev *hdev);
> >       int (*set_diag)(struct hci_dev *hdev, bool enable);
> >       int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
> > +     void (*cmd_timeout)(struct hci_dev *hdev, struct hci_command_hdr *cmd);
> > };
> >
> > #define HCI_PHY_HANDLE(handle)        (handle & 0xff)
> > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > index 7352fe85674b..c6917f57581a 100644
> > --- a/net/bluetooth/hci_core.c
> > +++ b/net/bluetooth/hci_core.c
> > @@ -2568,16 +2568,22 @@ static void hci_cmd_timeout(struct work_struct *work)
> > {
> >       struct hci_dev *hdev = container_of(work, struct hci_dev,
> >                                           cmd_timer.work);
> > +     struct hci_command_hdr *sent = NULL;
> >
> >       if (hdev->sent_cmd) {
> > -             struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data;
> > -             u16 opcode = __le16_to_cpu(sent->opcode);
> > +             u16 opcode;
> > +
> > +             sent = (void *) hdev->sent_cmd->data;
> > +             opcode = __le16_to_cpu(sent->opcode);
> >
> >               bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
> >       } else {
> >               bt_dev_err(hdev, "command tx timeout");
> >       }
> >
> > +     if (hdev->cmd_timeout)
> > +             hdev->cmd_timeout(hdev, sent);
> > +
>
> drop the sent parameter. You are not using it and if at some point in the future you might want to use it, then we add it and fix up all users.

Sure, will do.

>
> And frankly, I would move the hdev->cmd_timeout call into the hdev->sent_cmd block since I do not even know if it makes sense to deal with the fallback case where hdev->sent_cmd is not available. Unless you have that kind of error case, but that is only possible if you have external injection of HCI commands.

Ummm ... my preference would be to keep it outside the block so that
the hook is always invoked in any timeout, to be consistent (whether
externally injected or not). Let me know if that is OK. I plan to send
out an iteration keeping it outside, but I'll be happy to move it in
if you feel strongly about it.

Thanks,

Rajat

>
> Regards
>
> Marcel
>
diff mbox series

Patch

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e5ea633ea368..624d5f2b1f36 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -437,6 +437,7 @@  struct hci_dev {
 	int (*post_init)(struct hci_dev *hdev);
 	int (*set_diag)(struct hci_dev *hdev, bool enable);
 	int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+	void (*cmd_timeout)(struct hci_dev *hdev, struct hci_command_hdr *cmd);
 };
 
 #define HCI_PHY_HANDLE(handle)	(handle & 0xff)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 7352fe85674b..c6917f57581a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2568,16 +2568,22 @@  static void hci_cmd_timeout(struct work_struct *work)
 {
 	struct hci_dev *hdev = container_of(work, struct hci_dev,
 					    cmd_timer.work);
+	struct hci_command_hdr *sent = NULL;
 
 	if (hdev->sent_cmd) {
-		struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data;
-		u16 opcode = __le16_to_cpu(sent->opcode);
+		u16 opcode;
+
+		sent = (void *) hdev->sent_cmd->data;
+		opcode = __le16_to_cpu(sent->opcode);
 
 		bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
 	} else {
 		bt_dev_err(hdev, "command tx timeout");
 	}
 
+	if (hdev->cmd_timeout)
+		hdev->cmd_timeout(hdev, sent);
+
 	atomic_set(&hdev->cmd_cnt, 1);
 	queue_work(hdev->workqueue, &hdev->cmd_work);
 }