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

Bluetooth: Handle LE devices during suspend

To handle LE devices, we must first disable passive scanning and
disconnect all connected devices. Once that is complete, we update the
whitelist and re-enable scanning

Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Abhishek Pandit-Subedi and committed by
Marcel Holtmann
dd522a74 4f40afc6

+113 -54
+1
include/net/bluetooth/hci_core.h
··· 607 607 608 608 struct hci_conn *conn; 609 609 bool explicit_connect; 610 + bool wakeable; 610 611 }; 611 612 612 613 extern struct list_head hci_dev_list;
+112 -54
net/bluetooth/hci_request.c
··· 34 34 #define HCI_REQ_PEND 1 35 35 #define HCI_REQ_CANCELED 2 36 36 37 + #define LE_SUSPEND_SCAN_WINDOW 0x0012 38 + #define LE_SUSPEND_SCAN_INTERVAL 0x0060 39 + 37 40 void hci_req_init(struct hci_request *req, struct hci_dev *hdev) 38 41 { 39 42 skb_queue_head_init(&req->cmd_q); ··· 657 654 { 658 655 struct hci_dev *hdev = req->hdev; 659 656 657 + if (hdev->scanning_paused) { 658 + bt_dev_dbg(hdev, "Scanning is paused for suspend"); 659 + return; 660 + } 661 + 660 662 if (use_ext_scan(hdev)) { 661 663 struct hci_cp_le_set_ext_scan_enable cp; 662 664 ··· 678 670 } 679 671 } 680 672 681 - static void add_to_white_list(struct hci_request *req, 682 - struct hci_conn_params *params) 673 + static void del_from_white_list(struct hci_request *req, bdaddr_t *bdaddr, 674 + u8 bdaddr_type) 675 + { 676 + struct hci_cp_le_del_from_white_list cp; 677 + 678 + cp.bdaddr_type = bdaddr_type; 679 + bacpy(&cp.bdaddr, bdaddr); 680 + 681 + bt_dev_dbg(req->hdev, "Remove %pMR (0x%x) from whitelist", &cp.bdaddr, 682 + cp.bdaddr_type); 683 + hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, sizeof(cp), &cp); 684 + } 685 + 686 + /* Adds connection to white list if needed. On error, returns -1. */ 687 + static int add_to_white_list(struct hci_request *req, 688 + struct hci_conn_params *params, u8 *num_entries, 689 + bool allow_rpa) 683 690 { 684 691 struct hci_cp_le_add_to_white_list cp; 692 + struct hci_dev *hdev = req->hdev; 685 693 694 + /* Already in white list */ 695 + if (hci_bdaddr_list_lookup(&hdev->le_white_list, &params->addr, 696 + params->addr_type)) 697 + return 0; 698 + 699 + /* Select filter policy to accept all advertising */ 700 + if (*num_entries >= hdev->le_white_list_size) 701 + return -1; 702 + 703 + /* White list can not be used with RPAs */ 704 + if (!allow_rpa && 705 + hci_find_irk_by_addr(hdev, &params->addr, params->addr_type)) { 706 + return -1; 707 + } 708 + 709 + /* During suspend, only wakeable devices can be in whitelist */ 710 + if (hdev->suspended && !params->wakeable) 711 + return 0; 712 + 713 + *num_entries += 1; 686 714 cp.bdaddr_type = params->addr_type; 687 715 bacpy(&cp.bdaddr, &params->addr); 688 716 717 + bt_dev_dbg(hdev, "Add %pMR (0x%x) to whitelist", &cp.bdaddr, 718 + cp.bdaddr_type); 689 719 hci_req_add(req, HCI_OP_LE_ADD_TO_WHITE_LIST, sizeof(cp), &cp); 720 + 721 + return 0; 690 722 } 691 723 692 724 static u8 update_white_list(struct hci_request *req) ··· 734 686 struct hci_dev *hdev = req->hdev; 735 687 struct hci_conn_params *params; 736 688 struct bdaddr_list *b; 737 - uint8_t white_list_entries = 0; 689 + u8 num_entries = 0; 690 + bool pend_conn, pend_report; 691 + /* We allow whitelisting even with RPAs in suspend. In the worst case, 692 + * we won't be able to wake from devices that use the privacy1.2 693 + * features. Additionally, once we support privacy1.2 and IRK 694 + * offloading, we can update this to also check for those conditions. 695 + */ 696 + bool allow_rpa = hdev->suspended; 738 697 739 698 /* Go through the current white list programmed into the 740 699 * controller one by one and check if that address is still ··· 750 695 * command to remove it from the controller. 751 696 */ 752 697 list_for_each_entry(b, &hdev->le_white_list, list) { 753 - /* If the device is neither in pend_le_conns nor 754 - * pend_le_reports then remove it from the whitelist. 698 + pend_conn = hci_pend_le_action_lookup(&hdev->pend_le_conns, 699 + &b->bdaddr, 700 + b->bdaddr_type); 701 + pend_report = hci_pend_le_action_lookup(&hdev->pend_le_reports, 702 + &b->bdaddr, 703 + b->bdaddr_type); 704 + 705 + /* If the device is not likely to connect or report, 706 + * remove it from the whitelist. 755 707 */ 756 - if (!hci_pend_le_action_lookup(&hdev->pend_le_conns, 757 - &b->bdaddr, b->bdaddr_type) && 758 - !hci_pend_le_action_lookup(&hdev->pend_le_reports, 759 - &b->bdaddr, b->bdaddr_type)) { 760 - struct hci_cp_le_del_from_white_list cp; 761 - 762 - cp.bdaddr_type = b->bdaddr_type; 763 - bacpy(&cp.bdaddr, &b->bdaddr); 764 - 765 - hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, 766 - sizeof(cp), &cp); 708 + if (!pend_conn && !pend_report) { 709 + del_from_white_list(req, &b->bdaddr, b->bdaddr_type); 767 710 continue; 768 711 } 769 712 770 - if (hci_find_irk_by_addr(hdev, &b->bdaddr, b->bdaddr_type)) { 771 - /* White list can not be used with RPAs */ 713 + /* White list can not be used with RPAs */ 714 + if (!allow_rpa && 715 + hci_find_irk_by_addr(hdev, &b->bdaddr, b->bdaddr_type)) { 772 716 return 0x00; 773 717 } 774 718 775 - white_list_entries++; 719 + num_entries++; 776 720 } 777 721 778 722 /* Since all no longer valid white list entries have been ··· 785 731 * white list. 786 732 */ 787 733 list_for_each_entry(params, &hdev->pend_le_conns, action) { 788 - if (hci_bdaddr_list_lookup(&hdev->le_white_list, 789 - &params->addr, params->addr_type)) 790 - continue; 791 - 792 - if (white_list_entries >= hdev->le_white_list_size) { 793 - /* Select filter policy to accept all advertising */ 734 + if (add_to_white_list(req, params, &num_entries, allow_rpa)) 794 735 return 0x00; 795 - } 796 - 797 - if (hci_find_irk_by_addr(hdev, &params->addr, 798 - params->addr_type)) { 799 - /* White list can not be used with RPAs */ 800 - return 0x00; 801 - } 802 - 803 - white_list_entries++; 804 - add_to_white_list(req, params); 805 736 } 806 737 807 738 /* After adding all new pending connections, walk through 808 739 * the list of pending reports and also add these to the 809 - * white list if there is still space. 740 + * white list if there is still space. Abort if space runs out. 810 741 */ 811 742 list_for_each_entry(params, &hdev->pend_le_reports, action) { 812 - if (hci_bdaddr_list_lookup(&hdev->le_white_list, 813 - &params->addr, params->addr_type)) 814 - continue; 815 - 816 - if (white_list_entries >= hdev->le_white_list_size) { 817 - /* Select filter policy to accept all advertising */ 743 + if (add_to_white_list(req, params, &num_entries, allow_rpa)) 818 744 return 0x00; 819 - } 820 - 821 - if (hci_find_irk_by_addr(hdev, &params->addr, 822 - params->addr_type)) { 823 - /* White list can not be used with RPAs */ 824 - return 0x00; 825 - } 826 - 827 - white_list_entries++; 828 - add_to_white_list(req, params); 829 745 } 830 746 831 747 /* Select filter policy to use white list */ ··· 890 866 struct hci_dev *hdev = req->hdev; 891 867 u8 own_addr_type; 892 868 u8 filter_policy; 869 + u8 window, interval; 870 + 871 + if (hdev->scanning_paused) { 872 + bt_dev_dbg(hdev, "Scanning is paused for suspend"); 873 + return; 874 + } 893 875 894 876 /* Set require_privacy to false since no SCAN_REQ are send 895 877 * during passive scanning. Not using an non-resolvable address ··· 926 896 (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY)) 927 897 filter_policy |= 0x02; 928 898 929 - hci_req_start_scan(req, LE_SCAN_PASSIVE, hdev->le_scan_interval, 930 - hdev->le_scan_window, own_addr_type, filter_policy); 899 + if (hdev->suspended) { 900 + window = LE_SUSPEND_SCAN_WINDOW; 901 + interval = LE_SUSPEND_SCAN_INTERVAL; 902 + } else { 903 + window = hdev->le_scan_window; 904 + interval = hdev->le_scan_interval; 905 + } 906 + 907 + bt_dev_dbg(hdev, "LE passive scan with whitelist = %d", filter_policy); 908 + hci_req_start_scan(req, LE_SCAN_PASSIVE, interval, window, 909 + own_addr_type, filter_policy); 931 910 } 932 911 933 912 static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance) ··· 996 957 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); 997 958 } 998 959 960 + static void hci_req_config_le_suspend_scan(struct hci_request *req) 961 + { 962 + /* Can't change params without disabling first */ 963 + hci_req_add_le_scan_disable(req); 964 + 965 + /* Configure params and enable scanning */ 966 + hci_req_add_le_passive_scan(req); 967 + 968 + /* Block suspend notifier on response */ 969 + set_bit(SUSPEND_SCAN_ENABLE, req->hdev->suspend_tasks); 970 + } 971 + 999 972 static void suspend_req_complete(struct hci_dev *hdev, u8 status, u16 opcode) 1000 973 { 1001 974 bt_dev_dbg(hdev, "Request complete opcode=0x%x, status=0x%x", opcode, ··· 1042 991 page_scan = SCAN_DISABLED; 1043 992 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &page_scan); 1044 993 994 + /* Disable LE passive scan */ 995 + hci_req_add_le_scan_disable(&req); 996 + 1045 997 /* Mark task needing completion */ 1046 998 set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks); 1047 999 ··· 1072 1018 hdev->scanning_paused = false; 1073 1019 /* Enable event filter for paired devices */ 1074 1020 hci_req_set_event_filter(&req); 1021 + /* Enable passive scan at lower duty cycle */ 1022 + hci_req_config_le_suspend_scan(&req); 1075 1023 /* Pause scan changes again. */ 1076 1024 hdev->scanning_paused = true; 1077 1025 hci_req_run(&req, suspend_req_complete); ··· 1082 1026 hdev->scanning_paused = false; 1083 1027 1084 1028 hci_req_clear_event_filter(&req); 1029 + /* Reset passive/background scanning to normal */ 1030 + hci_req_config_le_suspend_scan(&req); 1085 1031 hci_req_run(&req, suspend_req_complete); 1086 1032 } 1087 1033