[for-4.14.y,4/5] Bluetooth: hci_serdev: Init hci_uart proto_lock to avoid oops

Message ID 1533042142-8681-4-git-send-email-amit.pundir@linaro.org
State New
Headers show
  • [for-4.14.y,1/5] mtd: nand: qcom: Add a NULL check for devm_kasprintf()
Related show

Commit Message

Amit Pundir July 31, 2018, 1:02 p.m.
From: Lukas Wunner <lukas@wunner.de>

commit d73e172816652772114827abaa2dbc053eecbbd7 upstream.

John Stultz reports a boot time crash with the HiKey board (which uses
hci_serdev) occurring in hci_uart_tx_wakeup().  That function is
contained in hci_ldisc.c, but also called from the newer hci_serdev.c.
It acquires the proto_lock in struct hci_uart and it turns out that we
forgot to init the lock in the serdev code path, thus causing the crash.

John bisected the crash to commit 67d2f8781b9f ("Bluetooth: hci_ldisc:
Allow sleeping while proto locks are held"), but the issue was present
before and the commit merely exposed it.  (Perhaps by luck, the crash
did not occur with rwlocks.)

Init the proto_lock in the serdev code path to avoid the oops.

Stack trace for posterity:

Unable to handle kernel read from unreadable memory at 406f127000
[000000406f127000] user address but active_mm is swapper
Internal error: Oops: 96000005 [#1] PREEMPT SMP
Hardware name: HiKey Development Board (DT)
Call trace:

Link: https://lkml.org/lkml/2017/11/15/908
Reported-and-tested-by: John Stultz <john.stultz@linaro.org>
Cc: Ronald Tschalär <ronald@innovation.ch>
Cc: Rob Herring <rob.herring@linaro.org>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Signed-off-by: Lukas Wunner <lukas@wunner.de>

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

Signed-off-by: Amit Pundir <amit.pundir@linaro.org>

Not applicable for 4.9.y, 4.4.y and 3.18.y

 drivers/bluetooth/hci_serdev.c | 1 +
 1 file changed, 1 insertion(+)



diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c
index b725ac4f7ff6..52e6d4d1608e 100644
--- a/drivers/bluetooth/hci_serdev.c
+++ b/drivers/bluetooth/hci_serdev.c
@@ -304,6 +304,7 @@  int hci_uart_register_device(struct hci_uart *hu,
 	hci_set_drvdata(hdev, hu);
 	INIT_WORK(&hu->write_work, hci_uart_write_work);
+	percpu_init_rwsem(&hu->proto_lock);
 	/* Only when vendor specific setup callback is provided, consider
 	 * the manufacturer information valid. This avoids filling in the