diff options
author | David S. Miller <davem@davemloft.net> | 2015-07-30 19:16:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-30 19:16:43 -0400 |
commit | 29a3060aa7cc2e5cfaabeb935fafb832b9b33ad4 (patch) | |
tree | 326179bc399ee9deceaf3b738d420d384f134f7a | |
parent | 8013d1d7eafb0589ca766db6b74026f76b7f5cb4 (diff) | |
parent | 5857d1dbae7d5bf4219efc39996ad002362a2951 (diff) |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says:
====================
pull request: bluetooth-next 2015-07-30
Here's a set of Bluetooth & 802.15.4 patches intended for the 4.3 kernel.
- Cleanups & fixes to mac802154
- Refactoring of Intel Bluetooth HCI driver
- Various coding style fixes to Bluetooth HCI drivers
- Support for Intel Lightning Peak Bluetooth devices
- Generic class code in interface descriptor in btusb to match more HW
- Refactoring of Bluetooth HS code together with a new config option
- Support for BCM4330B1 Broadcom UART controller
Let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
43 files changed, 1167 insertions, 331 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 2e777071e1dc..79e8234b1aa5 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig | |||
@@ -132,6 +132,7 @@ config BT_HCIUART_3WIRE | |||
132 | config BT_HCIUART_INTEL | 132 | config BT_HCIUART_INTEL |
133 | bool "Intel protocol support" | 133 | bool "Intel protocol support" |
134 | depends on BT_HCIUART | 134 | depends on BT_HCIUART |
135 | select BT_HCIUART_H4 | ||
135 | select BT_INTEL | 136 | select BT_INTEL |
136 | help | 137 | help |
137 | The Intel protocol support enables Bluetooth HCI over serial | 138 | The Intel protocol support enables Bluetooth HCI over serial |
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index fcfb72e9e0ee..a5c4d0584389 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c | |||
@@ -492,7 +492,7 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
492 | case HCI_SCODATA_PKT: | 492 | case HCI_SCODATA_PKT: |
493 | hdev->stat.sco_tx++; | 493 | hdev->stat.sco_tx++; |
494 | break; | 494 | break; |
495 | }; | 495 | } |
496 | 496 | ||
497 | /* Prepend skb with frame type */ | 497 | /* Prepend skb with frame type */ |
498 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); | 498 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 7aab65427d38..a00bb82eb7c6 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -427,7 +427,7 @@ static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
427 | case HCI_SCODATA_PKT: | 427 | case HCI_SCODATA_PKT: |
428 | hdev->stat.sco_tx++; | 428 | hdev->stat.sco_tx++; |
429 | break; | 429 | break; |
430 | }; | 430 | } |
431 | 431 | ||
432 | /* Prepend skb with frame type */ | 432 | /* Prepend skb with frame type */ |
433 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); | 433 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); |
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 9ceb8ac68fdc..02ed816a18f9 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) | 35 | #define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) |
36 | #define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}}) | 36 | #define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}}) |
37 | #define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}}) | ||
37 | 38 | ||
38 | int btbcm_check_bdaddr(struct hci_dev *hdev) | 39 | int btbcm_check_bdaddr(struct hci_dev *hdev) |
39 | { | 40 | { |
@@ -66,9 +67,13 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) | |||
66 | * | 67 | * |
67 | * The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller | 68 | * The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller |
68 | * with waiting for configuration state. | 69 | * with waiting for configuration state. |
70 | * | ||
71 | * The address 43:30:B1:00:00:00 indicates a BCM4330B1 controller | ||
72 | * with waiting for configuration state. | ||
69 | */ | 73 | */ |
70 | if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) || | 74 | if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) || |
71 | !bacmp(&bda->bdaddr, BDADDR_BCM4324B3)) { | 75 | !bacmp(&bda->bdaddr, BDADDR_BCM4324B3) || |
76 | !bacmp(&bda->bdaddr, BDADDR_BCM4330B1)) { | ||
72 | BT_INFO("%s: BCM: Using default device address (%pMR)", | 77 | BT_INFO("%s: BCM: Using default device address (%pMR)", |
73 | hdev->name, &bda->bdaddr); | 78 | hdev->name, &bda->bdaddr); |
74 | set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); | 79 | set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); |
@@ -241,6 +246,7 @@ static const struct { | |||
241 | u16 subver; | 246 | u16 subver; |
242 | const char *name; | 247 | const char *name; |
243 | } bcm_uart_subver_table[] = { | 248 | } bcm_uart_subver_table[] = { |
249 | { 0x4103, "BCM4330B1" }, /* 002.001.003 */ | ||
244 | { 0x410e, "BCM43341B0" }, /* 002.001.014 */ | 250 | { 0x410e, "BCM43341B0" }, /* 002.001.014 */ |
245 | { 0x4406, "BCM4324B3" }, /* 002.004.006 */ | 251 | { 0x4406, "BCM4324B3" }, /* 002.004.006 */ |
246 | { 0x610c, "BCM4354" }, /* 003.001.012 */ | 252 | { 0x610c, "BCM4354" }, /* 003.001.012 */ |
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 828f2f8d1568..1ce4ac16c7fa 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c | |||
@@ -89,6 +89,86 @@ int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) | |||
89 | } | 89 | } |
90 | EXPORT_SYMBOL_GPL(btintel_set_bdaddr); | 90 | EXPORT_SYMBOL_GPL(btintel_set_bdaddr); |
91 | 91 | ||
92 | void btintel_hw_error(struct hci_dev *hdev, u8 code) | ||
93 | { | ||
94 | struct sk_buff *skb; | ||
95 | u8 type = 0x00; | ||
96 | |||
97 | BT_ERR("%s: Hardware error 0x%2.2x", hdev->name, code); | ||
98 | |||
99 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); | ||
100 | if (IS_ERR(skb)) { | ||
101 | BT_ERR("%s: Reset after hardware error failed (%ld)", | ||
102 | hdev->name, PTR_ERR(skb)); | ||
103 | return; | ||
104 | } | ||
105 | kfree_skb(skb); | ||
106 | |||
107 | skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT); | ||
108 | if (IS_ERR(skb)) { | ||
109 | BT_ERR("%s: Retrieving Intel exception info failed (%ld)", | ||
110 | hdev->name, PTR_ERR(skb)); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | if (skb->len != 13) { | ||
115 | BT_ERR("%s: Exception info size mismatch", hdev->name); | ||
116 | kfree_skb(skb); | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | BT_ERR("%s: Exception info %s", hdev->name, (char *)(skb->data + 1)); | ||
121 | |||
122 | kfree_skb(skb); | ||
123 | } | ||
124 | EXPORT_SYMBOL_GPL(btintel_hw_error); | ||
125 | |||
126 | void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) | ||
127 | { | ||
128 | const char *variant; | ||
129 | |||
130 | switch (ver->fw_variant) { | ||
131 | case 0x06: | ||
132 | variant = "Bootloader"; | ||
133 | break; | ||
134 | case 0x23: | ||
135 | variant = "Firmware"; | ||
136 | break; | ||
137 | default: | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | BT_INFO("%s: %s revision %u.%u build %u week %u %u", hdev->name, | ||
142 | variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f, | ||
143 | ver->fw_build_num, ver->fw_build_ww, 2000 + ver->fw_build_yy); | ||
144 | } | ||
145 | EXPORT_SYMBOL_GPL(btintel_version_info); | ||
146 | |||
147 | int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, | ||
148 | const void *param) | ||
149 | { | ||
150 | while (plen > 0) { | ||
151 | struct sk_buff *skb; | ||
152 | u8 cmd_param[253], fragment_len = (plen > 252) ? 252 : plen; | ||
153 | |||
154 | cmd_param[0] = fragment_type; | ||
155 | memcpy(cmd_param + 1, param, fragment_len); | ||
156 | |||
157 | skb = __hci_cmd_sync(hdev, 0xfc09, fragment_len + 1, | ||
158 | cmd_param, HCI_INIT_TIMEOUT); | ||
159 | if (IS_ERR(skb)) | ||
160 | return PTR_ERR(skb); | ||
161 | |||
162 | kfree_skb(skb); | ||
163 | |||
164 | plen -= fragment_len; | ||
165 | param += fragment_len; | ||
166 | } | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(btintel_secure_send); | ||
171 | |||
92 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | 172 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
93 | MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); | 173 | MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); |
94 | MODULE_VERSION(VERSION); | 174 | MODULE_VERSION(VERSION); |
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 4bda6ab34f60..b278d14758d5 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h | |||
@@ -73,6 +73,11 @@ struct intel_secure_send_result { | |||
73 | 73 | ||
74 | int btintel_check_bdaddr(struct hci_dev *hdev); | 74 | int btintel_check_bdaddr(struct hci_dev *hdev); |
75 | int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); | 75 | int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); |
76 | void btintel_hw_error(struct hci_dev *hdev, u8 code); | ||
77 | |||
78 | void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver); | ||
79 | int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, | ||
80 | const void *param); | ||
76 | 81 | ||
77 | #else | 82 | #else |
78 | 83 | ||
@@ -86,4 +91,18 @@ static inline int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdadd | |||
86 | return -EOPNOTSUPP; | 91 | return -EOPNOTSUPP; |
87 | } | 92 | } |
88 | 93 | ||
94 | static inline void btintel_hw_error(struct hci_dev *hdev, u8 code) | ||
95 | { | ||
96 | } | ||
97 | |||
98 | static void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) | ||
99 | { | ||
100 | } | ||
101 | |||
102 | static inline int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, | ||
103 | u32 plen, const void *param) | ||
104 | { | ||
105 | return -EOPNOTSUPP; | ||
106 | } | ||
107 | |||
89 | #endif | 108 | #endif |
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 086f0ec89580..27a9aac25583 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h | |||
@@ -95,10 +95,10 @@ struct btmrvl_private { | |||
95 | struct btmrvl_device btmrvl_dev; | 95 | struct btmrvl_device btmrvl_dev; |
96 | struct btmrvl_adapter *adapter; | 96 | struct btmrvl_adapter *adapter; |
97 | struct btmrvl_thread main_thread; | 97 | struct btmrvl_thread main_thread; |
98 | int (*hw_host_to_card) (struct btmrvl_private *priv, | 98 | int (*hw_host_to_card)(struct btmrvl_private *priv, |
99 | u8 *payload, u16 nb); | 99 | u8 *payload, u16 nb); |
100 | int (*hw_wakeup_firmware) (struct btmrvl_private *priv); | 100 | int (*hw_wakeup_firmware)(struct btmrvl_private *priv); |
101 | int (*hw_process_int_status) (struct btmrvl_private *priv); | 101 | int (*hw_process_int_status)(struct btmrvl_private *priv); |
102 | void (*firmware_dump)(struct btmrvl_private *priv); | 102 | void (*firmware_dump)(struct btmrvl_private *priv); |
103 | spinlock_t driver_lock; /* spinlock used by driver */ | 103 | spinlock_t driver_lock; /* spinlock used by driver */ |
104 | #ifdef CONFIG_DEBUG_FS | 104 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b4cf8d9c9dac..cc92b0f84a51 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -68,6 +68,9 @@ static const struct usb_device_id btusb_table[] = { | |||
68 | /* Generic Bluetooth AMP device */ | 68 | /* Generic Bluetooth AMP device */ |
69 | { USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP }, | 69 | { USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP }, |
70 | 70 | ||
71 | /* Generic Bluetooth USB interface */ | ||
72 | { USB_INTERFACE_INFO(0xe0, 0x01, 0x01) }, | ||
73 | |||
71 | /* Apple-specific (Broadcom) devices */ | 74 | /* Apple-specific (Broadcom) devices */ |
72 | { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01), | 75 | { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01), |
73 | .driver_info = BTUSB_BCM_APPLE }, | 76 | .driver_info = BTUSB_BCM_APPLE }, |
@@ -1878,51 +1881,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) | |||
1878 | return -EILSEQ; | 1881 | return -EILSEQ; |
1879 | } | 1882 | } |
1880 | 1883 | ||
1881 | static int btusb_intel_secure_send(struct hci_dev *hdev, u8 fragment_type, | ||
1882 | u32 plen, const void *param) | ||
1883 | { | ||
1884 | while (plen > 0) { | ||
1885 | struct sk_buff *skb; | ||
1886 | u8 cmd_param[253], fragment_len = (plen > 252) ? 252 : plen; | ||
1887 | |||
1888 | cmd_param[0] = fragment_type; | ||
1889 | memcpy(cmd_param + 1, param, fragment_len); | ||
1890 | |||
1891 | skb = __hci_cmd_sync(hdev, 0xfc09, fragment_len + 1, | ||
1892 | cmd_param, HCI_INIT_TIMEOUT); | ||
1893 | if (IS_ERR(skb)) | ||
1894 | return PTR_ERR(skb); | ||
1895 | |||
1896 | kfree_skb(skb); | ||
1897 | |||
1898 | plen -= fragment_len; | ||
1899 | param += fragment_len; | ||
1900 | } | ||
1901 | |||
1902 | return 0; | ||
1903 | } | ||
1904 | |||
1905 | static void btusb_intel_version_info(struct hci_dev *hdev, | ||
1906 | struct intel_version *ver) | ||
1907 | { | ||
1908 | const char *variant; | ||
1909 | |||
1910 | switch (ver->fw_variant) { | ||
1911 | case 0x06: | ||
1912 | variant = "Bootloader"; | ||
1913 | break; | ||
1914 | case 0x23: | ||
1915 | variant = "Firmware"; | ||
1916 | break; | ||
1917 | default: | ||
1918 | return; | ||
1919 | } | ||
1920 | |||
1921 | BT_INFO("%s: %s revision %u.%u build %u week %u %u", hdev->name, | ||
1922 | variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f, | ||
1923 | ver->fw_build_num, ver->fw_build_ww, 2000 + ver->fw_build_yy); | ||
1924 | } | ||
1925 | |||
1926 | static int btusb_setup_intel_new(struct hci_dev *hdev) | 1884 | static int btusb_setup_intel_new(struct hci_dev *hdev) |
1927 | { | 1885 | { |
1928 | static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01, | 1886 | static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01, |
@@ -1984,7 +1942,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) | |||
1984 | return -EINVAL; | 1942 | return -EINVAL; |
1985 | } | 1943 | } |
1986 | 1944 | ||
1987 | btusb_intel_version_info(hdev, ver); | 1945 | btintel_version_info(hdev, ver); |
1988 | 1946 | ||
1989 | /* The firmware variant determines if the device is in bootloader | 1947 | /* The firmware variant determines if the device is in bootloader |
1990 | * mode or is running operational firmware. The value 0x06 identifies | 1948 | * mode or is running operational firmware. The value 0x06 identifies |
@@ -2104,7 +2062,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) | |||
2104 | /* Start the firmware download transaction with the Init fragment | 2062 | /* Start the firmware download transaction with the Init fragment |
2105 | * represented by the 128 bytes of CSS header. | 2063 | * represented by the 128 bytes of CSS header. |
2106 | */ | 2064 | */ |
2107 | err = btusb_intel_secure_send(hdev, 0x00, 128, fw->data); | 2065 | err = btintel_secure_send(hdev, 0x00, 128, fw->data); |
2108 | if (err < 0) { | 2066 | if (err < 0) { |
2109 | BT_ERR("%s: Failed to send firmware header (%d)", | 2067 | BT_ERR("%s: Failed to send firmware header (%d)", |
2110 | hdev->name, err); | 2068 | hdev->name, err); |
@@ -2114,7 +2072,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) | |||
2114 | /* Send the 256 bytes of public key information from the firmware | 2072 | /* Send the 256 bytes of public key information from the firmware |
2115 | * as the PKey fragment. | 2073 | * as the PKey fragment. |
2116 | */ | 2074 | */ |
2117 | err = btusb_intel_secure_send(hdev, 0x03, 256, fw->data + 128); | 2075 | err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128); |
2118 | if (err < 0) { | 2076 | if (err < 0) { |
2119 | BT_ERR("%s: Failed to send firmware public key (%d)", | 2077 | BT_ERR("%s: Failed to send firmware public key (%d)", |
2120 | hdev->name, err); | 2078 | hdev->name, err); |
@@ -2124,7 +2082,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) | |||
2124 | /* Send the 256 bytes of signature information from the firmware | 2082 | /* Send the 256 bytes of signature information from the firmware |
2125 | * as the Sign fragment. | 2083 | * as the Sign fragment. |
2126 | */ | 2084 | */ |
2127 | err = btusb_intel_secure_send(hdev, 0x02, 256, fw->data + 388); | 2085 | err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388); |
2128 | if (err < 0) { | 2086 | if (err < 0) { |
2129 | BT_ERR("%s: Failed to send firmware signature (%d)", | 2087 | BT_ERR("%s: Failed to send firmware signature (%d)", |
2130 | hdev->name, err); | 2088 | hdev->name, err); |
@@ -2148,8 +2106,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) | |||
2148 | * firmware data buffer as a single Data fragement. | 2106 | * firmware data buffer as a single Data fragement. |
2149 | */ | 2107 | */ |
2150 | if (!(frag_len % 4)) { | 2108 | if (!(frag_len % 4)) { |
2151 | err = btusb_intel_secure_send(hdev, 0x01, frag_len, | 2109 | err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr); |
2152 | fw_ptr); | ||
2153 | if (err < 0) { | 2110 | if (err < 0) { |
2154 | BT_ERR("%s: Failed to send firmware data (%d)", | 2111 | BT_ERR("%s: Failed to send firmware data (%d)", |
2155 | hdev->name, err); | 2112 | hdev->name, err); |
@@ -2291,39 +2248,6 @@ done: | |||
2291 | return 0; | 2248 | return 0; |
2292 | } | 2249 | } |
2293 | 2250 | ||
2294 | static void btusb_hw_error_intel(struct hci_dev *hdev, u8 code) | ||
2295 | { | ||
2296 | struct sk_buff *skb; | ||
2297 | u8 type = 0x00; | ||
2298 | |||
2299 | BT_ERR("%s: Hardware error 0x%2.2x", hdev->name, code); | ||
2300 | |||
2301 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); | ||
2302 | if (IS_ERR(skb)) { | ||
2303 | BT_ERR("%s: Reset after hardware error failed (%ld)", | ||
2304 | hdev->name, PTR_ERR(skb)); | ||
2305 | return; | ||
2306 | } | ||
2307 | kfree_skb(skb); | ||
2308 | |||
2309 | skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT); | ||
2310 | if (IS_ERR(skb)) { | ||
2311 | BT_ERR("%s: Retrieving Intel exception info failed (%ld)", | ||
2312 | hdev->name, PTR_ERR(skb)); | ||
2313 | return; | ||
2314 | } | ||
2315 | |||
2316 | if (skb->len != 13) { | ||
2317 | BT_ERR("%s: Exception info size mismatch", hdev->name); | ||
2318 | kfree_skb(skb); | ||
2319 | return; | ||
2320 | } | ||
2321 | |||
2322 | BT_ERR("%s: Exception info %s", hdev->name, (char *)(skb->data + 1)); | ||
2323 | |||
2324 | kfree_skb(skb); | ||
2325 | } | ||
2326 | |||
2327 | static int btusb_shutdown_intel(struct hci_dev *hdev) | 2251 | static int btusb_shutdown_intel(struct hci_dev *hdev) |
2328 | { | 2252 | { |
2329 | struct sk_buff *skb; | 2253 | struct sk_buff *skb; |
@@ -2783,7 +2707,7 @@ static int btusb_probe(struct usb_interface *intf, | |||
2783 | if (id->driver_info & BTUSB_INTEL_NEW) { | 2707 | if (id->driver_info & BTUSB_INTEL_NEW) { |
2784 | hdev->send = btusb_send_frame_intel; | 2708 | hdev->send = btusb_send_frame_intel; |
2785 | hdev->setup = btusb_setup_intel_new; | 2709 | hdev->setup = btusb_setup_intel_new; |
2786 | hdev->hw_error = btusb_hw_error_intel; | 2710 | hdev->hw_error = btintel_hw_error; |
2787 | hdev->set_bdaddr = btintel_set_bdaddr; | 2711 | hdev->set_bdaddr = btintel_set_bdaddr; |
2788 | set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); | 2712 | set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); |
2789 | } | 2713 | } |
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 78e10f0c65b2..84135c54ed2e 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -182,9 +182,9 @@ static void dtl1_control(struct dtl1_info *info, struct sk_buff *skb) | |||
182 | int i; | 182 | int i; |
183 | 183 | ||
184 | printk(KERN_INFO "Bluetooth: Nokia control data ="); | 184 | printk(KERN_INFO "Bluetooth: Nokia control data ="); |
185 | for (i = 0; i < skb->len; i++) { | 185 | for (i = 0; i < skb->len; i++) |
186 | printk(" %02x", skb->data[i]); | 186 | printk(" %02x", skb->data[i]); |
187 | } | 187 | |
188 | printk("\n"); | 188 | printk("\n"); |
189 | 189 | ||
190 | /* transition to active state */ | 190 | /* transition to active state */ |
@@ -406,7 +406,7 @@ static int dtl1_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
406 | break; | 406 | break; |
407 | default: | 407 | default: |
408 | return -EILSEQ; | 408 | return -EILSEQ; |
409 | }; | 409 | } |
410 | 410 | ||
411 | nsh.zero = 0; | 411 | nsh.zero = 0; |
412 | nsh.len = skb->len; | 412 | nsh.len = skb->len; |
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index 3455cecc9ecf..b35b238a0380 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c | |||
@@ -75,7 +75,7 @@ struct h5 { | |||
75 | size_t rx_pending; /* Expecting more bytes */ | 75 | size_t rx_pending; /* Expecting more bytes */ |
76 | u8 rx_ack; /* Last ack number received */ | 76 | u8 rx_ack; /* Last ack number received */ |
77 | 77 | ||
78 | int (*rx_func) (struct hci_uart *hu, u8 c); | 78 | int (*rx_func)(struct hci_uart *hu, u8 c); |
79 | 79 | ||
80 | struct timer_list timer; /* Retransmission timer */ | 80 | struct timer_list timer; /* Retransmission timer */ |
81 | 81 | ||
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index 5dd07bf05236..21dfa89751df 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c | |||
@@ -24,8 +24,569 @@ | |||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/skbuff.h> | 26 | #include <linux/skbuff.h> |
27 | #include <linux/firmware.h> | ||
28 | #include <linux/wait.h> | ||
27 | 29 | ||
28 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
29 | #include <net/bluetooth/hci_core.h> | 31 | #include <net/bluetooth/hci_core.h> |
30 | 32 | ||
31 | #include "hci_uart.h" | 33 | #include "hci_uart.h" |
34 | #include "btintel.h" | ||
35 | |||
36 | #define STATE_BOOTLOADER 0 | ||
37 | #define STATE_DOWNLOADING 1 | ||
38 | #define STATE_FIRMWARE_LOADED 2 | ||
39 | #define STATE_FIRMWARE_FAILED 3 | ||
40 | #define STATE_BOOTING 4 | ||
41 | |||
42 | struct intel_data { | ||
43 | struct sk_buff *rx_skb; | ||
44 | struct sk_buff_head txq; | ||
45 | unsigned long flags; | ||
46 | }; | ||
47 | |||
48 | static int intel_open(struct hci_uart *hu) | ||
49 | { | ||
50 | struct intel_data *intel; | ||
51 | |||
52 | BT_DBG("hu %p", hu); | ||
53 | |||
54 | intel = kzalloc(sizeof(*intel), GFP_KERNEL); | ||
55 | if (!intel) | ||
56 | return -ENOMEM; | ||
57 | |||
58 | skb_queue_head_init(&intel->txq); | ||
59 | |||
60 | hu->priv = intel; | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static int intel_close(struct hci_uart *hu) | ||
65 | { | ||
66 | struct intel_data *intel = hu->priv; | ||
67 | |||
68 | BT_DBG("hu %p", hu); | ||
69 | |||
70 | skb_queue_purge(&intel->txq); | ||
71 | kfree_skb(intel->rx_skb); | ||
72 | kfree(intel); | ||
73 | |||
74 | hu->priv = NULL; | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int intel_flush(struct hci_uart *hu) | ||
79 | { | ||
80 | struct intel_data *intel = hu->priv; | ||
81 | |||
82 | BT_DBG("hu %p", hu); | ||
83 | |||
84 | skb_queue_purge(&intel->txq); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode) | ||
90 | { | ||
91 | struct sk_buff *skb; | ||
92 | struct hci_event_hdr *hdr; | ||
93 | struct hci_ev_cmd_complete *evt; | ||
94 | |||
95 | skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_ATOMIC); | ||
96 | if (!skb) | ||
97 | return -ENOMEM; | ||
98 | |||
99 | hdr = (struct hci_event_hdr *)skb_put(skb, sizeof(*hdr)); | ||
100 | hdr->evt = HCI_EV_CMD_COMPLETE; | ||
101 | hdr->plen = sizeof(*evt) + 1; | ||
102 | |||
103 | evt = (struct hci_ev_cmd_complete *)skb_put(skb, sizeof(*evt)); | ||
104 | evt->ncmd = 0x01; | ||
105 | evt->opcode = cpu_to_le16(opcode); | ||
106 | |||
107 | *skb_put(skb, 1) = 0x00; | ||
108 | |||
109 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; | ||
110 | |||
111 | return hci_recv_frame(hdev, skb); | ||
112 | } | ||
113 | |||
114 | static int intel_setup(struct hci_uart *hu) | ||
115 | { | ||
116 | static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01, | ||
117 | 0x00, 0x08, 0x04, 0x00 }; | ||
118 | struct intel_data *intel = hu->priv; | ||
119 | struct hci_dev *hdev = hu->hdev; | ||
120 | struct sk_buff *skb; | ||
121 | struct intel_version *ver; | ||
122 | struct intel_boot_params *params; | ||
123 | const struct firmware *fw; | ||
124 | const u8 *fw_ptr; | ||
125 | char fwname[64]; | ||
126 | u32 frag_len; | ||
127 | ktime_t calltime, delta, rettime; | ||
128 | unsigned long long duration; | ||
129 | int err; | ||
130 | |||
131 | BT_DBG("%s", hdev->name); | ||
132 | |||
133 | hu->hdev->set_bdaddr = btintel_set_bdaddr; | ||
134 | |||
135 | calltime = ktime_get(); | ||
136 | |||
137 | set_bit(STATE_BOOTLOADER, &intel->flags); | ||
138 | |||
139 | /* Read the Intel version information to determine if the device | ||
140 | * is in bootloader mode or if it already has operational firmware | ||
141 | * loaded. | ||
142 | */ | ||
143 | skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); | ||
144 | if (IS_ERR(skb)) { | ||
145 | BT_ERR("%s: Reading Intel version information failed (%ld)", | ||
146 | hdev->name, PTR_ERR(skb)); | ||
147 | return PTR_ERR(skb); | ||
148 | } | ||
149 | |||
150 | if (skb->len != sizeof(*ver)) { | ||
151 | BT_ERR("%s: Intel version event size mismatch", hdev->name); | ||
152 | kfree_skb(skb); | ||
153 | return -EILSEQ; | ||
154 | } | ||
155 | |||
156 | ver = (struct intel_version *)skb->data; | ||
157 | if (ver->status) { | ||
158 | BT_ERR("%s: Intel version command failure (%02x)", | ||
159 | hdev->name, ver->status); | ||
160 | err = -bt_to_errno(ver->status); | ||
161 | kfree_skb(skb); | ||
162 | return err; | ||
163 | } | ||
164 | |||
165 | /* The hardware platform number has a fixed value of 0x37 and | ||
166 | * for now only accept this single value. | ||
167 | */ | ||
168 | if (ver->hw_platform != 0x37) { | ||
169 | BT_ERR("%s: Unsupported Intel hardware platform (%u)", | ||
170 | hdev->name, ver->hw_platform); | ||
171 | kfree_skb(skb); | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | |||
175 | /* At the moment only the hardware variant iBT 3.0 (LnP/SfP) is | ||
176 | * supported by this firmware loading method. This check has been | ||
177 | * put in place to ensure correct forward compatibility options | ||
178 | * when newer hardware variants come along. | ||
179 | */ | ||
180 | if (ver->hw_variant != 0x0b) { | ||
181 | BT_ERR("%s: Unsupported Intel hardware variant (%u)", | ||
182 | hdev->name, ver->hw_variant); | ||
183 | kfree_skb(skb); | ||
184 | return -EINVAL; | ||
185 | } | ||
186 | |||
187 | btintel_version_info(hdev, ver); | ||
188 | |||
189 | /* The firmware variant determines if the device is in bootloader | ||
190 | * mode or is running operational firmware. The value 0x06 identifies | ||
191 | * the bootloader and the value 0x23 identifies the operational | ||
192 | * firmware. | ||
193 | * | ||
194 | * When the operational firmware is already present, then only | ||
195 | * the check for valid Bluetooth device address is needed. This | ||
196 | * determines if the device will be added as configured or | ||
197 | * unconfigured controller. | ||
198 | * | ||
199 | * It is not possible to use the Secure Boot Parameters in this | ||
200 | * case since that command is only available in bootloader mode. | ||
201 | */ | ||
202 | if (ver->fw_variant == 0x23) { | ||
203 | kfree_skb(skb); | ||
204 | clear_bit(STATE_BOOTLOADER, &intel->flags); | ||
205 | btintel_check_bdaddr(hdev); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /* If the device is not in bootloader mode, then the only possible | ||
210 | * choice is to return an error and abort the device initialization. | ||
211 | */ | ||
212 | if (ver->fw_variant != 0x06) { | ||
213 | BT_ERR("%s: Unsupported Intel firmware variant (%u)", | ||
214 | hdev->name, ver->fw_variant); | ||
215 | kfree_skb(skb); | ||
216 | return -ENODEV; | ||
217 | } | ||
218 | |||
219 | kfree_skb(skb); | ||
220 | |||
221 | /* Read the secure boot parameters to identify the operating | ||
222 | * details of the bootloader. | ||
223 | */ | ||
224 | skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT); | ||
225 | if (IS_ERR(skb)) { | ||
226 | BT_ERR("%s: Reading Intel boot parameters failed (%ld)", | ||
227 | hdev->name, PTR_ERR(skb)); | ||
228 | return PTR_ERR(skb); | ||
229 | } | ||
230 | |||
231 | if (skb->len != sizeof(*params)) { | ||
232 | BT_ERR("%s: Intel boot parameters size mismatch", hdev->name); | ||
233 | kfree_skb(skb); | ||
234 | return -EILSEQ; | ||
235 | } | ||
236 | |||
237 | params = (struct intel_boot_params *)skb->data; | ||
238 | if (params->status) { | ||
239 | BT_ERR("%s: Intel boot parameters command failure (%02x)", | ||
240 | hdev->name, params->status); | ||
241 | err = -bt_to_errno(params->status); | ||
242 | kfree_skb(skb); | ||
243 | return err; | ||
244 | } | ||
245 | |||
246 | BT_INFO("%s: Device revision is %u", hdev->name, | ||
247 | le16_to_cpu(params->dev_revid)); | ||
248 | |||
249 | BT_INFO("%s: Secure boot is %s", hdev->name, | ||
250 | params->secure_boot ? "enabled" : "disabled"); | ||
251 | |||
252 | BT_INFO("%s: Minimum firmware build %u week %u %u", hdev->name, | ||
253 | params->min_fw_build_nn, params->min_fw_build_cw, | ||
254 | 2000 + params->min_fw_build_yy); | ||
255 | |||
256 | /* It is required that every single firmware fragment is acknowledged | ||
257 | * with a command complete event. If the boot parameters indicate | ||
258 | * that this bootloader does not send them, then abort the setup. | ||
259 | */ | ||
260 | if (params->limited_cce != 0x00) { | ||
261 | BT_ERR("%s: Unsupported Intel firmware loading method (%u)", | ||
262 | hdev->name, params->limited_cce); | ||
263 | kfree_skb(skb); | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | |||
267 | /* If the OTP has no valid Bluetooth device address, then there will | ||
268 | * also be no valid address for the operational firmware. | ||
269 | */ | ||
270 | if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { | ||
271 | BT_INFO("%s: No device address configured", hdev->name); | ||
272 | set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); | ||
273 | } | ||
274 | |||
275 | /* With this Intel bootloader only the hardware variant and device | ||
276 | * revision information are used to select the right firmware. | ||
277 | * | ||
278 | * Currently this bootloader support is limited to hardware variant | ||
279 | * iBT 3.0 (LnP/SfP) which is identified by the value 11 (0x0b). | ||
280 | */ | ||
281 | snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.sfi", | ||
282 | le16_to_cpu(params->dev_revid)); | ||
283 | |||
284 | err = request_firmware(&fw, fwname, &hdev->dev); | ||
285 | if (err < 0) { | ||
286 | BT_ERR("%s: Failed to load Intel firmware file (%d)", | ||
287 | hdev->name, err); | ||
288 | kfree_skb(skb); | ||
289 | return err; | ||
290 | } | ||
291 | |||
292 | BT_INFO("%s: Found device firmware: %s", hdev->name, fwname); | ||
293 | |||
294 | kfree_skb(skb); | ||
295 | |||
296 | if (fw->size < 644) { | ||
297 | BT_ERR("%s: Invalid size of firmware file (%zu)", | ||
298 | hdev->name, fw->size); | ||
299 | err = -EBADF; | ||
300 | goto done; | ||
301 | } | ||
302 | |||
303 | set_bit(STATE_DOWNLOADING, &intel->flags); | ||
304 | |||
305 | /* Start the firmware download transaction with the Init fragment | ||
306 | * represented by the 128 bytes of CSS header. | ||
307 | */ | ||
308 | err = btintel_secure_send(hdev, 0x00, 128, fw->data); | ||
309 | if (err < 0) { | ||
310 | BT_ERR("%s: Failed to send firmware header (%d)", | ||
311 | hdev->name, err); | ||
312 | goto done; | ||
313 | } | ||
314 | |||
315 | /* Send the 256 bytes of public key information from the firmware | ||
316 | * as the PKey fragment. | ||
317 | */ | ||
318 | err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128); | ||
319 | if (err < 0) { | ||
320 | BT_ERR("%s: Failed to send firmware public key (%d)", | ||
321 | hdev->name, err); | ||
322 | goto done; | ||
323 | } | ||
324 | |||
325 | /* Send the 256 bytes of signature information from the firmware | ||
326 | * as the Sign fragment. | ||
327 | */ | ||
328 | err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388); | ||
329 | if (err < 0) { | ||
330 | BT_ERR("%s: Failed to send firmware signature (%d)", | ||
331 | hdev->name, err); | ||
332 | goto done; | ||
333 | } | ||
334 | |||
335 | fw_ptr = fw->data + 644; | ||
336 | frag_len = 0; | ||
337 | |||
338 | while (fw_ptr - fw->data < fw->size) { | ||
339 | struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); | ||
340 | |||
341 | frag_len += sizeof(*cmd) + cmd->plen; | ||
342 | |||
343 | BT_DBG("%s: patching %td/%zu", hdev->name, | ||
344 | (fw_ptr - fw->data), fw->size); | ||
345 | |||
346 | /* The parameter length of the secure send command requires | ||
347 | * a 4 byte alignment. It happens so that the firmware file | ||
348 | * contains proper Intel_NOP commands to align the fragments | ||
349 | * as needed. | ||
350 | * | ||
351 | * Send set of commands with 4 byte alignment from the | ||
352 | * firmware data buffer as a single Data fragement. | ||
353 | */ | ||
354 | if (frag_len % 4) | ||
355 | continue; | ||
356 | |||
357 | /* Send each command from the firmware data buffer as | ||
358 | * a single Data fragment. | ||
359 | */ | ||
360 | err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr); | ||
361 | if (err < 0) { | ||
362 | BT_ERR("%s: Failed to send firmware data (%d)", | ||
363 | hdev->name, err); | ||
364 | goto done; | ||
365 | } | ||
366 | |||
367 | fw_ptr += frag_len; | ||
368 | frag_len = 0; | ||
369 | } | ||
370 | |||
371 | set_bit(STATE_FIRMWARE_LOADED, &intel->flags); | ||
372 | |||
373 | BT_INFO("%s: Waiting for firmware download to complete", hdev->name); | ||
374 | |||
375 | /* Before switching the device into operational mode and with that | ||
376 | * booting the loaded firmware, wait for the bootloader notification | ||
377 | * that all fragments have been successfully received. | ||
378 | * | ||
379 | * When the event processing receives the notification, then the | ||
380 | * STATE_DOWNLOADING flag will be cleared. | ||
381 | * | ||
382 | * The firmware loading should not take longer than 5 seconds | ||
383 | * and thus just timeout if that happens and fail the setup | ||
384 | * of this device. | ||
385 | */ | ||
386 | err = wait_on_bit_timeout(&intel->flags, STATE_DOWNLOADING, | ||
387 | TASK_INTERRUPTIBLE, | ||
388 | msecs_to_jiffies(5000)); | ||
389 | if (err == 1) { | ||
390 | BT_ERR("%s: Firmware loading interrupted", hdev->name); | ||
391 | err = -EINTR; | ||
392 | goto done; | ||
393 | } | ||
394 | |||
395 | if (err) { | ||
396 | BT_ERR("%s: Firmware loading timeout", hdev->name); | ||
397 | err = -ETIMEDOUT; | ||
398 | goto done; | ||
399 | } | ||
400 | |||
401 | if (test_bit(STATE_FIRMWARE_FAILED, &intel->flags)) { | ||
402 | BT_ERR("%s: Firmware loading failed", hdev->name); | ||
403 | err = -ENOEXEC; | ||
404 | goto done; | ||
405 | } | ||
406 | |||
407 | rettime = ktime_get(); | ||
408 | delta = ktime_sub(rettime, calltime); | ||
409 | duration = (unsigned long long) ktime_to_ns(delta) >> 10; | ||
410 | |||
411 | BT_INFO("%s: Firmware loaded in %llu usecs", hdev->name, duration); | ||
412 | |||
413 | done: | ||
414 | release_firmware(fw); | ||
415 | |||
416 | if (err < 0) | ||
417 | return err; | ||
418 | |||
419 | calltime = ktime_get(); | ||
420 | |||
421 | set_bit(STATE_BOOTING, &intel->flags); | ||
422 | |||
423 | skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param, | ||
424 | HCI_INIT_TIMEOUT); | ||
425 | if (IS_ERR(skb)) | ||
426 | return PTR_ERR(skb); | ||
427 | |||
428 | kfree_skb(skb); | ||
429 | |||
430 | /* The bootloader will not indicate when the device is ready. This | ||
431 | * is done by the operational firmware sending bootup notification. | ||
432 | * | ||
433 | * Booting into operational firmware should not take longer than | ||
434 | * 1 second. However if that happens, then just fail the setup | ||
435 | * since something went wrong. | ||
436 | */ | ||
437 | BT_INFO("%s: Waiting for device to boot", hdev->name); | ||
438 | |||
439 | err = wait_on_bit_timeout(&intel->flags, STATE_BOOTING, | ||
440 | TASK_INTERRUPTIBLE, | ||
441 | msecs_to_jiffies(1000)); | ||
442 | |||
443 | if (err == 1) { | ||
444 | BT_ERR("%s: Device boot interrupted", hdev->name); | ||
445 | return -EINTR; | ||
446 | } | ||
447 | |||
448 | if (err) { | ||
449 | BT_ERR("%s: Device boot timeout", hdev->name); | ||
450 | return -ETIMEDOUT; | ||
451 | } | ||
452 | |||
453 | rettime = ktime_get(); | ||
454 | delta = ktime_sub(rettime, calltime); | ||
455 | duration = (unsigned long long) ktime_to_ns(delta) >> 10; | ||
456 | |||
457 | BT_INFO("%s: Device booted in %llu usecs", hdev->name, duration); | ||
458 | |||
459 | clear_bit(STATE_BOOTLOADER, &intel->flags); | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static int intel_recv_event(struct hci_dev *hdev, struct sk_buff *skb) | ||
465 | { | ||
466 | struct hci_uart *hu = hci_get_drvdata(hdev); | ||
467 | struct intel_data *intel = hu->priv; | ||
468 | struct hci_event_hdr *hdr; | ||
469 | |||
470 | if (!test_bit(STATE_BOOTLOADER, &intel->flags)) | ||
471 | goto recv; | ||
472 | |||
473 | hdr = (void *)skb->data; | ||
474 | |||
475 | /* When the firmware loading completes the device sends | ||
476 | * out a vendor specific event indicating the result of | ||
477 | * the firmware loading. | ||
478 | */ | ||
479 | if (skb->len == 7 && hdr->evt == 0xff && hdr->plen == 0x05 && | ||
480 | skb->data[2] == 0x06) { | ||
481 | if (skb->data[3] != 0x00) | ||
482 | set_bit(STATE_FIRMWARE_FAILED, &intel->flags); | ||
483 | |||
484 | if (test_and_clear_bit(STATE_DOWNLOADING, &intel->flags) && | ||
485 | test_bit(STATE_FIRMWARE_LOADED, &intel->flags)) { | ||
486 | smp_mb__after_atomic(); | ||
487 | wake_up_bit(&intel->flags, STATE_DOWNLOADING); | ||
488 | } | ||
489 | |||
490 | /* When switching to the operational firmware the device | ||
491 | * sends a vendor specific event indicating that the bootup | ||
492 | * completed. | ||
493 | */ | ||
494 | } else if (skb->len == 9 && hdr->evt == 0xff && hdr->plen == 0x07 && | ||
495 | skb->data[2] == 0x02) { | ||
496 | if (test_and_clear_bit(STATE_BOOTING, &intel->flags)) { | ||
497 | smp_mb__after_atomic(); | ||
498 | wake_up_bit(&intel->flags, STATE_BOOTING); | ||
499 | } | ||
500 | } | ||
501 | recv: | ||
502 | return hci_recv_frame(hdev, skb); | ||
503 | } | ||
504 | |||
505 | static const struct h4_recv_pkt intel_recv_pkts[] = { | ||
506 | { H4_RECV_ACL, .recv = hci_recv_frame }, | ||
507 | { H4_RECV_SCO, .recv = hci_recv_frame }, | ||
508 | { H4_RECV_EVENT, .recv = intel_recv_event }, | ||
509 | }; | ||
510 | |||
511 | static int intel_recv(struct hci_uart *hu, const void *data, int count) | ||
512 | { | ||
513 | struct intel_data *intel = hu->priv; | ||
514 | |||
515 | if (!test_bit(HCI_UART_REGISTERED, &hu->flags)) | ||
516 | return -EUNATCH; | ||
517 | |||
518 | intel->rx_skb = h4_recv_buf(hu->hdev, intel->rx_skb, data, count, | ||
519 | intel_recv_pkts, | ||
520 | ARRAY_SIZE(intel_recv_pkts)); | ||
521 | if (IS_ERR(intel->rx_skb)) { | ||
522 | int err = PTR_ERR(intel->rx_skb); | ||
523 | BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err); | ||
524 | intel->rx_skb = NULL; | ||
525 | return err; | ||
526 | } | ||
527 | |||
528 | return count; | ||
529 | } | ||
530 | |||
531 | static int intel_enqueue(struct hci_uart *hu, struct sk_buff *skb) | ||
532 | { | ||
533 | struct intel_data *intel = hu->priv; | ||
534 | |||
535 | BT_DBG("hu %p skb %p", hu, skb); | ||
536 | |||
537 | skb_queue_tail(&intel->txq, skb); | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static struct sk_buff *intel_dequeue(struct hci_uart *hu) | ||
543 | { | ||
544 | struct intel_data *intel = hu->priv; | ||
545 | struct sk_buff *skb; | ||
546 | |||
547 | skb = skb_dequeue(&intel->txq); | ||
548 | if (!skb) | ||
549 | return skb; | ||
550 | |||
551 | if (test_bit(STATE_BOOTLOADER, &intel->flags) && | ||
552 | (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT)) { | ||
553 | struct hci_command_hdr *cmd = (void *)skb->data; | ||
554 | __u16 opcode = le16_to_cpu(cmd->opcode); | ||
555 | |||
556 | /* When the 0xfc01 command is issued to boot into | ||
557 | * the operational firmware, it will actually not | ||
558 | * send a command complete event. To keep the flow | ||
559 | * control working inject that event here. | ||
560 | */ | ||
561 | if (opcode == 0xfc01) | ||
562 | inject_cmd_complete(hu->hdev, opcode); | ||
563 | } | ||
564 | |||
565 | /* Prepend skb with frame type */ | ||
566 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); | ||
567 | |||
568 | return skb; | ||
569 | } | ||
570 | |||
571 | static const struct hci_uart_proto intel_proto = { | ||
572 | .id = HCI_UART_INTEL, | ||
573 | .name = "Intel", | ||
574 | .init_speed = 115200, | ||
575 | .open = intel_open, | ||
576 | .close = intel_close, | ||
577 | .flush = intel_flush, | ||
578 | .setup = intel_setup, | ||
579 | .recv = intel_recv, | ||
580 | .enqueue = intel_enqueue, | ||
581 | .dequeue = intel_dequeue, | ||
582 | }; | ||
583 | |||
584 | int __init intel_init(void) | ||
585 | { | ||
586 | return hci_uart_register_proto(&intel_proto); | ||
587 | } | ||
588 | |||
589 | int __exit intel_deinit(void) | ||
590 | { | ||
591 | return hci_uart_unregister_proto(&intel_proto); | ||
592 | } | ||
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 177dd69fdd95..20c2ac193ff9 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -770,7 +770,7 @@ static int __init hci_uart_init(void) | |||
770 | 770 | ||
771 | /* Register the tty discipline */ | 771 | /* Register the tty discipline */ |
772 | 772 | ||
773 | memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc)); | 773 | memset(&hci_uart_ldisc, 0, sizeof(hci_uart_ldisc)); |
774 | hci_uart_ldisc.magic = TTY_LDISC_MAGIC; | 774 | hci_uart_ldisc.magic = TTY_LDISC_MAGIC; |
775 | hci_uart_ldisc.name = "n_hci"; | 775 | hci_uart_ldisc.name = "n_hci"; |
776 | hci_uart_ldisc.open = hci_uart_tty_open; | 776 | hci_uart_ldisc.open = hci_uart_tty_open; |
@@ -804,6 +804,9 @@ static int __init hci_uart_init(void) | |||
804 | #ifdef CONFIG_BT_HCIUART_3WIRE | 804 | #ifdef CONFIG_BT_HCIUART_3WIRE |
805 | h5_init(); | 805 | h5_init(); |
806 | #endif | 806 | #endif |
807 | #ifdef CONFIG_BT_HCIUART_INTEL | ||
808 | intel_init(); | ||
809 | #endif | ||
807 | #ifdef CONFIG_BT_HCIUART_BCM | 810 | #ifdef CONFIG_BT_HCIUART_BCM |
808 | bcm_init(); | 811 | bcm_init(); |
809 | #endif | 812 | #endif |
@@ -830,6 +833,9 @@ static void __exit hci_uart_exit(void) | |||
830 | #ifdef CONFIG_BT_HCIUART_3WIRE | 833 | #ifdef CONFIG_BT_HCIUART_3WIRE |
831 | h5_deinit(); | 834 | h5_deinit(); |
832 | #endif | 835 | #endif |
836 | #ifdef CONFIG_BT_HCIUART_INTEL | ||
837 | intel_deinit(); | ||
838 | #endif | ||
833 | #ifdef CONFIG_BT_HCIUART_BCM | 839 | #ifdef CONFIG_BT_HCIUART_BCM |
834 | bcm_deinit(); | 840 | bcm_deinit(); |
835 | #endif | 841 | #endif |
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index ce9c670956f5..496587a73a9d 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h | |||
@@ -167,6 +167,11 @@ int h5_init(void); | |||
167 | int h5_deinit(void); | 167 | int h5_deinit(void); |
168 | #endif | 168 | #endif |
169 | 169 | ||
170 | #ifdef CONFIG_BT_HCIUART_INTEL | ||
171 | int intel_init(void); | ||
172 | int intel_deinit(void); | ||
173 | #endif | ||
174 | |||
170 | #ifdef CONFIG_BT_HCIUART_BCM | 175 | #ifdef CONFIG_BT_HCIUART_BCM |
171 | int bcm_init(void); | 176 | int bcm_init(void); |
172 | int bcm_deinit(void); | 177 | int bcm_deinit(void); |
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index f7bd9f3ddaac..d0d5bf6cbb68 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c | |||
@@ -545,7 +545,9 @@ at86rf230_async_state_delay(void *context) | |||
545 | } | 545 | } |
546 | 546 | ||
547 | /* Default delay is 1us in the most cases */ | 547 | /* Default delay is 1us in the most cases */ |
548 | tim = ktime_set(0, NSEC_PER_USEC); | 548 | udelay(1); |
549 | at86rf230_async_state_timer(&ctx->timer); | ||
550 | return; | ||
549 | 551 | ||
550 | change: | 552 | change: |
551 | hrtimer_start(&ctx->timer, tim, HRTIMER_MODE_REL); | 553 | hrtimer_start(&ctx->timer, tim, HRTIMER_MODE_REL); |
diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index b6fc29579667..613dae559925 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c | |||
@@ -1151,7 +1151,6 @@ MODULE_DEVICE_TABLE(of, cc2520_of_ids); | |||
1151 | static struct spi_driver cc2520_driver = { | 1151 | static struct spi_driver cc2520_driver = { |
1152 | .driver = { | 1152 | .driver = { |
1153 | .name = "cc2520", | 1153 | .name = "cc2520", |
1154 | .bus = &spi_bus_type, | ||
1155 | .owner = THIS_MODULE, | 1154 | .owner = THIS_MODULE, |
1156 | .of_match_table = of_match_ptr(cc2520_of_ids), | 1155 | .of_match_table = of_match_ptr(cc2520_of_ids), |
1157 | }, | 1156 | }, |
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 2549760e039f..997724b8e434 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c | |||
@@ -812,7 +812,6 @@ MODULE_DEVICE_TABLE(spi, mrf24j40_ids); | |||
812 | static struct spi_driver mrf24j40_driver = { | 812 | static struct spi_driver mrf24j40_driver = { |
813 | .driver = { | 813 | .driver = { |
814 | .name = "mrf24j40", | 814 | .name = "mrf24j40", |
815 | .bus = &spi_bus_type, | ||
816 | .owner = THIS_MODULE, | 815 | .owner = THIS_MODULE, |
817 | }, | 816 | }, |
818 | .id_table = mrf24j40_ids, | 817 | .id_table = mrf24j40_ids, |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3bd618d3e55d..2a6b0919e23f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -1297,7 +1297,7 @@ static inline int hci_check_conn_params(u16 min, u16 max, u16 latency, | |||
1297 | if (max >= to_multiplier * 8) | 1297 | if (max >= to_multiplier * 8) |
1298 | return -EINVAL; | 1298 | return -EINVAL; |
1299 | 1299 | ||
1300 | max_latency = (to_multiplier * 8 / max) - 1; | 1300 | max_latency = (to_multiplier * 4 / max) - 1; |
1301 | if (latency > 499 || latency > max_latency) | 1301 | if (latency > 499 || latency > max_latency) |
1302 | return -EINVAL; | 1302 | return -EINVAL; |
1303 | 1303 | ||
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 2239a3753092..c98afc08cc26 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -55,6 +55,8 @@ | |||
55 | #define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000) | 55 | #define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000) |
56 | #define L2CAP_MOVE_TIMEOUT msecs_to_jiffies(4000) | 56 | #define L2CAP_MOVE_TIMEOUT msecs_to_jiffies(4000) |
57 | #define L2CAP_MOVE_ERTX_TIMEOUT msecs_to_jiffies(60000) | 57 | #define L2CAP_MOVE_ERTX_TIMEOUT msecs_to_jiffies(60000) |
58 | #define L2CAP_WAIT_ACK_POLL_PERIOD msecs_to_jiffies(200) | ||
59 | #define L2CAP_WAIT_ACK_TIMEOUT msecs_to_jiffies(10000) | ||
58 | 60 | ||
59 | #define L2CAP_A2MP_DEFAULT_MTU 670 | 61 | #define L2CAP_A2MP_DEFAULT_MTU 670 |
60 | 62 | ||
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 290a9a69af07..382f94b59f2f 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h | |||
@@ -34,6 +34,8 @@ struct cfg802154_ops { | |||
34 | int type); | 34 | int type); |
35 | void (*del_virtual_intf_deprecated)(struct wpan_phy *wpan_phy, | 35 | void (*del_virtual_intf_deprecated)(struct wpan_phy *wpan_phy, |
36 | struct net_device *dev); | 36 | struct net_device *dev); |
37 | int (*suspend)(struct wpan_phy *wpan_phy); | ||
38 | int (*resume)(struct wpan_phy *wpan_phy); | ||
37 | int (*add_virtual_intf)(struct wpan_phy *wpan_phy, | 39 | int (*add_virtual_intf)(struct wpan_phy *wpan_phy, |
38 | const char *name, | 40 | const char *name, |
39 | unsigned char name_assign_type, | 41 | unsigned char name_assign_type, |
diff --git a/include/net/mac802154.h b/include/net/mac802154.h index f534a46911dc..b7f99615224b 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h | |||
@@ -321,23 +321,6 @@ int ieee802154_register_hw(struct ieee802154_hw *hw); | |||
321 | void ieee802154_unregister_hw(struct ieee802154_hw *hw); | 321 | void ieee802154_unregister_hw(struct ieee802154_hw *hw); |
322 | 322 | ||
323 | /** | 323 | /** |
324 | * ieee802154_rx - receive frame | ||
325 | * | ||
326 | * Use this function to hand received frames to mac802154. The receive | ||
327 | * buffer in @skb must start with an IEEE 802.15.4 header. In case of a | ||
328 | * paged @skb is used, the driver is recommended to put the ieee802154 | ||
329 | * header of the frame on the linear part of the @skb to avoid memory | ||
330 | * allocation and/or memcpy by the stack. | ||
331 | * | ||
332 | * This function may not be called in IRQ context. Calls to this function | ||
333 | * for a single hardware must be synchronized against each other. | ||
334 | * | ||
335 | * @hw: the hardware this frame came in on | ||
336 | * @skb: the buffer to receive, owned by mac802154 after this call | ||
337 | */ | ||
338 | void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb); | ||
339 | |||
340 | /** | ||
341 | * ieee802154_rx_irqsafe - receive frame | 324 | * ieee802154_rx_irqsafe - receive frame |
342 | * | 325 | * |
343 | * Like ieee802154_rx() but can be called in IRQ context | 326 | * Like ieee802154_rx() but can be called in IRQ context |
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 94a375c04f21..9055d7b9d112 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c | |||
@@ -613,6 +613,8 @@ EXPORT_SYMBOL_GPL(lowpan_header_compress); | |||
613 | 613 | ||
614 | static int __init lowpan_module_init(void) | 614 | static int __init lowpan_module_init(void) |
615 | { | 615 | { |
616 | request_module_nowait("ipv6"); | ||
617 | |||
616 | request_module_nowait("nhc_dest"); | 618 | request_module_nowait("nhc_dest"); |
617 | request_module_nowait("nhc_fragment"); | 619 | request_module_nowait("nhc_fragment"); |
618 | request_module_nowait("nhc_hop"); | 620 | request_module_nowait("nhc_hop"); |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 2fb7b3064904..0ffe2e24020a 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
@@ -859,9 +859,22 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev) | |||
859 | SET_NETDEV_DEV(netdev, &chan->conn->hcon->hdev->dev); | 859 | SET_NETDEV_DEV(netdev, &chan->conn->hcon->hdev->dev); |
860 | SET_NETDEV_DEVTYPE(netdev, &bt_type); | 860 | SET_NETDEV_DEVTYPE(netdev, &bt_type); |
861 | 861 | ||
862 | *dev = netdev_priv(netdev); | ||
863 | (*dev)->netdev = netdev; | ||
864 | (*dev)->hdev = chan->conn->hcon->hdev; | ||
865 | INIT_LIST_HEAD(&(*dev)->peers); | ||
866 | |||
867 | spin_lock(&devices_lock); | ||
868 | INIT_LIST_HEAD(&(*dev)->list); | ||
869 | list_add_rcu(&(*dev)->list, &bt_6lowpan_devices); | ||
870 | spin_unlock(&devices_lock); | ||
871 | |||
862 | err = register_netdev(netdev); | 872 | err = register_netdev(netdev); |
863 | if (err < 0) { | 873 | if (err < 0) { |
864 | BT_INFO("register_netdev failed %d", err); | 874 | BT_INFO("register_netdev failed %d", err); |
875 | spin_lock(&devices_lock); | ||
876 | list_del_rcu(&(*dev)->list); | ||
877 | spin_unlock(&devices_lock); | ||
865 | free_netdev(netdev); | 878 | free_netdev(netdev); |
866 | goto out; | 879 | goto out; |
867 | } | 880 | } |
@@ -871,16 +884,6 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev) | |||
871 | &chan->src, chan->src_type); | 884 | &chan->src, chan->src_type); |
872 | set_bit(__LINK_STATE_PRESENT, &netdev->state); | 885 | set_bit(__LINK_STATE_PRESENT, &netdev->state); |
873 | 886 | ||
874 | *dev = netdev_priv(netdev); | ||
875 | (*dev)->netdev = netdev; | ||
876 | (*dev)->hdev = chan->conn->hcon->hdev; | ||
877 | INIT_LIST_HEAD(&(*dev)->peers); | ||
878 | |||
879 | spin_lock(&devices_lock); | ||
880 | INIT_LIST_HEAD(&(*dev)->list); | ||
881 | list_add_rcu(&(*dev)->list, &bt_6lowpan_devices); | ||
882 | spin_unlock(&devices_lock); | ||
883 | |||
884 | return 0; | 887 | return 0; |
885 | 888 | ||
886 | out: | 889 | out: |
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index b8c794b87523..95d1a66ba03a 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -53,6 +53,11 @@ source "net/bluetooth/cmtp/Kconfig" | |||
53 | 53 | ||
54 | source "net/bluetooth/hidp/Kconfig" | 54 | source "net/bluetooth/hidp/Kconfig" |
55 | 55 | ||
56 | config BT_HS | ||
57 | bool "Bluetooth High Speed (HS) features" | ||
58 | depends on BT_BREDR | ||
59 | default y | ||
60 | |||
56 | config BT_LE | 61 | config BT_LE |
57 | bool "Bluetooth Low Energy (LE) features" | 62 | bool "Bluetooth Low Energy (LE) features" |
58 | depends on BT | 63 | depends on BT |
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index 29c12ae72a66..2b15ae8c1def 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile | |||
@@ -13,9 +13,10 @@ bluetooth_6lowpan-y := 6lowpan.o | |||
13 | 13 | ||
14 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ | 14 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ |
15 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \ | 15 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \ |
16 | a2mp.o amp.o ecc.o hci_request.o mgmt_util.o | 16 | ecc.o hci_request.o mgmt_util.o |
17 | 17 | ||
18 | bluetooth-$(CONFIG_BT_BREDR) += sco.o | 18 | bluetooth-$(CONFIG_BT_BREDR) += sco.o |
19 | bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o | ||
19 | bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o | 20 | bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o |
20 | bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o | 21 | bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o |
21 | 22 | ||
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 5a04eb1a7e57..5f123c3320a7 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <net/bluetooth/hci_core.h> | 16 | #include <net/bluetooth/hci_core.h> |
17 | #include <net/bluetooth/l2cap.h> | 17 | #include <net/bluetooth/l2cap.h> |
18 | 18 | ||
19 | #include "hci_request.h" | ||
19 | #include "a2mp.h" | 20 | #include "a2mp.h" |
20 | #include "amp.h" | 21 | #include "amp.h" |
21 | 22 | ||
@@ -286,11 +287,21 @@ static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb, | |||
286 | return 0; | 287 | return 0; |
287 | } | 288 | } |
288 | 289 | ||
290 | static void read_local_amp_info_complete(struct hci_dev *hdev, u8 status, | ||
291 | u16 opcode) | ||
292 | { | ||
293 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
294 | |||
295 | a2mp_send_getinfo_rsp(hdev); | ||
296 | } | ||
297 | |||
289 | static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, | 298 | static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, |
290 | struct a2mp_cmd *hdr) | 299 | struct a2mp_cmd *hdr) |
291 | { | 300 | { |
292 | struct a2mp_info_req *req = (void *) skb->data; | 301 | struct a2mp_info_req *req = (void *) skb->data; |
293 | struct hci_dev *hdev; | 302 | struct hci_dev *hdev; |
303 | struct hci_request hreq; | ||
304 | int err = 0; | ||
294 | 305 | ||
295 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | 306 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
296 | return -EINVAL; | 307 | return -EINVAL; |
@@ -311,7 +322,11 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
311 | } | 322 | } |
312 | 323 | ||
313 | set_bit(READ_LOC_AMP_INFO, &mgr->state); | 324 | set_bit(READ_LOC_AMP_INFO, &mgr->state); |
314 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | 325 | hci_req_init(&hreq, hdev); |
326 | hci_req_add(&hreq, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | ||
327 | err = hci_req_run(&hreq, read_local_amp_info_complete); | ||
328 | if (err < 0) | ||
329 | a2mp_send_getinfo_rsp(hdev); | ||
315 | 330 | ||
316 | done: | 331 | done: |
317 | if (hdev) | 332 | if (hdev) |
diff --git a/net/bluetooth/a2mp.h b/net/bluetooth/a2mp.h index 296f665adb09..a4ff3ea9b38a 100644 --- a/net/bluetooth/a2mp.h +++ b/net/bluetooth/a2mp.h | |||
@@ -130,10 +130,29 @@ struct a2mp_physlink_rsp { | |||
130 | #define A2MP_STATUS_SECURITY_VIOLATION 0x06 | 130 | #define A2MP_STATUS_SECURITY_VIOLATION 0x06 |
131 | 131 | ||
132 | struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr); | 132 | struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr); |
133 | |||
134 | #if IS_ENABLED(CONFIG_BT_HS) | ||
133 | int amp_mgr_put(struct amp_mgr *mgr); | 135 | int amp_mgr_put(struct amp_mgr *mgr); |
134 | struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, | 136 | struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, |
135 | struct sk_buff *skb); | 137 | struct sk_buff *skb); |
136 | void a2mp_discover_amp(struct l2cap_chan *chan); | 138 | void a2mp_discover_amp(struct l2cap_chan *chan); |
139 | #else | ||
140 | static inline int amp_mgr_put(struct amp_mgr *mgr) | ||
141 | { | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static inline struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, | ||
146 | struct sk_buff *skb) | ||
147 | { | ||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | static inline void a2mp_discover_amp(struct l2cap_chan *chan) | ||
152 | { | ||
153 | } | ||
154 | #endif | ||
155 | |||
137 | void a2mp_send_getinfo_rsp(struct hci_dev *hdev); | 156 | void a2mp_send_getinfo_rsp(struct hci_dev *hdev); |
138 | void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); | 157 | void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); |
139 | void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status); | 158 | void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status); |
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index ee016f039100..238ddd3cf95f 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <net/bluetooth/hci_core.h> | 16 | #include <net/bluetooth/hci_core.h> |
17 | #include <crypto/hash.h> | 17 | #include <crypto/hash.h> |
18 | 18 | ||
19 | #include "hci_request.h" | ||
19 | #include "a2mp.h" | 20 | #include "a2mp.h" |
20 | #include "amp.h" | 21 | #include "amp.h" |
21 | 22 | ||
@@ -220,10 +221,49 @@ int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type) | |||
220 | return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data); | 221 | return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data); |
221 | } | 222 | } |
222 | 223 | ||
224 | static void read_local_amp_assoc_complete(struct hci_dev *hdev, u8 status, | ||
225 | u16 opcode, struct sk_buff *skb) | ||
226 | { | ||
227 | struct hci_rp_read_local_amp_assoc *rp = (void *)skb->data; | ||
228 | struct amp_assoc *assoc = &hdev->loc_assoc; | ||
229 | size_t rem_len, frag_len; | ||
230 | |||
231 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
232 | |||
233 | if (rp->status) | ||
234 | goto send_rsp; | ||
235 | |||
236 | frag_len = skb->len - sizeof(*rp); | ||
237 | rem_len = __le16_to_cpu(rp->rem_len); | ||
238 | |||
239 | if (rem_len > frag_len) { | ||
240 | BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); | ||
241 | |||
242 | memcpy(assoc->data + assoc->offset, rp->frag, frag_len); | ||
243 | assoc->offset += frag_len; | ||
244 | |||
245 | /* Read other fragments */ | ||
246 | amp_read_loc_assoc_frag(hdev, rp->phy_handle); | ||
247 | |||
248 | return; | ||
249 | } | ||
250 | |||
251 | memcpy(assoc->data + assoc->offset, rp->frag, rem_len); | ||
252 | assoc->len = assoc->offset + rem_len; | ||
253 | assoc->offset = 0; | ||
254 | |||
255 | send_rsp: | ||
256 | /* Send A2MP Rsp when all fragments are received */ | ||
257 | a2mp_send_getampassoc_rsp(hdev, rp->status); | ||
258 | a2mp_send_create_phy_link_req(hdev, rp->status); | ||
259 | } | ||
260 | |||
223 | void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle) | 261 | void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle) |
224 | { | 262 | { |
225 | struct hci_cp_read_local_amp_assoc cp; | 263 | struct hci_cp_read_local_amp_assoc cp; |
226 | struct amp_assoc *loc_assoc = &hdev->loc_assoc; | 264 | struct amp_assoc *loc_assoc = &hdev->loc_assoc; |
265 | struct hci_request req; | ||
266 | int err = 0; | ||
227 | 267 | ||
228 | BT_DBG("%s handle %d", hdev->name, phy_handle); | 268 | BT_DBG("%s handle %d", hdev->name, phy_handle); |
229 | 269 | ||
@@ -231,12 +271,18 @@ void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle) | |||
231 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | 271 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); |
232 | cp.len_so_far = cpu_to_le16(loc_assoc->offset); | 272 | cp.len_so_far = cpu_to_le16(loc_assoc->offset); |
233 | 273 | ||
234 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | 274 | hci_req_init(&req, hdev); |
275 | hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | ||
276 | err = hci_req_run_skb(&req, read_local_amp_assoc_complete); | ||
277 | if (err < 0) | ||
278 | a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID); | ||
235 | } | 279 | } |
236 | 280 | ||
237 | void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr) | 281 | void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr) |
238 | { | 282 | { |
239 | struct hci_cp_read_local_amp_assoc cp; | 283 | struct hci_cp_read_local_amp_assoc cp; |
284 | struct hci_request req; | ||
285 | int err = 0; | ||
240 | 286 | ||
241 | memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc)); | 287 | memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc)); |
242 | memset(&cp, 0, sizeof(cp)); | 288 | memset(&cp, 0, sizeof(cp)); |
@@ -244,7 +290,11 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr) | |||
244 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | 290 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); |
245 | 291 | ||
246 | set_bit(READ_LOC_AMP_ASSOC, &mgr->state); | 292 | set_bit(READ_LOC_AMP_ASSOC, &mgr->state); |
247 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | 293 | hci_req_init(&req, hdev); |
294 | hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | ||
295 | hci_req_run_skb(&req, read_local_amp_assoc_complete); | ||
296 | if (err < 0) | ||
297 | a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID); | ||
248 | } | 298 | } |
249 | 299 | ||
250 | void amp_read_loc_assoc_final_data(struct hci_dev *hdev, | 300 | void amp_read_loc_assoc_final_data(struct hci_dev *hdev, |
@@ -252,6 +302,8 @@ void amp_read_loc_assoc_final_data(struct hci_dev *hdev, | |||
252 | { | 302 | { |
253 | struct hci_cp_read_local_amp_assoc cp; | 303 | struct hci_cp_read_local_amp_assoc cp; |
254 | struct amp_mgr *mgr = hcon->amp_mgr; | 304 | struct amp_mgr *mgr = hcon->amp_mgr; |
305 | struct hci_request req; | ||
306 | int err = 0; | ||
255 | 307 | ||
256 | cp.phy_handle = hcon->handle; | 308 | cp.phy_handle = hcon->handle; |
257 | cp.len_so_far = cpu_to_le16(0); | 309 | cp.len_so_far = cpu_to_le16(0); |
@@ -260,7 +312,25 @@ void amp_read_loc_assoc_final_data(struct hci_dev *hdev, | |||
260 | set_bit(READ_LOC_AMP_ASSOC_FINAL, &mgr->state); | 312 | set_bit(READ_LOC_AMP_ASSOC_FINAL, &mgr->state); |
261 | 313 | ||
262 | /* Read Local AMP Assoc final link information data */ | 314 | /* Read Local AMP Assoc final link information data */ |
263 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | 315 | hci_req_init(&req, hdev); |
316 | hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | ||
317 | hci_req_run_skb(&req, read_local_amp_assoc_complete); | ||
318 | if (err < 0) | ||
319 | a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID); | ||
320 | } | ||
321 | |||
322 | static void write_remote_amp_assoc_complete(struct hci_dev *hdev, u8 status, | ||
323 | u16 opcode, struct sk_buff *skb) | ||
324 | { | ||
325 | struct hci_rp_write_remote_amp_assoc *rp = (void *)skb->data; | ||
326 | |||
327 | BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", | ||
328 | hdev->name, rp->status, rp->phy_handle); | ||
329 | |||
330 | if (rp->status) | ||
331 | return; | ||
332 | |||
333 | amp_write_rem_assoc_continue(hdev, rp->phy_handle); | ||
264 | } | 334 | } |
265 | 335 | ||
266 | /* Write AMP Assoc data fragments, returns true with last fragment written*/ | 336 | /* Write AMP Assoc data fragments, returns true with last fragment written*/ |
@@ -270,6 +340,7 @@ static bool amp_write_rem_assoc_frag(struct hci_dev *hdev, | |||
270 | struct hci_cp_write_remote_amp_assoc *cp; | 340 | struct hci_cp_write_remote_amp_assoc *cp; |
271 | struct amp_mgr *mgr = hcon->amp_mgr; | 341 | struct amp_mgr *mgr = hcon->amp_mgr; |
272 | struct amp_ctrl *ctrl; | 342 | struct amp_ctrl *ctrl; |
343 | struct hci_request req; | ||
273 | u16 frag_len, len; | 344 | u16 frag_len, len; |
274 | 345 | ||
275 | ctrl = amp_ctrl_lookup(mgr, hcon->remote_id); | 346 | ctrl = amp_ctrl_lookup(mgr, hcon->remote_id); |
@@ -307,7 +378,9 @@ static bool amp_write_rem_assoc_frag(struct hci_dev *hdev, | |||
307 | 378 | ||
308 | amp_ctrl_put(ctrl); | 379 | amp_ctrl_put(ctrl); |
309 | 380 | ||
310 | hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp); | 381 | hci_req_init(&req, hdev); |
382 | hci_req_add(&req, HCI_OP_WRITE_REMOTE_AMP_ASSOC, sizeof(cp), &cp); | ||
383 | hci_req_run_skb(&req, write_remote_amp_assoc_complete); | ||
311 | 384 | ||
312 | kfree(cp); | 385 | kfree(cp); |
313 | 386 | ||
@@ -344,10 +417,37 @@ void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle) | |||
344 | amp_write_rem_assoc_frag(hdev, hcon); | 417 | amp_write_rem_assoc_frag(hdev, hcon); |
345 | } | 418 | } |
346 | 419 | ||
420 | static void create_phylink_complete(struct hci_dev *hdev, u8 status, | ||
421 | u16 opcode) | ||
422 | { | ||
423 | struct hci_cp_create_phy_link *cp; | ||
424 | |||
425 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
426 | |||
427 | cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); | ||
428 | if (!cp) | ||
429 | return; | ||
430 | |||
431 | hci_dev_lock(hdev); | ||
432 | |||
433 | if (status) { | ||
434 | struct hci_conn *hcon; | ||
435 | |||
436 | hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); | ||
437 | if (hcon) | ||
438 | hci_conn_del(hcon); | ||
439 | } else { | ||
440 | amp_write_remote_assoc(hdev, cp->phy_handle); | ||
441 | } | ||
442 | |||
443 | hci_dev_unlock(hdev); | ||
444 | } | ||
445 | |||
347 | void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | 446 | void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, |
348 | struct hci_conn *hcon) | 447 | struct hci_conn *hcon) |
349 | { | 448 | { |
350 | struct hci_cp_create_phy_link cp; | 449 | struct hci_cp_create_phy_link cp; |
450 | struct hci_request req; | ||
351 | 451 | ||
352 | cp.phy_handle = hcon->handle; | 452 | cp.phy_handle = hcon->handle; |
353 | 453 | ||
@@ -360,13 +460,33 @@ void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
360 | return; | 460 | return; |
361 | } | 461 | } |
362 | 462 | ||
363 | hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp); | 463 | hci_req_init(&req, hdev); |
464 | hci_req_add(&req, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp); | ||
465 | hci_req_run(&req, create_phylink_complete); | ||
466 | } | ||
467 | |||
468 | static void accept_phylink_complete(struct hci_dev *hdev, u8 status, | ||
469 | u16 opcode) | ||
470 | { | ||
471 | struct hci_cp_accept_phy_link *cp; | ||
472 | |||
473 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
474 | |||
475 | if (status) | ||
476 | return; | ||
477 | |||
478 | cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); | ||
479 | if (!cp) | ||
480 | return; | ||
481 | |||
482 | amp_write_remote_assoc(hdev, cp->phy_handle); | ||
364 | } | 483 | } |
365 | 484 | ||
366 | void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | 485 | void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, |
367 | struct hci_conn *hcon) | 486 | struct hci_conn *hcon) |
368 | { | 487 | { |
369 | struct hci_cp_accept_phy_link cp; | 488 | struct hci_cp_accept_phy_link cp; |
489 | struct hci_request req; | ||
370 | 490 | ||
371 | cp.phy_handle = hcon->handle; | 491 | cp.phy_handle = hcon->handle; |
372 | 492 | ||
@@ -379,7 +499,9 @@ void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
379 | return; | 499 | return; |
380 | } | 500 | } |
381 | 501 | ||
382 | hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp); | 502 | hci_req_init(&req, hdev); |
503 | hci_req_add(&req, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp); | ||
504 | hci_req_run(&req, accept_phylink_complete); | ||
383 | } | 505 | } |
384 | 506 | ||
385 | void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon) | 507 | void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon) |
diff --git a/net/bluetooth/amp.h b/net/bluetooth/amp.h index 7ea3db77ba89..8848f8158ae4 100644 --- a/net/bluetooth/amp.h +++ b/net/bluetooth/amp.h | |||
@@ -44,6 +44,20 @@ void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
44 | struct hci_conn *hcon); | 44 | struct hci_conn *hcon); |
45 | void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | 45 | void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, |
46 | struct hci_conn *hcon); | 46 | struct hci_conn *hcon); |
47 | |||
48 | #if IS_ENABLED(CONFIG_BT_HS) | ||
49 | void amp_create_logical_link(struct l2cap_chan *chan); | ||
50 | void amp_disconnect_logical_link(struct hci_chan *hchan); | ||
51 | #else | ||
52 | static inline void amp_create_logical_link(struct l2cap_chan *chan) | ||
53 | { | ||
54 | } | ||
55 | |||
56 | static inline void amp_disconnect_logical_link(struct hci_chan *hchan) | ||
57 | { | ||
58 | } | ||
59 | #endif | ||
60 | |||
47 | void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); | 61 | void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); |
48 | void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); | 62 | void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); |
49 | void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon); | 63 | void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon); |
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index b0c6c6af76ef..9a50338772f3 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c | |||
@@ -100,9 +100,9 @@ static void cmtp_application_del(struct cmtp_session *session, struct cmtp_appli | |||
100 | static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value) | 100 | static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value) |
101 | { | 101 | { |
102 | struct cmtp_application *app; | 102 | struct cmtp_application *app; |
103 | struct list_head *p, *n; | 103 | struct list_head *p; |
104 | 104 | ||
105 | list_for_each_safe(p, n, &session->applications) { | 105 | list_for_each(p, &session->applications) { |
106 | app = list_entry(p, struct cmtp_application, list); | 106 | app = list_entry(p, struct cmtp_application, list); |
107 | switch (pattern) { | 107 | switch (pattern) { |
108 | case CMTP_MSGNUM: | 108 | case CMTP_MSGNUM: |
@@ -511,13 +511,13 @@ static int cmtp_proc_show(struct seq_file *m, void *v) | |||
511 | struct capi_ctr *ctrl = m->private; | 511 | struct capi_ctr *ctrl = m->private; |
512 | struct cmtp_session *session = ctrl->driverdata; | 512 | struct cmtp_session *session = ctrl->driverdata; |
513 | struct cmtp_application *app; | 513 | struct cmtp_application *app; |
514 | struct list_head *p, *n; | 514 | struct list_head *p; |
515 | 515 | ||
516 | seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl)); | 516 | seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl)); |
517 | seq_printf(m, "addr %s\n", session->name); | 517 | seq_printf(m, "addr %s\n", session->name); |
518 | seq_printf(m, "ctrl %d\n", session->num); | 518 | seq_printf(m, "ctrl %d\n", session->num); |
519 | 519 | ||
520 | list_for_each_safe(p, n, &session->applications) { | 520 | list_for_each(p, &session->applications) { |
521 | app = list_entry(p, struct cmtp_application, list); | 521 | app = list_entry(p, struct cmtp_application, list); |
522 | seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping); | 522 | seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping); |
523 | } | 523 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 2f8fb33067e1..bc43b6490555 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2822,10 +2822,6 @@ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, | |||
2822 | { | 2822 | { |
2823 | struct hci_conn_params *params; | 2823 | struct hci_conn_params *params; |
2824 | 2824 | ||
2825 | /* The conn params list only contains identity addresses */ | ||
2826 | if (!hci_is_identity_address(addr, addr_type)) | ||
2827 | return NULL; | ||
2828 | |||
2829 | list_for_each_entry(params, &hdev->le_conn_params, list) { | 2825 | list_for_each_entry(params, &hdev->le_conn_params, list) { |
2830 | if (bacmp(¶ms->addr, addr) == 0 && | 2826 | if (bacmp(¶ms->addr, addr) == 0 && |
2831 | params->addr_type == addr_type) { | 2827 | params->addr_type == addr_type) { |
@@ -2842,10 +2838,6 @@ struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list, | |||
2842 | { | 2838 | { |
2843 | struct hci_conn_params *param; | 2839 | struct hci_conn_params *param; |
2844 | 2840 | ||
2845 | /* The list only contains identity addresses */ | ||
2846 | if (!hci_is_identity_address(addr, addr_type)) | ||
2847 | return NULL; | ||
2848 | |||
2849 | list_for_each_entry(param, list, action) { | 2841 | list_for_each_entry(param, list, action) { |
2850 | if (bacmp(¶m->addr, addr) == 0 && | 2842 | if (bacmp(¶m->addr, addr) == 0 && |
2851 | param->addr_type == addr_type) | 2843 | param->addr_type == addr_type) |
@@ -2861,9 +2853,6 @@ struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev, | |||
2861 | { | 2853 | { |
2862 | struct hci_conn_params *params; | 2854 | struct hci_conn_params *params; |
2863 | 2855 | ||
2864 | if (!hci_is_identity_address(addr, addr_type)) | ||
2865 | return NULL; | ||
2866 | |||
2867 | params = hci_conn_params_lookup(hdev, addr, addr_type); | 2856 | params = hci_conn_params_lookup(hdev, addr, addr_type); |
2868 | if (params) | 2857 | if (params) |
2869 | return params; | 2858 | return params; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 32363c2b7f83..218d7dfc342f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -823,7 +823,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | |||
823 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 823 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
824 | 824 | ||
825 | if (rp->status) | 825 | if (rp->status) |
826 | goto a2mp_rsp; | 826 | return; |
827 | 827 | ||
828 | hdev->amp_status = rp->amp_status; | 828 | hdev->amp_status = rp->amp_status; |
829 | hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); | 829 | hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); |
@@ -835,46 +835,6 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | |||
835 | hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); | 835 | hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); |
836 | hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); | 836 | hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); |
837 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); | 837 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); |
838 | |||
839 | a2mp_rsp: | ||
840 | a2mp_send_getinfo_rsp(hdev); | ||
841 | } | ||
842 | |||
843 | static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, | ||
844 | struct sk_buff *skb) | ||
845 | { | ||
846 | struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; | ||
847 | struct amp_assoc *assoc = &hdev->loc_assoc; | ||
848 | size_t rem_len, frag_len; | ||
849 | |||
850 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
851 | |||
852 | if (rp->status) | ||
853 | goto a2mp_rsp; | ||
854 | |||
855 | frag_len = skb->len - sizeof(*rp); | ||
856 | rem_len = __le16_to_cpu(rp->rem_len); | ||
857 | |||
858 | if (rem_len > frag_len) { | ||
859 | BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); | ||
860 | |||
861 | memcpy(assoc->data + assoc->offset, rp->frag, frag_len); | ||
862 | assoc->offset += frag_len; | ||
863 | |||
864 | /* Read other fragments */ | ||
865 | amp_read_loc_assoc_frag(hdev, rp->phy_handle); | ||
866 | |||
867 | return; | ||
868 | } | ||
869 | |||
870 | memcpy(assoc->data + assoc->offset, rp->frag, rem_len); | ||
871 | assoc->len = assoc->offset + rem_len; | ||
872 | assoc->offset = 0; | ||
873 | |||
874 | a2mp_rsp: | ||
875 | /* Send A2MP Rsp when all fragments are received */ | ||
876 | a2mp_send_getampassoc_rsp(hdev, rp->status); | ||
877 | a2mp_send_create_phy_link_req(hdev, rp->status); | ||
878 | } | 838 | } |
879 | 839 | ||
880 | static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, | 840 | static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, |
@@ -1409,20 +1369,6 @@ static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) | |||
1409 | hci_dev_unlock(hdev); | 1369 | hci_dev_unlock(hdev); |
1410 | } | 1370 | } |
1411 | 1371 | ||
1412 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, | ||
1413 | struct sk_buff *skb) | ||
1414 | { | ||
1415 | struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; | ||
1416 | |||
1417 | BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", | ||
1418 | hdev->name, rp->status, rp->phy_handle); | ||
1419 | |||
1420 | if (rp->status) | ||
1421 | return; | ||
1422 | |||
1423 | amp_write_rem_assoc_continue(hdev, rp->phy_handle); | ||
1424 | } | ||
1425 | |||
1426 | static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) | 1372 | static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) |
1427 | { | 1373 | { |
1428 | struct hci_rp_read_rssi *rp = (void *) skb->data; | 1374 | struct hci_rp_read_rssi *rp = (void *) skb->data; |
@@ -1944,47 +1890,6 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) | |||
1944 | hci_dev_unlock(hdev); | 1890 | hci_dev_unlock(hdev); |
1945 | } | 1891 | } |
1946 | 1892 | ||
1947 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | ||
1948 | { | ||
1949 | struct hci_cp_create_phy_link *cp; | ||
1950 | |||
1951 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1952 | |||
1953 | cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); | ||
1954 | if (!cp) | ||
1955 | return; | ||
1956 | |||
1957 | hci_dev_lock(hdev); | ||
1958 | |||
1959 | if (status) { | ||
1960 | struct hci_conn *hcon; | ||
1961 | |||
1962 | hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); | ||
1963 | if (hcon) | ||
1964 | hci_conn_del(hcon); | ||
1965 | } else { | ||
1966 | amp_write_remote_assoc(hdev, cp->phy_handle); | ||
1967 | } | ||
1968 | |||
1969 | hci_dev_unlock(hdev); | ||
1970 | } | ||
1971 | |||
1972 | static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) | ||
1973 | { | ||
1974 | struct hci_cp_accept_phy_link *cp; | ||
1975 | |||
1976 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1977 | |||
1978 | if (status) | ||
1979 | return; | ||
1980 | |||
1981 | cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); | ||
1982 | if (!cp) | ||
1983 | return; | ||
1984 | |||
1985 | amp_write_remote_assoc(hdev, cp->phy_handle); | ||
1986 | } | ||
1987 | |||
1988 | static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) | 1893 | static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) |
1989 | { | 1894 | { |
1990 | struct hci_cp_le_create_conn *cp; | 1895 | struct hci_cp_le_create_conn *cp; |
@@ -2998,10 +2903,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, | |||
2998 | hci_cc_read_clock(hdev, skb); | 2903 | hci_cc_read_clock(hdev, skb); |
2999 | break; | 2904 | break; |
3000 | 2905 | ||
3001 | case HCI_OP_READ_LOCAL_AMP_ASSOC: | ||
3002 | hci_cc_read_local_amp_assoc(hdev, skb); | ||
3003 | break; | ||
3004 | |||
3005 | case HCI_OP_READ_INQ_RSP_TX_POWER: | 2906 | case HCI_OP_READ_INQ_RSP_TX_POWER: |
3006 | hci_cc_read_inq_rsp_tx_power(hdev, skb); | 2907 | hci_cc_read_inq_rsp_tx_power(hdev, skb); |
3007 | break; | 2908 | break; |
@@ -3106,10 +3007,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, | |||
3106 | hci_cc_set_adv_param(hdev, skb); | 3007 | hci_cc_set_adv_param(hdev, skb); |
3107 | break; | 3008 | break; |
3108 | 3009 | ||
3109 | case HCI_OP_WRITE_REMOTE_AMP_ASSOC: | ||
3110 | hci_cc_write_remote_amp_assoc(hdev, skb); | ||
3111 | break; | ||
3112 | |||
3113 | case HCI_OP_READ_RSSI: | 3010 | case HCI_OP_READ_RSSI: |
3114 | hci_cc_read_rssi(hdev, skb); | 3011 | hci_cc_read_rssi(hdev, skb); |
3115 | break; | 3012 | break; |
@@ -3193,14 +3090,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, | |||
3193 | hci_cs_setup_sync_conn(hdev, ev->status); | 3090 | hci_cs_setup_sync_conn(hdev, ev->status); |
3194 | break; | 3091 | break; |
3195 | 3092 | ||
3196 | case HCI_OP_CREATE_PHY_LINK: | ||
3197 | hci_cs_create_phylink(hdev, ev->status); | ||
3198 | break; | ||
3199 | |||
3200 | case HCI_OP_ACCEPT_PHY_LINK: | ||
3201 | hci_cs_accept_phylink(hdev, ev->status); | ||
3202 | break; | ||
3203 | |||
3204 | case HCI_OP_SNIFF_MODE: | 3093 | case HCI_OP_SNIFF_MODE: |
3205 | hci_cs_sniff_mode(hdev, ev->status); | 3094 | hci_cs_sniff_mode(hdev, ev->status); |
3206 | break; | 3095 | break; |
@@ -4399,6 +4288,23 @@ unlock: | |||
4399 | hci_dev_unlock(hdev); | 4288 | hci_dev_unlock(hdev); |
4400 | } | 4289 | } |
4401 | 4290 | ||
4291 | #if IS_ENABLED(CONFIG_BT_HS) | ||
4292 | static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
4293 | { | ||
4294 | struct hci_ev_channel_selected *ev = (void *)skb->data; | ||
4295 | struct hci_conn *hcon; | ||
4296 | |||
4297 | BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); | ||
4298 | |||
4299 | skb_pull(skb, sizeof(*ev)); | ||
4300 | |||
4301 | hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); | ||
4302 | if (!hcon) | ||
4303 | return; | ||
4304 | |||
4305 | amp_read_loc_assoc_final_data(hdev, hcon); | ||
4306 | } | ||
4307 | |||
4402 | static void hci_phy_link_complete_evt(struct hci_dev *hdev, | 4308 | static void hci_phy_link_complete_evt(struct hci_dev *hdev, |
4403 | struct sk_buff *skb) | 4309 | struct sk_buff *skb) |
4404 | { | 4310 | { |
@@ -4522,6 +4428,7 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, | |||
4522 | 4428 | ||
4523 | hci_dev_unlock(hdev); | 4429 | hci_dev_unlock(hdev); |
4524 | } | 4430 | } |
4431 | #endif | ||
4525 | 4432 | ||
4526 | static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 4433 | static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
4527 | { | 4434 | { |
@@ -5206,22 +5113,6 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
5206 | } | 5113 | } |
5207 | } | 5114 | } |
5208 | 5115 | ||
5209 | static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
5210 | { | ||
5211 | struct hci_ev_channel_selected *ev = (void *) skb->data; | ||
5212 | struct hci_conn *hcon; | ||
5213 | |||
5214 | BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); | ||
5215 | |||
5216 | skb_pull(skb, sizeof(*ev)); | ||
5217 | |||
5218 | hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); | ||
5219 | if (!hcon) | ||
5220 | return; | ||
5221 | |||
5222 | amp_read_loc_assoc_final_data(hdev, hcon); | ||
5223 | } | ||
5224 | |||
5225 | static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, | 5116 | static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, |
5226 | u8 event, struct sk_buff *skb) | 5117 | u8 event, struct sk_buff *skb) |
5227 | { | 5118 | { |
@@ -5442,14 +5333,15 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
5442 | hci_le_meta_evt(hdev, skb); | 5333 | hci_le_meta_evt(hdev, skb); |
5443 | break; | 5334 | break; |
5444 | 5335 | ||
5445 | case HCI_EV_CHANNEL_SELECTED: | ||
5446 | hci_chan_selected_evt(hdev, skb); | ||
5447 | break; | ||
5448 | |||
5449 | case HCI_EV_REMOTE_OOB_DATA_REQUEST: | 5336 | case HCI_EV_REMOTE_OOB_DATA_REQUEST: |
5450 | hci_remote_oob_data_request_evt(hdev, skb); | 5337 | hci_remote_oob_data_request_evt(hdev, skb); |
5451 | break; | 5338 | break; |
5452 | 5339 | ||
5340 | #if IS_ENABLED(CONFIG_BT_HS) | ||
5341 | case HCI_EV_CHANNEL_SELECTED: | ||
5342 | hci_chan_selected_evt(hdev, skb); | ||
5343 | break; | ||
5344 | |||
5453 | case HCI_EV_PHY_LINK_COMPLETE: | 5345 | case HCI_EV_PHY_LINK_COMPLETE: |
5454 | hci_phy_link_complete_evt(hdev, skb); | 5346 | hci_phy_link_complete_evt(hdev, skb); |
5455 | break; | 5347 | break; |
@@ -5465,6 +5357,7 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
5465 | case HCI_EV_DISCONN_PHY_LINK_COMPLETE: | 5357 | case HCI_EV_DISCONN_PHY_LINK_COMPLETE: |
5466 | hci_disconn_phylink_complete_evt(hdev, skb); | 5358 | hci_disconn_phylink_complete_evt(hdev, skb); |
5467 | break; | 5359 | break; |
5360 | #endif | ||
5468 | 5361 | ||
5469 | case HCI_EV_NUM_COMP_BLOCKS: | 5362 | case HCI_EV_NUM_COMP_BLOCKS: |
5470 | hci_num_comp_blocks_evt(hdev, skb); | 5363 | hci_num_comp_blocks_evt(hdev, skb); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 244287706f91..586b3d580cfc 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -1054,18 +1054,23 @@ static void l2cap_sock_kill(struct sock *sk) | |||
1054 | sock_put(sk); | 1054 | sock_put(sk); |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | static int __l2cap_wait_ack(struct sock *sk) | 1057 | static int __l2cap_wait_ack(struct sock *sk, struct l2cap_chan *chan) |
1058 | { | 1058 | { |
1059 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
1060 | DECLARE_WAITQUEUE(wait, current); | 1059 | DECLARE_WAITQUEUE(wait, current); |
1061 | int err = 0; | 1060 | int err = 0; |
1062 | int timeo = HZ/5; | 1061 | int timeo = L2CAP_WAIT_ACK_POLL_PERIOD; |
1062 | /* Timeout to prevent infinite loop */ | ||
1063 | unsigned long timeout = jiffies + L2CAP_WAIT_ACK_TIMEOUT; | ||
1063 | 1064 | ||
1064 | add_wait_queue(sk_sleep(sk), &wait); | 1065 | add_wait_queue(sk_sleep(sk), &wait); |
1065 | set_current_state(TASK_INTERRUPTIBLE); | 1066 | set_current_state(TASK_INTERRUPTIBLE); |
1066 | while (chan->unacked_frames > 0 && chan->conn) { | 1067 | do { |
1068 | BT_DBG("Waiting for %d ACKs, timeout %04d ms", | ||
1069 | chan->unacked_frames, time_after(jiffies, timeout) ? 0 : | ||
1070 | jiffies_to_msecs(timeout - jiffies)); | ||
1071 | |||
1067 | if (!timeo) | 1072 | if (!timeo) |
1068 | timeo = HZ/5; | 1073 | timeo = L2CAP_WAIT_ACK_POLL_PERIOD; |
1069 | 1074 | ||
1070 | if (signal_pending(current)) { | 1075 | if (signal_pending(current)) { |
1071 | err = sock_intr_errno(timeo); | 1076 | err = sock_intr_errno(timeo); |
@@ -1080,7 +1085,15 @@ static int __l2cap_wait_ack(struct sock *sk) | |||
1080 | err = sock_error(sk); | 1085 | err = sock_error(sk); |
1081 | if (err) | 1086 | if (err) |
1082 | break; | 1087 | break; |
1083 | } | 1088 | |
1089 | if (time_after(jiffies, timeout)) { | ||
1090 | err = -ENOLINK; | ||
1091 | break; | ||
1092 | } | ||
1093 | |||
1094 | } while (chan->unacked_frames > 0 && | ||
1095 | chan->state == BT_CONNECTED); | ||
1096 | |||
1084 | set_current_state(TASK_RUNNING); | 1097 | set_current_state(TASK_RUNNING); |
1085 | remove_wait_queue(sk_sleep(sk), &wait); | 1098 | remove_wait_queue(sk_sleep(sk), &wait); |
1086 | return err; | 1099 | return err; |
@@ -1098,7 +1111,12 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
1098 | if (!sk) | 1111 | if (!sk) |
1099 | return 0; | 1112 | return 0; |
1100 | 1113 | ||
1114 | /* prevent sk structure from being freed whilst unlocked */ | ||
1115 | sock_hold(sk); | ||
1116 | |||
1101 | chan = l2cap_pi(sk)->chan; | 1117 | chan = l2cap_pi(sk)->chan; |
1118 | /* prevent chan structure from being freed whilst unlocked */ | ||
1119 | l2cap_chan_hold(chan); | ||
1102 | conn = chan->conn; | 1120 | conn = chan->conn; |
1103 | 1121 | ||
1104 | BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); | 1122 | BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); |
@@ -1110,8 +1128,10 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
1110 | lock_sock(sk); | 1128 | lock_sock(sk); |
1111 | 1129 | ||
1112 | if (!sk->sk_shutdown) { | 1130 | if (!sk->sk_shutdown) { |
1113 | if (chan->mode == L2CAP_MODE_ERTM) | 1131 | if (chan->mode == L2CAP_MODE_ERTM && |
1114 | err = __l2cap_wait_ack(sk); | 1132 | chan->unacked_frames > 0 && |
1133 | chan->state == BT_CONNECTED) | ||
1134 | err = __l2cap_wait_ack(sk, chan); | ||
1115 | 1135 | ||
1116 | sk->sk_shutdown = SHUTDOWN_MASK; | 1136 | sk->sk_shutdown = SHUTDOWN_MASK; |
1117 | 1137 | ||
@@ -1134,6 +1154,11 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
1134 | if (conn) | 1154 | if (conn) |
1135 | mutex_unlock(&conn->chan_lock); | 1155 | mutex_unlock(&conn->chan_lock); |
1136 | 1156 | ||
1157 | l2cap_chan_put(chan); | ||
1158 | sock_put(sk); | ||
1159 | |||
1160 | BT_DBG("err: %d", err); | ||
1161 | |||
1137 | return err; | 1162 | return err; |
1138 | } | 1163 | } |
1139 | 1164 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7998fb279165..7ab191589541 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -6226,6 +6226,17 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, | |||
6226 | else | 6226 | else |
6227 | auto_conn = HCI_AUTO_CONN_REPORT; | 6227 | auto_conn = HCI_AUTO_CONN_REPORT; |
6228 | 6228 | ||
6229 | /* Kernel internally uses conn_params with resolvable private | ||
6230 | * address, but Add Device allows only identity addresses. | ||
6231 | * Make sure it is enforced before calling | ||
6232 | * hci_conn_params_lookup. | ||
6233 | */ | ||
6234 | if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) { | ||
6235 | err = cmd->cmd_complete(cmd, MGMT_STATUS_INVALID_PARAMS); | ||
6236 | mgmt_pending_remove(cmd); | ||
6237 | goto unlock; | ||
6238 | } | ||
6239 | |||
6229 | /* If the connection parameters don't exist for this device, | 6240 | /* If the connection parameters don't exist for this device, |
6230 | * they will be created and configured with defaults. | 6241 | * they will be created and configured with defaults. |
6231 | */ | 6242 | */ |
@@ -6340,6 +6351,18 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, | |||
6340 | else | 6351 | else |
6341 | addr_type = ADDR_LE_DEV_RANDOM; | 6352 | addr_type = ADDR_LE_DEV_RANDOM; |
6342 | 6353 | ||
6354 | /* Kernel internally uses conn_params with resolvable private | ||
6355 | * address, but Remove Device allows only identity addresses. | ||
6356 | * Make sure it is enforced before calling | ||
6357 | * hci_conn_params_lookup. | ||
6358 | */ | ||
6359 | if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) { | ||
6360 | err = cmd->cmd_complete(cmd, | ||
6361 | MGMT_STATUS_INVALID_PARAMS); | ||
6362 | mgmt_pending_remove(cmd); | ||
6363 | goto unlock; | ||
6364 | } | ||
6365 | |||
6343 | params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, | 6366 | params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, |
6344 | addr_type); | 6367 | addr_type); |
6345 | if (!params) { | 6368 | if (!params) { |
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h index b2155a123f6c..8d5960a37195 100644 --- a/net/ieee802154/rdev-ops.h +++ b/net/ieee802154/rdev-ops.h | |||
@@ -24,6 +24,26 @@ rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, | |||
24 | } | 24 | } |
25 | 25 | ||
26 | static inline int | 26 | static inline int |
27 | rdev_suspend(struct cfg802154_registered_device *rdev) | ||
28 | { | ||
29 | int ret; | ||
30 | trace_802154_rdev_suspend(&rdev->wpan_phy); | ||
31 | ret = rdev->ops->suspend(&rdev->wpan_phy); | ||
32 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
33 | return ret; | ||
34 | } | ||
35 | |||
36 | static inline int | ||
37 | rdev_resume(struct cfg802154_registered_device *rdev) | ||
38 | { | ||
39 | int ret; | ||
40 | trace_802154_rdev_resume(&rdev->wpan_phy); | ||
41 | ret = rdev->ops->resume(&rdev->wpan_phy); | ||
42 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | static inline int | ||
27 | rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name, | 47 | rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name, |
28 | unsigned char name_assign_type, | 48 | unsigned char name_assign_type, |
29 | enum nl802154_iftype type, __le64 extended_addr) | 49 | enum nl802154_iftype type, __le64 extended_addr) |
diff --git a/net/ieee802154/sysfs.c b/net/ieee802154/sysfs.c index 133b4280660c..bd88525b041e 100644 --- a/net/ieee802154/sysfs.c +++ b/net/ieee802154/sysfs.c | |||
@@ -14,11 +14,13 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/rtnetlink.h> | ||
17 | 18 | ||
18 | #include <net/cfg802154.h> | 19 | #include <net/cfg802154.h> |
19 | 20 | ||
20 | #include "core.h" | 21 | #include "core.h" |
21 | #include "sysfs.h" | 22 | #include "sysfs.h" |
23 | #include "rdev-ops.h" | ||
22 | 24 | ||
23 | static inline struct cfg802154_registered_device * | 25 | static inline struct cfg802154_registered_device * |
24 | dev_to_rdev(struct device *dev) | 26 | dev_to_rdev(struct device *dev) |
@@ -62,10 +64,46 @@ static struct attribute *pmib_attrs[] = { | |||
62 | }; | 64 | }; |
63 | ATTRIBUTE_GROUPS(pmib); | 65 | ATTRIBUTE_GROUPS(pmib); |
64 | 66 | ||
67 | #ifdef CONFIG_PM_SLEEP | ||
68 | static int wpan_phy_suspend(struct device *dev) | ||
69 | { | ||
70 | struct cfg802154_registered_device *rdev = dev_to_rdev(dev); | ||
71 | int ret = 0; | ||
72 | |||
73 | if (rdev->ops->suspend) { | ||
74 | rtnl_lock(); | ||
75 | ret = rdev_suspend(rdev); | ||
76 | rtnl_unlock(); | ||
77 | } | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | static int wpan_phy_resume(struct device *dev) | ||
83 | { | ||
84 | struct cfg802154_registered_device *rdev = dev_to_rdev(dev); | ||
85 | int ret = 0; | ||
86 | |||
87 | if (rdev->ops->resume) { | ||
88 | rtnl_lock(); | ||
89 | ret = rdev_resume(rdev); | ||
90 | rtnl_unlock(); | ||
91 | } | ||
92 | |||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | static SIMPLE_DEV_PM_OPS(wpan_phy_pm_ops, wpan_phy_suspend, wpan_phy_resume); | ||
97 | #define WPAN_PHY_PM_OPS (&wpan_phy_pm_ops) | ||
98 | #else | ||
99 | #define WPAN_PHY_PM_OPS NULL | ||
100 | #endif | ||
101 | |||
65 | struct class wpan_phy_class = { | 102 | struct class wpan_phy_class = { |
66 | .name = "ieee802154", | 103 | .name = "ieee802154", |
67 | .dev_release = wpan_phy_release, | 104 | .dev_release = wpan_phy_release, |
68 | .dev_groups = pmib_groups, | 105 | .dev_groups = pmib_groups, |
106 | .pm = WPAN_PHY_PM_OPS, | ||
69 | }; | 107 | }; |
70 | 108 | ||
71 | int wpan_phy_sysfs_init(void) | 109 | int wpan_phy_sysfs_init(void) |
diff --git a/net/ieee802154/trace.h b/net/ieee802154/trace.h index 9b5f0eb36696..4399b7fbaa31 100644 --- a/net/ieee802154/trace.h +++ b/net/ieee802154/trace.h | |||
@@ -40,6 +40,28 @@ | |||
40 | * rdev->ops traces * | 40 | * rdev->ops traces * |
41 | *************************************************************/ | 41 | *************************************************************/ |
42 | 42 | ||
43 | DECLARE_EVENT_CLASS(wpan_phy_only_evt, | ||
44 | TP_PROTO(struct wpan_phy *wpan_phy), | ||
45 | TP_ARGS(wpan_phy), | ||
46 | TP_STRUCT__entry( | ||
47 | WPAN_PHY_ENTRY | ||
48 | ), | ||
49 | TP_fast_assign( | ||
50 | WPAN_PHY_ASSIGN; | ||
51 | ), | ||
52 | TP_printk(WPAN_PHY_PR_FMT, WPAN_PHY_PR_ARG) | ||
53 | ); | ||
54 | |||
55 | DEFINE_EVENT(wpan_phy_only_evt, 802154_rdev_suspend, | ||
56 | TP_PROTO(struct wpan_phy *wpan_phy), | ||
57 | TP_ARGS(wpan_phy) | ||
58 | ); | ||
59 | |||
60 | DEFINE_EVENT(wpan_phy_only_evt, 802154_rdev_resume, | ||
61 | TP_PROTO(struct wpan_phy *wpan_phy), | ||
62 | TP_ARGS(wpan_phy) | ||
63 | ); | ||
64 | |||
43 | TRACE_EVENT(802154_rdev_add_virtual_intf, | 65 | TRACE_EVENT(802154_rdev_add_virtual_intf, |
44 | TP_PROTO(struct wpan_phy *wpan_phy, char *name, | 66 | TP_PROTO(struct wpan_phy *wpan_phy, char *name, |
45 | enum nl802154_iftype type, __le64 extended_addr), | 67 | enum nl802154_iftype type, __le64 extended_addr), |
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index 317c4662e544..f7ba51e8b4ca 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c | |||
@@ -44,6 +44,49 @@ static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, | |||
44 | ieee802154_if_remove(sdata); | 44 | ieee802154_if_remove(sdata); |
45 | } | 45 | } |
46 | 46 | ||
47 | #ifdef CONFIG_PM | ||
48 | static int ieee802154_suspend(struct wpan_phy *wpan_phy) | ||
49 | { | ||
50 | struct ieee802154_local *local = wpan_phy_priv(wpan_phy); | ||
51 | |||
52 | if (!local->open_count) | ||
53 | goto suspend; | ||
54 | |||
55 | ieee802154_stop_queue(&local->hw); | ||
56 | synchronize_net(); | ||
57 | |||
58 | /* stop hardware - this must stop RX */ | ||
59 | ieee802154_stop_device(local); | ||
60 | |||
61 | suspend: | ||
62 | local->suspended = true; | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int ieee802154_resume(struct wpan_phy *wpan_phy) | ||
67 | { | ||
68 | struct ieee802154_local *local = wpan_phy_priv(wpan_phy); | ||
69 | int ret; | ||
70 | |||
71 | /* nothing to do if HW shouldn't run */ | ||
72 | if (!local->open_count) | ||
73 | goto wake_up; | ||
74 | |||
75 | /* restart hardware */ | ||
76 | ret = drv_start(local); | ||
77 | if (ret) | ||
78 | return ret; | ||
79 | |||
80 | wake_up: | ||
81 | ieee802154_wake_queue(&local->hw); | ||
82 | local->suspended = false; | ||
83 | return 0; | ||
84 | } | ||
85 | #else | ||
86 | #define ieee802154_suspend NULL | ||
87 | #define ieee802154_resume NULL | ||
88 | #endif | ||
89 | |||
47 | static int | 90 | static int |
48 | ieee802154_add_iface(struct wpan_phy *phy, const char *name, | 91 | ieee802154_add_iface(struct wpan_phy *phy, const char *name, |
49 | unsigned char name_assign_type, | 92 | unsigned char name_assign_type, |
@@ -145,13 +188,18 @@ static int | |||
145 | ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | 188 | ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, |
146 | __le16 pan_id) | 189 | __le16 pan_id) |
147 | { | 190 | { |
191 | int ret; | ||
192 | |||
148 | ASSERT_RTNL(); | 193 | ASSERT_RTNL(); |
149 | 194 | ||
150 | if (wpan_dev->pan_id == pan_id) | 195 | if (wpan_dev->pan_id == pan_id) |
151 | return 0; | 196 | return 0; |
152 | 197 | ||
153 | wpan_dev->pan_id = pan_id; | 198 | ret = mac802154_wpan_update_llsec(wpan_dev->netdev); |
154 | return 0; | 199 | if (!ret) |
200 | wpan_dev->pan_id = pan_id; | ||
201 | |||
202 | return ret; | ||
155 | } | 203 | } |
156 | 204 | ||
157 | static int | 205 | static int |
@@ -227,6 +275,8 @@ ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | |||
227 | const struct cfg802154_ops mac802154_config_ops = { | 275 | const struct cfg802154_ops mac802154_config_ops = { |
228 | .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated, | 276 | .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated, |
229 | .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated, | 277 | .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated, |
278 | .suspend = ieee802154_suspend, | ||
279 | .resume = ieee802154_resume, | ||
230 | .add_virtual_intf = ieee802154_add_iface, | 280 | .add_virtual_intf = ieee802154_add_iface, |
231 | .del_virtual_intf = ieee802154_del_iface, | 281 | .del_virtual_intf = ieee802154_del_iface, |
232 | .set_channel = ieee802154_set_channel, | 282 | .set_channel = ieee802154_set_channel, |
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 34755d5751a4..56ccffa3f2bf 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h | |||
@@ -56,9 +56,13 @@ struct ieee802154_local { | |||
56 | struct hrtimer ifs_timer; | 56 | struct hrtimer ifs_timer; |
57 | 57 | ||
58 | bool started; | 58 | bool started; |
59 | bool suspended; | ||
59 | 60 | ||
60 | struct tasklet_struct tasklet; | 61 | struct tasklet_struct tasklet; |
61 | struct sk_buff_head skb_queue; | 62 | struct sk_buff_head skb_queue; |
63 | |||
64 | struct sk_buff *tx_skb; | ||
65 | struct work_struct tx_work; | ||
62 | }; | 66 | }; |
63 | 67 | ||
64 | enum { | 68 | enum { |
@@ -94,8 +98,6 @@ struct ieee802154_sub_if_data { | |||
94 | struct mac802154_llsec sec; | 98 | struct mac802154_llsec sec; |
95 | }; | 99 | }; |
96 | 100 | ||
97 | #define MAC802154_CHAN_NONE 0xff /* No channel is assigned */ | ||
98 | |||
99 | /* utility functions/constants */ | 101 | /* utility functions/constants */ |
100 | extern const void *const mac802154_wpan_phy_privid; /* for wpan_phy privid */ | 102 | extern const void *const mac802154_wpan_phy_privid; /* for wpan_phy privid */ |
101 | 103 | ||
@@ -125,6 +127,8 @@ ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata) | |||
125 | 127 | ||
126 | extern struct ieee802154_mlme_ops mac802154_mlme_wpan; | 128 | extern struct ieee802154_mlme_ops mac802154_mlme_wpan; |
127 | 129 | ||
130 | void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb); | ||
131 | void ieee802154_xmit_worker(struct work_struct *work); | ||
128 | netdev_tx_t | 132 | netdev_tx_t |
129 | ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | 133 | ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); |
130 | netdev_tx_t | 134 | netdev_tx_t |
@@ -167,6 +171,8 @@ void mac802154_get_table(struct net_device *dev, | |||
167 | struct ieee802154_llsec_table **t); | 171 | struct ieee802154_llsec_table **t); |
168 | void mac802154_unlock_table(struct net_device *dev); | 172 | void mac802154_unlock_table(struct net_device *dev); |
169 | 173 | ||
174 | int mac802154_wpan_update_llsec(struct net_device *dev); | ||
175 | |||
170 | /* interface handling */ | 176 | /* interface handling */ |
171 | int ieee802154_iface_init(void); | 177 | int ieee802154_iface_init(void); |
172 | void ieee802154_iface_exit(void); | 178 | void ieee802154_iface_exit(void); |
@@ -176,5 +182,6 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name, | |||
176 | unsigned char name_assign_type, enum nl802154_iftype type, | 182 | unsigned char name_assign_type, enum nl802154_iftype type, |
177 | __le64 extended_addr); | 183 | __le64 extended_addr); |
178 | void ieee802154_remove_interfaces(struct ieee802154_local *local); | 184 | void ieee802154_remove_interfaces(struct ieee802154_local *local); |
185 | void ieee802154_stop_device(struct ieee802154_local *local); | ||
179 | 186 | ||
180 | #endif /* __IEEE802154_I_H */ | 187 | #endif /* __IEEE802154_I_H */ |
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 8b698246a51b..416de903e467 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include "ieee802154_i.h" | 30 | #include "ieee802154_i.h" |
31 | #include "driver-ops.h" | 31 | #include "driver-ops.h" |
32 | 32 | ||
33 | static int mac802154_wpan_update_llsec(struct net_device *dev) | 33 | int mac802154_wpan_update_llsec(struct net_device *dev) |
34 | { | 34 | { |
35 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | 35 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); |
36 | struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); | 36 | struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); |
@@ -314,11 +314,8 @@ static int mac802154_slave_close(struct net_device *dev) | |||
314 | 314 | ||
315 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 315 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
316 | 316 | ||
317 | if (!local->open_count) { | 317 | if (!local->open_count) |
318 | flush_workqueue(local->workqueue); | 318 | ieee802154_stop_device(local); |
319 | hrtimer_cancel(&local->ifs_timer); | ||
320 | drv_stop(local); | ||
321 | } | ||
322 | 319 | ||
323 | return 0; | 320 | return 0; |
324 | } | 321 | } |
@@ -471,6 +468,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, | |||
471 | enum nl802154_iftype type) | 468 | enum nl802154_iftype type) |
472 | { | 469 | { |
473 | struct wpan_dev *wpan_dev = &sdata->wpan_dev; | 470 | struct wpan_dev *wpan_dev = &sdata->wpan_dev; |
471 | int ret; | ||
474 | u8 tmp; | 472 | u8 tmp; |
475 | 473 | ||
476 | /* set some type-dependent values */ | 474 | /* set some type-dependent values */ |
@@ -505,6 +503,10 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, | |||
505 | mutex_init(&sdata->sec_mtx); | 503 | mutex_init(&sdata->sec_mtx); |
506 | 504 | ||
507 | mac802154_llsec_init(&sdata->sec); | 505 | mac802154_llsec_init(&sdata->sec); |
506 | ret = mac802154_wpan_update_llsec(sdata->dev); | ||
507 | if (ret < 0) | ||
508 | return ret; | ||
509 | |||
508 | break; | 510 | break; |
509 | case NL802154_IFTYPE_MONITOR: | 511 | case NL802154_IFTYPE_MONITOR: |
510 | sdata->dev->destructor = free_netdev; | 512 | sdata->dev->destructor = free_netdev; |
diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 356b346e1ee8..9e55431b9a5c 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c | |||
@@ -40,7 +40,7 @@ static void ieee802154_tasklet_handler(unsigned long data) | |||
40 | * netstack. | 40 | * netstack. |
41 | */ | 41 | */ |
42 | skb->pkt_type = 0; | 42 | skb->pkt_type = 0; |
43 | ieee802154_rx(&local->hw, skb); | 43 | ieee802154_rx(local, skb); |
44 | break; | 44 | break; |
45 | default: | 45 | default: |
46 | WARN(1, "mac802154: Packet is of unknown type %d\n", | 46 | WARN(1, "mac802154: Packet is of unknown type %d\n", |
@@ -58,11 +58,9 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) | |||
58 | struct ieee802154_local *local; | 58 | struct ieee802154_local *local; |
59 | size_t priv_size; | 59 | size_t priv_size; |
60 | 60 | ||
61 | if (!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed || | 61 | if (WARN_ON(!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed || |
62 | !ops->start || !ops->stop || !ops->set_channel) { | 62 | !ops->start || !ops->stop || !ops->set_channel)) |
63 | pr_err("undefined IEEE802.15.4 device operations\n"); | ||
64 | return NULL; | 63 | return NULL; |
65 | } | ||
66 | 64 | ||
67 | /* Ensure 32-byte alignment of our private data and hw private data. | 65 | /* Ensure 32-byte alignment of our private data and hw private data. |
68 | * We use the wpan_phy priv data for both our ieee802154_local and for | 66 | * We use the wpan_phy priv data for both our ieee802154_local and for |
@@ -107,6 +105,8 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) | |||
107 | 105 | ||
108 | skb_queue_head_init(&local->skb_queue); | 106 | skb_queue_head_init(&local->skb_queue); |
109 | 107 | ||
108 | INIT_WORK(&local->tx_work, ieee802154_xmit_worker); | ||
109 | |||
110 | /* init supported flags with 802.15.4 default ranges */ | 110 | /* init supported flags with 802.15.4 default ranges */ |
111 | phy->supported.max_minbe = 8; | 111 | phy->supported.max_minbe = 8; |
112 | phy->supported.min_maxbe = 3; | 112 | phy->supported.min_maxbe = 3; |
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c index d93ad2d4a4fc..d1c33c1d6b9b 100644 --- a/net/mac802154/rx.c +++ b/net/mac802154/rx.c | |||
@@ -246,13 +246,15 @@ ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb) | |||
246 | } | 246 | } |
247 | } | 247 | } |
248 | 248 | ||
249 | void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb) | 249 | void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb) |
250 | { | 250 | { |
251 | struct ieee802154_local *local = hw_to_local(hw); | ||
252 | u16 crc; | 251 | u16 crc; |
253 | 252 | ||
254 | WARN_ON_ONCE(softirq_count() == 0); | 253 | WARN_ON_ONCE(softirq_count() == 0); |
255 | 254 | ||
255 | if (local->suspended) | ||
256 | goto drop; | ||
257 | |||
256 | /* TODO: When a transceiver omits the checksum here, we | 258 | /* TODO: When a transceiver omits the checksum here, we |
257 | * add an own calculated one. This is currently an ugly | 259 | * add an own calculated one. This is currently an ugly |
258 | * solution because the monitor needs a crc here. | 260 | * solution because the monitor needs a crc here. |
@@ -273,8 +275,7 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb) | |||
273 | crc = crc_ccitt(0, skb->data, skb->len); | 275 | crc = crc_ccitt(0, skb->data, skb->len); |
274 | if (crc) { | 276 | if (crc) { |
275 | rcu_read_unlock(); | 277 | rcu_read_unlock(); |
276 | kfree_skb(skb); | 278 | goto drop; |
277 | return; | ||
278 | } | 279 | } |
279 | } | 280 | } |
280 | /* remove crc */ | 281 | /* remove crc */ |
@@ -283,8 +284,11 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb) | |||
283 | __ieee802154_rx_handle_packet(local, skb); | 284 | __ieee802154_rx_handle_packet(local, skb); |
284 | 285 | ||
285 | rcu_read_unlock(); | 286 | rcu_read_unlock(); |
287 | |||
288 | return; | ||
289 | drop: | ||
290 | kfree_skb(skb); | ||
286 | } | 291 | } |
287 | EXPORT_SYMBOL(ieee802154_rx); | ||
288 | 292 | ||
289 | void | 293 | void |
290 | ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb, u8 lqi) | 294 | ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb, u8 lqi) |
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c index c62e95695c78..7ed439172f30 100644 --- a/net/mac802154/tx.c +++ b/net/mac802154/tx.c | |||
@@ -30,23 +30,11 @@ | |||
30 | #include "ieee802154_i.h" | 30 | #include "ieee802154_i.h" |
31 | #include "driver-ops.h" | 31 | #include "driver-ops.h" |
32 | 32 | ||
33 | /* IEEE 802.15.4 transceivers can sleep during the xmit session, so process | 33 | void ieee802154_xmit_worker(struct work_struct *work) |
34 | * packets through the workqueue. | ||
35 | */ | ||
36 | struct ieee802154_xmit_cb { | ||
37 | struct sk_buff *skb; | ||
38 | struct work_struct work; | ||
39 | struct ieee802154_local *local; | ||
40 | }; | ||
41 | |||
42 | static struct ieee802154_xmit_cb ieee802154_xmit_cb; | ||
43 | |||
44 | static void ieee802154_xmit_worker(struct work_struct *work) | ||
45 | { | 34 | { |
46 | struct ieee802154_xmit_cb *cb = | 35 | struct ieee802154_local *local = |
47 | container_of(work, struct ieee802154_xmit_cb, work); | 36 | container_of(work, struct ieee802154_local, tx_work); |
48 | struct ieee802154_local *local = cb->local; | 37 | struct sk_buff *skb = local->tx_skb; |
49 | struct sk_buff *skb = cb->skb; | ||
50 | struct net_device *dev = skb->dev; | 38 | struct net_device *dev = skb->dev; |
51 | int res; | 39 | int res; |
52 | 40 | ||
@@ -106,11 +94,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb) | |||
106 | dev->stats.tx_packets++; | 94 | dev->stats.tx_packets++; |
107 | dev->stats.tx_bytes += skb->len; | 95 | dev->stats.tx_bytes += skb->len; |
108 | } else { | 96 | } else { |
109 | INIT_WORK(&ieee802154_xmit_cb.work, ieee802154_xmit_worker); | 97 | local->tx_skb = skb; |
110 | ieee802154_xmit_cb.skb = skb; | 98 | queue_work(local->workqueue, &local->tx_work); |
111 | ieee802154_xmit_cb.local = local; | ||
112 | |||
113 | queue_work(local->workqueue, &ieee802154_xmit_cb.work); | ||
114 | } | 99 | } |
115 | 100 | ||
116 | return NETDEV_TX_OK; | 101 | return NETDEV_TX_OK; |
diff --git a/net/mac802154/util.c b/net/mac802154/util.c index 583435f38930..f9fd0957ab67 100644 --- a/net/mac802154/util.c +++ b/net/mac802154/util.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "ieee802154_i.h" | 16 | #include "ieee802154_i.h" |
17 | #include "driver-ops.h" | ||
17 | 18 | ||
18 | /* privid for wpan_phys to determine whether they belong to us or not */ | 19 | /* privid for wpan_phys to determine whether they belong to us or not */ |
19 | const void *const mac802154_wpan_phy_privid = &mac802154_wpan_phy_privid; | 20 | const void *const mac802154_wpan_phy_privid = &mac802154_wpan_phy_privid; |
@@ -92,3 +93,10 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb, | |||
92 | dev_consume_skb_any(skb); | 93 | dev_consume_skb_any(skb); |
93 | } | 94 | } |
94 | EXPORT_SYMBOL(ieee802154_xmit_complete); | 95 | EXPORT_SYMBOL(ieee802154_xmit_complete); |
96 | |||
97 | void ieee802154_stop_device(struct ieee802154_local *local) | ||
98 | { | ||
99 | flush_workqueue(local->workqueue); | ||
100 | hrtimer_cancel(&local->ifs_timer); | ||
101 | drv_stop(local); | ||
102 | } | ||