Bluetooth: Perform a power cycle when receiving hardware error event

When receiving a HCI Hardware Error event, the controller should be
assumed to be non-functional until issuing a HCI Reset command.

The Bluetooth hardware errors are vendor specific and so add a
new hdev->hw_error callback that drivers can provide to run extra
code to handle the hardware error.

After completing the vendor specific error handling perform a full
reset of the Bluetooth stack by closing and re-opening the transport.

Based-on-patch-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Marcel Holtmann 2015-01-28 11:09:55 -08:00
commit c7741d16a5
3 changed files with 27 additions and 1 deletions

View file

@ -2151,6 +2151,26 @@ static void hci_power_off(struct work_struct *work)
smp_unregister(hdev);
}
static void hci_error_reset(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev, error_reset);
BT_DBG("%s", hdev->name);
if (hdev->hw_error)
hdev->hw_error(hdev, hdev->hw_error_code);
else
BT_ERR("%s hardware error 0x%2.2x", hdev->name,
hdev->hw_error_code);
if (hci_dev_do_close(hdev))
return;
smp_unregister(hdev);
hci_dev_do_open(hdev);
}
static void hci_discov_off(struct work_struct *work)
{
struct hci_dev *hdev;
@ -2943,6 +2963,7 @@ struct hci_dev *hci_alloc_dev(void)
INIT_WORK(&hdev->cmd_work, hci_cmd_work);
INIT_WORK(&hdev->tx_work, hci_tx_work);
INIT_WORK(&hdev->power_on, hci_power_on);
INIT_WORK(&hdev->error_reset, hci_error_reset);
INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);