Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: Mark controller is down when HCI_AUTO_OFF is set

During the initial setup phase, the controller is powered on and will
be powered off again if it is not used within the auto-off timeout.

Userspace using ioctl does not know about the difference between the
initial setup phase and a controller being present. It is a bad idea
to keep the controller powered by just looking at the device list or
device information. Instead just tell userspace that the controller
is still down.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>

authored by

Marcel Holtmann and committed by
Johan Hedberg
2e84d8db 13a779e4

+19 -6
+19 -6
net/bluetooth/hci_core.c
··· 2817 2817 2818 2818 read_lock(&hci_dev_list_lock); 2819 2819 list_for_each_entry(hdev, &hci_dev_list, list) { 2820 - if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) 2821 - cancel_delayed_work(&hdev->power_off); 2820 + unsigned long flags = hdev->flags; 2821 + 2822 + /* When the auto-off is configured it means the transport 2823 + * is running, but in that case still indicate that the 2824 + * device is actually down. 2825 + */ 2826 + if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) 2827 + flags &= ~BIT(HCI_UP); 2822 2828 2823 2829 if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2824 2830 set_bit(HCI_PAIRABLE, &hdev->dev_flags); 2825 2831 2826 2832 (dr + n)->dev_id = hdev->id; 2827 - (dr + n)->dev_opt = hdev->flags; 2833 + (dr + n)->dev_opt = flags; 2828 2834 2829 2835 if (++n >= dev_num) 2830 2836 break; ··· 2850 2844 { 2851 2845 struct hci_dev *hdev; 2852 2846 struct hci_dev_info di; 2847 + unsigned long flags; 2853 2848 int err = 0; 2854 2849 2855 2850 if (copy_from_user(&di, arg, sizeof(di))) ··· 2860 2853 if (!hdev) 2861 2854 return -ENODEV; 2862 2855 2863 - if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) 2864 - cancel_delayed_work_sync(&hdev->power_off); 2856 + /* When the auto-off is configured it means the transport 2857 + * is running, but in that case still indicate that the 2858 + * device is actually down. 2859 + */ 2860 + if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) 2861 + flags = hdev->flags & ~BIT(HCI_UP); 2862 + else 2863 + flags = hdev->flags; 2865 2864 2866 2865 if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2867 2866 set_bit(HCI_PAIRABLE, &hdev->dev_flags); ··· 2875 2862 strcpy(di.name, hdev->name); 2876 2863 di.bdaddr = hdev->bdaddr; 2877 2864 di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4); 2878 - di.flags = hdev->flags; 2865 + di.flags = flags; 2879 2866 di.pkt_type = hdev->pkt_type; 2880 2867 if (lmp_bredr_capable(hdev)) { 2881 2868 di.acl_mtu = hdev->acl_mtu;