diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-04-12 16:18:44 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-12 16:18:44 -0400 |
commit | 252f4bf400df1712408fe83ba199a66a1b57ab1d (patch) | |
tree | e07fa00abdd55b31e22567786c78635f32c6a66c /net | |
parent | 6ba1037c3d871ab70e342631516dbf841c35b086 (diff) | |
parent | b37e3b6d64358604960b35e8ecbb7aed22e0926e (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/ath/ar9170/main.c
drivers/net/wireless/ath/ar9170/phy.c
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
Diffstat (limited to 'net')
35 files changed, 1109 insertions, 357 deletions
diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index 70672544db86..8e6c06158f8e 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h | |||
@@ -23,88 +23,88 @@ | |||
23 | #include <linux/crc32.h> | 23 | #include <linux/crc32.h> |
24 | #include <net/bluetooth/bluetooth.h> | 24 | #include <net/bluetooth/bluetooth.h> |
25 | 25 | ||
26 | // Limits | 26 | /* Limits */ |
27 | #define BNEP_MAX_PROTO_FILTERS 5 | 27 | #define BNEP_MAX_PROTO_FILTERS 5 |
28 | #define BNEP_MAX_MULTICAST_FILTERS 20 | 28 | #define BNEP_MAX_MULTICAST_FILTERS 20 |
29 | 29 | ||
30 | // UUIDs | 30 | /* UUIDs */ |
31 | #define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB | 31 | #define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB |
32 | #define BNEP_UUID16 0x02 | 32 | #define BNEP_UUID16 0x02 |
33 | #define BNEP_UUID32 0x04 | 33 | #define BNEP_UUID32 0x04 |
34 | #define BNEP_UUID128 0x16 | 34 | #define BNEP_UUID128 0x16 |
35 | 35 | ||
36 | #define BNEP_SVC_PANU 0x1115 | 36 | #define BNEP_SVC_PANU 0x1115 |
37 | #define BNEP_SVC_NAP 0x1116 | 37 | #define BNEP_SVC_NAP 0x1116 |
38 | #define BNEP_SVC_GN 0x1117 | 38 | #define BNEP_SVC_GN 0x1117 |
39 | 39 | ||
40 | // Packet types | 40 | /* Packet types */ |
41 | #define BNEP_GENERAL 0x00 | 41 | #define BNEP_GENERAL 0x00 |
42 | #define BNEP_CONTROL 0x01 | 42 | #define BNEP_CONTROL 0x01 |
43 | #define BNEP_COMPRESSED 0x02 | 43 | #define BNEP_COMPRESSED 0x02 |
44 | #define BNEP_COMPRESSED_SRC_ONLY 0x03 | 44 | #define BNEP_COMPRESSED_SRC_ONLY 0x03 |
45 | #define BNEP_COMPRESSED_DST_ONLY 0x04 | 45 | #define BNEP_COMPRESSED_DST_ONLY 0x04 |
46 | 46 | ||
47 | // Control types | 47 | /* Control types */ |
48 | #define BNEP_CMD_NOT_UNDERSTOOD 0x00 | 48 | #define BNEP_CMD_NOT_UNDERSTOOD 0x00 |
49 | #define BNEP_SETUP_CONN_REQ 0x01 | 49 | #define BNEP_SETUP_CONN_REQ 0x01 |
50 | #define BNEP_SETUP_CONN_RSP 0x02 | 50 | #define BNEP_SETUP_CONN_RSP 0x02 |
51 | #define BNEP_FILTER_NET_TYPE_SET 0x03 | 51 | #define BNEP_FILTER_NET_TYPE_SET 0x03 |
52 | #define BNEP_FILTER_NET_TYPE_RSP 0x04 | 52 | #define BNEP_FILTER_NET_TYPE_RSP 0x04 |
53 | #define BNEP_FILTER_MULTI_ADDR_SET 0x05 | 53 | #define BNEP_FILTER_MULTI_ADDR_SET 0x05 |
54 | #define BNEP_FILTER_MULTI_ADDR_RSP 0x06 | 54 | #define BNEP_FILTER_MULTI_ADDR_RSP 0x06 |
55 | 55 | ||
56 | // Extension types | 56 | /* Extension types */ |
57 | #define BNEP_EXT_CONTROL 0x00 | 57 | #define BNEP_EXT_CONTROL 0x00 |
58 | 58 | ||
59 | // Response messages | 59 | /* Response messages */ |
60 | #define BNEP_SUCCESS 0x00 | 60 | #define BNEP_SUCCESS 0x00 |
61 | 61 | ||
62 | #define BNEP_CONN_INVALID_DST 0x01 | 62 | #define BNEP_CONN_INVALID_DST 0x01 |
63 | #define BNEP_CONN_INVALID_SRC 0x02 | 63 | #define BNEP_CONN_INVALID_SRC 0x02 |
64 | #define BNEP_CONN_INVALID_SVC 0x03 | 64 | #define BNEP_CONN_INVALID_SVC 0x03 |
65 | #define BNEP_CONN_NOT_ALLOWED 0x04 | 65 | #define BNEP_CONN_NOT_ALLOWED 0x04 |
66 | 66 | ||
67 | #define BNEP_FILTER_UNSUPPORTED_REQ 0x01 | 67 | #define BNEP_FILTER_UNSUPPORTED_REQ 0x01 |
68 | #define BNEP_FILTER_INVALID_RANGE 0x02 | 68 | #define BNEP_FILTER_INVALID_RANGE 0x02 |
69 | #define BNEP_FILTER_INVALID_MCADDR 0x02 | 69 | #define BNEP_FILTER_INVALID_MCADDR 0x02 |
70 | #define BNEP_FILTER_LIMIT_REACHED 0x03 | 70 | #define BNEP_FILTER_LIMIT_REACHED 0x03 |
71 | #define BNEP_FILTER_DENIED_SECURITY 0x04 | 71 | #define BNEP_FILTER_DENIED_SECURITY 0x04 |
72 | 72 | ||
73 | // L2CAP settings | 73 | /* L2CAP settings */ |
74 | #define BNEP_MTU 1691 | 74 | #define BNEP_MTU 1691 |
75 | #define BNEP_PSM 0x0f | 75 | #define BNEP_PSM 0x0f |
76 | #define BNEP_FLUSH_TO 0xffff | 76 | #define BNEP_FLUSH_TO 0xffff |
77 | #define BNEP_CONNECT_TO 15 | 77 | #define BNEP_CONNECT_TO 15 |
78 | #define BNEP_FILTER_TO 15 | 78 | #define BNEP_FILTER_TO 15 |
79 | 79 | ||
80 | // Headers | 80 | /* Headers */ |
81 | #define BNEP_TYPE_MASK 0x7f | 81 | #define BNEP_TYPE_MASK 0x7f |
82 | #define BNEP_EXT_HEADER 0x80 | 82 | #define BNEP_EXT_HEADER 0x80 |
83 | 83 | ||
84 | struct bnep_setup_conn_req { | 84 | struct bnep_setup_conn_req { |
85 | __u8 type; | 85 | __u8 type; |
86 | __u8 ctrl; | 86 | __u8 ctrl; |
87 | __u8 uuid_size; | 87 | __u8 uuid_size; |
88 | __u8 service[0]; | 88 | __u8 service[0]; |
89 | } __packed; | 89 | } __packed; |
90 | 90 | ||
91 | struct bnep_set_filter_req { | 91 | struct bnep_set_filter_req { |
92 | __u8 type; | 92 | __u8 type; |
93 | __u8 ctrl; | 93 | __u8 ctrl; |
94 | __be16 len; | 94 | __be16 len; |
95 | __u8 list[0]; | 95 | __u8 list[0]; |
96 | } __packed; | 96 | } __packed; |
97 | 97 | ||
98 | struct bnep_control_rsp { | 98 | struct bnep_control_rsp { |
99 | __u8 type; | 99 | __u8 type; |
100 | __u8 ctrl; | 100 | __u8 ctrl; |
101 | __be16 resp; | 101 | __be16 resp; |
102 | } __packed; | 102 | } __packed; |
103 | 103 | ||
104 | struct bnep_ext_hdr { | 104 | struct bnep_ext_hdr { |
105 | __u8 type; | 105 | __u8 type; |
106 | __u8 len; | 106 | __u8 len; |
107 | __u8 data[0]; | 107 | __u8 data[0]; |
108 | } __packed; | 108 | } __packed; |
109 | 109 | ||
110 | /* BNEP ioctl defines */ | 110 | /* BNEP ioctl defines */ |
@@ -114,10 +114,10 @@ struct bnep_ext_hdr { | |||
114 | #define BNEPGETCONNINFO _IOR('B', 211, int) | 114 | #define BNEPGETCONNINFO _IOR('B', 211, int) |
115 | 115 | ||
116 | struct bnep_connadd_req { | 116 | struct bnep_connadd_req { |
117 | int sock; // Connected socket | 117 | int sock; /* Connected socket */ |
118 | __u32 flags; | 118 | __u32 flags; |
119 | __u16 role; | 119 | __u16 role; |
120 | char device[16]; // Name of the Ethernet device | 120 | char device[16]; /* Name of the Ethernet device */ |
121 | }; | 121 | }; |
122 | 122 | ||
123 | struct bnep_conndel_req { | 123 | struct bnep_conndel_req { |
@@ -148,14 +148,14 @@ int bnep_del_connection(struct bnep_conndel_req *req); | |||
148 | int bnep_get_connlist(struct bnep_connlist_req *req); | 148 | int bnep_get_connlist(struct bnep_connlist_req *req); |
149 | int bnep_get_conninfo(struct bnep_conninfo *ci); | 149 | int bnep_get_conninfo(struct bnep_conninfo *ci); |
150 | 150 | ||
151 | // BNEP sessions | 151 | /* BNEP sessions */ |
152 | struct bnep_session { | 152 | struct bnep_session { |
153 | struct list_head list; | 153 | struct list_head list; |
154 | 154 | ||
155 | unsigned int role; | 155 | unsigned int role; |
156 | unsigned long state; | 156 | unsigned long state; |
157 | unsigned long flags; | 157 | unsigned long flags; |
158 | atomic_t killed; | 158 | struct task_struct *task; |
159 | 159 | ||
160 | struct ethhdr eh; | 160 | struct ethhdr eh; |
161 | struct msghdr msg; | 161 | struct msghdr msg; |
@@ -173,7 +173,7 @@ void bnep_sock_cleanup(void); | |||
173 | 173 | ||
174 | static inline int bnep_mc_hash(__u8 *addr) | 174 | static inline int bnep_mc_hash(__u8 *addr) |
175 | { | 175 | { |
176 | return (crc32_be(~0, addr, ETH_ALEN) >> 26); | 176 | return crc32_be(~0, addr, ETH_ALEN) >> 26; |
177 | } | 177 | } |
178 | 178 | ||
179 | #endif | 179 | #endif |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 03d4d1245d58..ca39fcf010ce 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
37 | #include <linux/net.h> | 37 | #include <linux/net.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/kthread.h> | ||
39 | #include <net/sock.h> | 40 | #include <net/sock.h> |
40 | 41 | ||
41 | #include <linux/socket.h> | 42 | #include <linux/socket.h> |
@@ -131,7 +132,8 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len | |||
131 | return -EILSEQ; | 132 | return -EILSEQ; |
132 | 133 | ||
133 | n = get_unaligned_be16(data); | 134 | n = get_unaligned_be16(data); |
134 | data++; len -= 2; | 135 | data++; |
136 | len -= 2; | ||
135 | 137 | ||
136 | if (len < n) | 138 | if (len < n) |
137 | return -EILSEQ; | 139 | return -EILSEQ; |
@@ -176,7 +178,8 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) | |||
176 | return -EILSEQ; | 178 | return -EILSEQ; |
177 | 179 | ||
178 | n = get_unaligned_be16(data); | 180 | n = get_unaligned_be16(data); |
179 | data += 2; len -= 2; | 181 | data += 2; |
182 | len -= 2; | ||
180 | 183 | ||
181 | if (len < n) | 184 | if (len < n) |
182 | return -EILSEQ; | 185 | return -EILSEQ; |
@@ -187,6 +190,8 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) | |||
187 | n /= (ETH_ALEN * 2); | 190 | n /= (ETH_ALEN * 2); |
188 | 191 | ||
189 | if (n > 0) { | 192 | if (n > 0) { |
193 | int i; | ||
194 | |||
190 | s->mc_filter = 0; | 195 | s->mc_filter = 0; |
191 | 196 | ||
192 | /* Always send broadcast */ | 197 | /* Always send broadcast */ |
@@ -196,18 +201,22 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) | |||
196 | for (; n > 0; n--) { | 201 | for (; n > 0; n--) { |
197 | u8 a1[6], *a2; | 202 | u8 a1[6], *a2; |
198 | 203 | ||
199 | memcpy(a1, data, ETH_ALEN); data += ETH_ALEN; | 204 | memcpy(a1, data, ETH_ALEN); |
200 | a2 = data; data += ETH_ALEN; | 205 | data += ETH_ALEN; |
206 | a2 = data; | ||
207 | data += ETH_ALEN; | ||
201 | 208 | ||
202 | BT_DBG("mc filter %s -> %s", | 209 | BT_DBG("mc filter %s -> %s", |
203 | batostr((void *) a1), batostr((void *) a2)); | 210 | batostr((void *) a1), batostr((void *) a2)); |
204 | 211 | ||
205 | #define INCA(a) { int i = 5; while (i >=0 && ++a[i--] == 0); } | ||
206 | |||
207 | /* Iterate from a1 to a2 */ | 212 | /* Iterate from a1 to a2 */ |
208 | set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); | 213 | set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); |
209 | while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) { | 214 | while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) { |
210 | INCA(a1); | 215 | /* Increment a1 */ |
216 | i = 5; | ||
217 | while (i >= 0 && ++a1[i--] == 0) | ||
218 | ; | ||
219 | |||
211 | set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); | 220 | set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); |
212 | } | 221 | } |
213 | } | 222 | } |
@@ -227,7 +236,8 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len) | |||
227 | u8 cmd = *(u8 *)data; | 236 | u8 cmd = *(u8 *)data; |
228 | int err = 0; | 237 | int err = 0; |
229 | 238 | ||
230 | data++; len--; | 239 | data++; |
240 | len--; | ||
231 | 241 | ||
232 | switch (cmd) { | 242 | switch (cmd) { |
233 | case BNEP_CMD_NOT_UNDERSTOOD: | 243 | case BNEP_CMD_NOT_UNDERSTOOD: |
@@ -302,7 +312,6 @@ static u8 __bnep_rx_hlen[] = { | |||
302 | ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */ | 312 | ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */ |
303 | ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */ | 313 | ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */ |
304 | }; | 314 | }; |
305 | #define BNEP_RX_TYPES (sizeof(__bnep_rx_hlen) - 1) | ||
306 | 315 | ||
307 | static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) | 316 | static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) |
308 | { | 317 | { |
@@ -312,9 +321,10 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) | |||
312 | 321 | ||
313 | dev->stats.rx_bytes += skb->len; | 322 | dev->stats.rx_bytes += skb->len; |
314 | 323 | ||
315 | type = *(u8 *) skb->data; skb_pull(skb, 1); | 324 | type = *(u8 *) skb->data; |
325 | skb_pull(skb, 1); | ||
316 | 326 | ||
317 | if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES) | 327 | if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen)) |
318 | goto badframe; | 328 | goto badframe; |
319 | 329 | ||
320 | if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) { | 330 | if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) { |
@@ -367,14 +377,14 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) | |||
367 | 377 | ||
368 | case BNEP_COMPRESSED_DST_ONLY: | 378 | case BNEP_COMPRESSED_DST_ONLY: |
369 | memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), | 379 | memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), |
370 | ETH_ALEN); | 380 | ETH_ALEN); |
371 | memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, | 381 | memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, |
372 | ETH_ALEN + 2); | 382 | ETH_ALEN + 2); |
373 | break; | 383 | break; |
374 | 384 | ||
375 | case BNEP_GENERAL: | 385 | case BNEP_GENERAL: |
376 | memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb), | 386 | memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb), |
377 | ETH_ALEN * 2); | 387 | ETH_ALEN * 2); |
378 | put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); | 388 | put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); |
379 | break; | 389 | break; |
380 | } | 390 | } |
@@ -470,15 +480,14 @@ static int bnep_session(void *arg) | |||
470 | 480 | ||
471 | BT_DBG(""); | 481 | BT_DBG(""); |
472 | 482 | ||
473 | daemonize("kbnepd %s", dev->name); | ||
474 | set_user_nice(current, -15); | 483 | set_user_nice(current, -15); |
475 | 484 | ||
476 | init_waitqueue_entry(&wait, current); | 485 | init_waitqueue_entry(&wait, current); |
477 | add_wait_queue(sk_sleep(sk), &wait); | 486 | add_wait_queue(sk_sleep(sk), &wait); |
478 | while (!atomic_read(&s->killed)) { | 487 | while (!kthread_should_stop()) { |
479 | set_current_state(TASK_INTERRUPTIBLE); | 488 | set_current_state(TASK_INTERRUPTIBLE); |
480 | 489 | ||
481 | // RX | 490 | /* RX */ |
482 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 491 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { |
483 | skb_orphan(skb); | 492 | skb_orphan(skb); |
484 | bnep_rx_frame(s, skb); | 493 | bnep_rx_frame(s, skb); |
@@ -487,7 +496,7 @@ static int bnep_session(void *arg) | |||
487 | if (sk->sk_state != BT_CONNECTED) | 496 | if (sk->sk_state != BT_CONNECTED) |
488 | break; | 497 | break; |
489 | 498 | ||
490 | // TX | 499 | /* TX */ |
491 | while ((skb = skb_dequeue(&sk->sk_write_queue))) | 500 | while ((skb = skb_dequeue(&sk->sk_write_queue))) |
492 | if (bnep_tx_frame(s, skb)) | 501 | if (bnep_tx_frame(s, skb)) |
493 | break; | 502 | break; |
@@ -555,8 +564,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
555 | 564 | ||
556 | /* session struct allocated as private part of net_device */ | 565 | /* session struct allocated as private part of net_device */ |
557 | dev = alloc_netdev(sizeof(struct bnep_session), | 566 | dev = alloc_netdev(sizeof(struct bnep_session), |
558 | (*req->device) ? req->device : "bnep%d", | 567 | (*req->device) ? req->device : "bnep%d", |
559 | bnep_net_setup); | 568 | bnep_net_setup); |
560 | if (!dev) | 569 | if (!dev) |
561 | return -ENOMEM; | 570 | return -ENOMEM; |
562 | 571 | ||
@@ -571,7 +580,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
571 | s = netdev_priv(dev); | 580 | s = netdev_priv(dev); |
572 | 581 | ||
573 | /* This is rx header therefore addresses are swapped. | 582 | /* This is rx header therefore addresses are swapped. |
574 | * ie eh.h_dest is our local address. */ | 583 | * ie. eh.h_dest is our local address. */ |
575 | memcpy(s->eh.h_dest, &src, ETH_ALEN); | 584 | memcpy(s->eh.h_dest, &src, ETH_ALEN); |
576 | memcpy(s->eh.h_source, &dst, ETH_ALEN); | 585 | memcpy(s->eh.h_source, &dst, ETH_ALEN); |
577 | memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); | 586 | memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); |
@@ -597,17 +606,17 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
597 | SET_NETDEV_DEVTYPE(dev, &bnep_type); | 606 | SET_NETDEV_DEVTYPE(dev, &bnep_type); |
598 | 607 | ||
599 | err = register_netdev(dev); | 608 | err = register_netdev(dev); |
600 | if (err) { | 609 | if (err) |
601 | goto failed; | 610 | goto failed; |
602 | } | ||
603 | 611 | ||
604 | __bnep_link_session(s); | 612 | __bnep_link_session(s); |
605 | 613 | ||
606 | err = kernel_thread(bnep_session, s, CLONE_KERNEL); | 614 | s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); |
607 | if (err < 0) { | 615 | if (IS_ERR(s->task)) { |
608 | /* Session thread start failed, gotta cleanup. */ | 616 | /* Session thread start failed, gotta cleanup. */ |
609 | unregister_netdev(dev); | 617 | unregister_netdev(dev); |
610 | __bnep_unlink_session(s); | 618 | __bnep_unlink_session(s); |
619 | err = PTR_ERR(s->task); | ||
611 | goto failed; | 620 | goto failed; |
612 | } | 621 | } |
613 | 622 | ||
@@ -631,15 +640,9 @@ int bnep_del_connection(struct bnep_conndel_req *req) | |||
631 | down_read(&bnep_session_sem); | 640 | down_read(&bnep_session_sem); |
632 | 641 | ||
633 | s = __bnep_get_session(req->dst); | 642 | s = __bnep_get_session(req->dst); |
634 | if (s) { | 643 | if (s) |
635 | /* Wakeup user-space which is polling for socket errors. | 644 | kthread_stop(s->task); |
636 | * This is temporary hack until we have shutdown in L2CAP */ | 645 | else |
637 | s->sock->sk->sk_err = EUNATCH; | ||
638 | |||
639 | /* Kill session thread */ | ||
640 | atomic_inc(&s->killed); | ||
641 | wake_up_interruptible(sk_sleep(s->sock->sk)); | ||
642 | } else | ||
643 | err = -ENOENT; | 646 | err = -ENOENT; |
644 | 647 | ||
645 | up_read(&bnep_session_sem); | 648 | up_read(&bnep_session_sem); |
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index d935da71ab3b..17800b1d28ea 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -39,10 +39,10 @@ | |||
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/compat.h> | 40 | #include <linux/compat.h> |
41 | #include <linux/gfp.h> | 41 | #include <linux/gfp.h> |
42 | #include <linux/uaccess.h> | ||
42 | #include <net/sock.h> | 43 | #include <net/sock.h> |
43 | 44 | ||
44 | #include <asm/system.h> | 45 | #include <asm/system.h> |
45 | #include <asm/uaccess.h> | ||
46 | 46 | ||
47 | #include "bnep.h" | 47 | #include "bnep.h" |
48 | 48 | ||
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index 67cff810c77d..744233cba244 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/ioctl.h> | 35 | #include <linux/ioctl.h> |
36 | #include <linux/file.h> | 36 | #include <linux/file.h> |
37 | #include <linux/wait.h> | 37 | #include <linux/wait.h> |
38 | #include <linux/kthread.h> | ||
38 | #include <net/sock.h> | 39 | #include <net/sock.h> |
39 | 40 | ||
40 | #include <linux/isdn/capilli.h> | 41 | #include <linux/isdn/capilli.h> |
@@ -143,7 +144,7 @@ static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb) | |||
143 | 144 | ||
144 | skb_queue_tail(&session->transmit, skb); | 145 | skb_queue_tail(&session->transmit, skb); |
145 | 146 | ||
146 | cmtp_schedule(session); | 147 | wake_up_interruptible(sk_sleep(session->sock->sk)); |
147 | } | 148 | } |
148 | 149 | ||
149 | static void cmtp_send_interopmsg(struct cmtp_session *session, | 150 | static void cmtp_send_interopmsg(struct cmtp_session *session, |
@@ -386,8 +387,7 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl) | |||
386 | 387 | ||
387 | capi_ctr_down(ctrl); | 388 | capi_ctr_down(ctrl); |
388 | 389 | ||
389 | atomic_inc(&session->terminate); | 390 | kthread_stop(session->task); |
390 | cmtp_schedule(session); | ||
391 | } | 391 | } |
392 | 392 | ||
393 | static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) | 393 | static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) |
diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h index 785e79e953c5..db43b54ac9af 100644 --- a/net/bluetooth/cmtp/cmtp.h +++ b/net/bluetooth/cmtp/cmtp.h | |||
@@ -37,7 +37,7 @@ | |||
37 | #define CMTP_LOOPBACK 0 | 37 | #define CMTP_LOOPBACK 0 |
38 | 38 | ||
39 | struct cmtp_connadd_req { | 39 | struct cmtp_connadd_req { |
40 | int sock; // Connected socket | 40 | int sock; /* Connected socket */ |
41 | __u32 flags; | 41 | __u32 flags; |
42 | }; | 42 | }; |
43 | 43 | ||
@@ -81,7 +81,7 @@ struct cmtp_session { | |||
81 | 81 | ||
82 | char name[BTNAMSIZ]; | 82 | char name[BTNAMSIZ]; |
83 | 83 | ||
84 | atomic_t terminate; | 84 | struct task_struct *task; |
85 | 85 | ||
86 | wait_queue_head_t wait; | 86 | wait_queue_head_t wait; |
87 | 87 | ||
@@ -121,13 +121,6 @@ void cmtp_detach_device(struct cmtp_session *session); | |||
121 | 121 | ||
122 | void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb); | 122 | void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb); |
123 | 123 | ||
124 | static inline void cmtp_schedule(struct cmtp_session *session) | ||
125 | { | ||
126 | struct sock *sk = session->sock->sk; | ||
127 | |||
128 | wake_up_interruptible(sk_sleep(sk)); | ||
129 | } | ||
130 | |||
131 | /* CMTP init defines */ | 124 | /* CMTP init defines */ |
132 | int cmtp_init_sockets(void); | 125 | int cmtp_init_sockets(void); |
133 | void cmtp_cleanup_sockets(void); | 126 | void cmtp_cleanup_sockets(void); |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 964ea9126f9f..cce99b0919f5 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/ioctl.h> | 35 | #include <linux/ioctl.h> |
36 | #include <linux/file.h> | 36 | #include <linux/file.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/kthread.h> | ||
38 | #include <net/sock.h> | 39 | #include <net/sock.h> |
39 | 40 | ||
40 | #include <linux/isdn/capilli.h> | 41 | #include <linux/isdn/capilli.h> |
@@ -235,9 +236,12 @@ static void cmtp_process_transmit(struct cmtp_session *session) | |||
235 | 236 | ||
236 | size = min_t(uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->len); | 237 | size = min_t(uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->len); |
237 | 238 | ||
238 | if ((scb->id < 0) && ((scb->id = cmtp_alloc_block_id(session)) < 0)) { | 239 | if (scb->id < 0) { |
239 | skb_queue_head(&session->transmit, skb); | 240 | scb->id = cmtp_alloc_block_id(session); |
240 | break; | 241 | if (scb->id < 0) { |
242 | skb_queue_head(&session->transmit, skb); | ||
243 | break; | ||
244 | } | ||
241 | } | 245 | } |
242 | 246 | ||
243 | if (size < 256) { | 247 | if (size < 256) { |
@@ -284,12 +288,11 @@ static int cmtp_session(void *arg) | |||
284 | 288 | ||
285 | BT_DBG("session %p", session); | 289 | BT_DBG("session %p", session); |
286 | 290 | ||
287 | daemonize("kcmtpd_ctr_%d", session->num); | ||
288 | set_user_nice(current, -15); | 291 | set_user_nice(current, -15); |
289 | 292 | ||
290 | init_waitqueue_entry(&wait, current); | 293 | init_waitqueue_entry(&wait, current); |
291 | add_wait_queue(sk_sleep(sk), &wait); | 294 | add_wait_queue(sk_sleep(sk), &wait); |
292 | while (!atomic_read(&session->terminate)) { | 295 | while (!kthread_should_stop()) { |
293 | set_current_state(TASK_INTERRUPTIBLE); | 296 | set_current_state(TASK_INTERRUPTIBLE); |
294 | 297 | ||
295 | if (sk->sk_state != BT_CONNECTED) | 298 | if (sk->sk_state != BT_CONNECTED) |
@@ -367,9 +370,12 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) | |||
367 | 370 | ||
368 | __cmtp_link_session(session); | 371 | __cmtp_link_session(session); |
369 | 372 | ||
370 | err = kernel_thread(cmtp_session, session, CLONE_KERNEL); | 373 | session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", |
371 | if (err < 0) | 374 | session->num); |
375 | if (IS_ERR(session->task)) { | ||
376 | err = PTR_ERR(session->task); | ||
372 | goto unlink; | 377 | goto unlink; |
378 | } | ||
373 | 379 | ||
374 | if (!(session->flags & (1 << CMTP_LOOPBACK))) { | 380 | if (!(session->flags & (1 << CMTP_LOOPBACK))) { |
375 | err = cmtp_attach_device(session); | 381 | err = cmtp_attach_device(session); |
@@ -406,9 +412,8 @@ int cmtp_del_connection(struct cmtp_conndel_req *req) | |||
406 | /* Flush the transmit queue */ | 412 | /* Flush the transmit queue */ |
407 | skb_queue_purge(&session->transmit); | 413 | skb_queue_purge(&session->transmit); |
408 | 414 | ||
409 | /* Kill session thread */ | 415 | /* Stop session thread */ |
410 | atomic_inc(&session->terminate); | 416 | kthread_stop(session->task); |
411 | cmtp_schedule(session); | ||
412 | } else | 417 | } else |
413 | err = -ENOENT; | 418 | err = -ENOENT; |
414 | 419 | ||
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 7ea1979a8e4f..3f2dd5c25ae5 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c | |||
@@ -34,12 +34,12 @@ | |||
34 | #include <linux/file.h> | 34 | #include <linux/file.h> |
35 | #include <linux/compat.h> | 35 | #include <linux/compat.h> |
36 | #include <linux/gfp.h> | 36 | #include <linux/gfp.h> |
37 | #include <linux/uaccess.h> | ||
37 | #include <net/sock.h> | 38 | #include <net/sock.h> |
38 | 39 | ||
39 | #include <linux/isdn/capilli.h> | 40 | #include <linux/isdn/capilli.h> |
40 | 41 | ||
41 | #include <asm/system.h> | 42 | #include <asm/system.h> |
42 | #include <asm/uaccess.h> | ||
43 | 43 | ||
44 | #include "cmtp.h" | 44 | #include "cmtp.h" |
45 | 45 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index c83f618282f7..1ad4907766c7 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -56,7 +56,6 @@ | |||
56 | static void hci_cmd_task(unsigned long arg); | 56 | static void hci_cmd_task(unsigned long arg); |
57 | static void hci_rx_task(unsigned long arg); | 57 | static void hci_rx_task(unsigned long arg); |
58 | static void hci_tx_task(unsigned long arg); | 58 | static void hci_tx_task(unsigned long arg); |
59 | static void hci_notify(struct hci_dev *hdev, int event); | ||
60 | 59 | ||
61 | static DEFINE_RWLOCK(hci_task_lock); | 60 | static DEFINE_RWLOCK(hci_task_lock); |
62 | 61 | ||
@@ -1083,6 +1082,70 @@ static void hci_cmd_timer(unsigned long arg) | |||
1083 | tasklet_schedule(&hdev->cmd_task); | 1082 | tasklet_schedule(&hdev->cmd_task); |
1084 | } | 1083 | } |
1085 | 1084 | ||
1085 | struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, | ||
1086 | bdaddr_t *bdaddr) | ||
1087 | { | ||
1088 | struct oob_data *data; | ||
1089 | |||
1090 | list_for_each_entry(data, &hdev->remote_oob_data, list) | ||
1091 | if (bacmp(bdaddr, &data->bdaddr) == 0) | ||
1092 | return data; | ||
1093 | |||
1094 | return NULL; | ||
1095 | } | ||
1096 | |||
1097 | int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr) | ||
1098 | { | ||
1099 | struct oob_data *data; | ||
1100 | |||
1101 | data = hci_find_remote_oob_data(hdev, bdaddr); | ||
1102 | if (!data) | ||
1103 | return -ENOENT; | ||
1104 | |||
1105 | BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); | ||
1106 | |||
1107 | list_del(&data->list); | ||
1108 | kfree(data); | ||
1109 | |||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | int hci_remote_oob_data_clear(struct hci_dev *hdev) | ||
1114 | { | ||
1115 | struct oob_data *data, *n; | ||
1116 | |||
1117 | list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) { | ||
1118 | list_del(&data->list); | ||
1119 | kfree(data); | ||
1120 | } | ||
1121 | |||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | ||
1126 | u8 *randomizer) | ||
1127 | { | ||
1128 | struct oob_data *data; | ||
1129 | |||
1130 | data = hci_find_remote_oob_data(hdev, bdaddr); | ||
1131 | |||
1132 | if (!data) { | ||
1133 | data = kmalloc(sizeof(*data), GFP_ATOMIC); | ||
1134 | if (!data) | ||
1135 | return -ENOMEM; | ||
1136 | |||
1137 | bacpy(&data->bdaddr, bdaddr); | ||
1138 | list_add(&data->list, &hdev->remote_oob_data); | ||
1139 | } | ||
1140 | |||
1141 | memcpy(data->hash, hash, sizeof(data->hash)); | ||
1142 | memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); | ||
1143 | |||
1144 | BT_DBG("%s for %s", hdev->name, batostr(bdaddr)); | ||
1145 | |||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1086 | /* Register HCI device */ | 1149 | /* Register HCI device */ |
1087 | int hci_register_dev(struct hci_dev *hdev) | 1150 | int hci_register_dev(struct hci_dev *hdev) |
1088 | { | 1151 | { |
@@ -1147,6 +1210,8 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1147 | 1210 | ||
1148 | INIT_LIST_HEAD(&hdev->link_keys); | 1211 | INIT_LIST_HEAD(&hdev->link_keys); |
1149 | 1212 | ||
1213 | INIT_LIST_HEAD(&hdev->remote_oob_data); | ||
1214 | |||
1150 | INIT_WORK(&hdev->power_on, hci_power_on); | 1215 | INIT_WORK(&hdev->power_on, hci_power_on); |
1151 | INIT_WORK(&hdev->power_off, hci_power_off); | 1216 | INIT_WORK(&hdev->power_off, hci_power_off); |
1152 | setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); | 1217 | setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); |
@@ -1226,6 +1291,7 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
1226 | hci_blacklist_clear(hdev); | 1291 | hci_blacklist_clear(hdev); |
1227 | hci_uuids_clear(hdev); | 1292 | hci_uuids_clear(hdev); |
1228 | hci_link_keys_clear(hdev); | 1293 | hci_link_keys_clear(hdev); |
1294 | hci_remote_oob_data_clear(hdev); | ||
1229 | hci_dev_unlock_bh(hdev); | 1295 | hci_dev_unlock_bh(hdev); |
1230 | 1296 | ||
1231 | __hci_dev_put(hdev); | 1297 | __hci_dev_put(hdev); |
@@ -1275,7 +1341,7 @@ int hci_recv_frame(struct sk_buff *skb) | |||
1275 | EXPORT_SYMBOL(hci_recv_frame); | 1341 | EXPORT_SYMBOL(hci_recv_frame); |
1276 | 1342 | ||
1277 | static int hci_reassembly(struct hci_dev *hdev, int type, void *data, | 1343 | static int hci_reassembly(struct hci_dev *hdev, int type, void *data, |
1278 | int count, __u8 index, gfp_t gfp_mask) | 1344 | int count, __u8 index) |
1279 | { | 1345 | { |
1280 | int len = 0; | 1346 | int len = 0; |
1281 | int hlen = 0; | 1347 | int hlen = 0; |
@@ -1305,7 +1371,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, | |||
1305 | break; | 1371 | break; |
1306 | } | 1372 | } |
1307 | 1373 | ||
1308 | skb = bt_skb_alloc(len, gfp_mask); | 1374 | skb = bt_skb_alloc(len, GFP_ATOMIC); |
1309 | if (!skb) | 1375 | if (!skb) |
1310 | return -ENOMEM; | 1376 | return -ENOMEM; |
1311 | 1377 | ||
@@ -1391,8 +1457,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) | |||
1391 | return -EILSEQ; | 1457 | return -EILSEQ; |
1392 | 1458 | ||
1393 | while (count) { | 1459 | while (count) { |
1394 | rem = hci_reassembly(hdev, type, data, count, | 1460 | rem = hci_reassembly(hdev, type, data, count, type - 1); |
1395 | type - 1, GFP_ATOMIC); | ||
1396 | if (rem < 0) | 1461 | if (rem < 0) |
1397 | return rem; | 1462 | return rem; |
1398 | 1463 | ||
@@ -1426,8 +1491,8 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count) | |||
1426 | } else | 1491 | } else |
1427 | type = bt_cb(skb)->pkt_type; | 1492 | type = bt_cb(skb)->pkt_type; |
1428 | 1493 | ||
1429 | rem = hci_reassembly(hdev, type, data, | 1494 | rem = hci_reassembly(hdev, type, data, count, |
1430 | count, STREAM_REASSEMBLY, GFP_ATOMIC); | 1495 | STREAM_REASSEMBLY); |
1431 | if (rem < 0) | 1496 | if (rem < 0) |
1432 | return rem; | 1497 | return rem; |
1433 | 1498 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index cebe7588469f..7a3398d9cd65 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -195,14 +195,17 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
195 | 195 | ||
196 | BT_DBG("%s status 0x%x", hdev->name, status); | 196 | BT_DBG("%s status 0x%x", hdev->name, status); |
197 | 197 | ||
198 | if (status) | ||
199 | return; | ||
200 | |||
201 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); | 198 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); |
202 | if (!sent) | 199 | if (!sent) |
203 | return; | 200 | return; |
204 | 201 | ||
205 | memcpy(hdev->dev_name, sent, 248); | 202 | if (test_bit(HCI_MGMT, &hdev->flags)) |
203 | mgmt_set_local_name_complete(hdev->id, sent, status); | ||
204 | |||
205 | if (status) | ||
206 | return; | ||
207 | |||
208 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); | ||
206 | } | 209 | } |
207 | 210 | ||
208 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) | 211 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -214,7 +217,7 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
214 | if (rp->status) | 217 | if (rp->status) |
215 | return; | 218 | return; |
216 | 219 | ||
217 | memcpy(hdev->dev_name, rp->name, 248); | 220 | memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); |
218 | } | 221 | } |
219 | 222 | ||
220 | static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) | 223 | static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -821,6 +824,17 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, | |||
821 | rp->status); | 824 | rp->status); |
822 | } | 825 | } |
823 | 826 | ||
827 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | ||
828 | struct sk_buff *skb) | ||
829 | { | ||
830 | struct hci_rp_read_local_oob_data *rp = (void *) skb->data; | ||
831 | |||
832 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
833 | |||
834 | mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash, | ||
835 | rp->randomizer, rp->status); | ||
836 | } | ||
837 | |||
824 | static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | 838 | static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) |
825 | { | 839 | { |
826 | BT_DBG("%s status 0x%x", hdev->name, status); | 840 | BT_DBG("%s status 0x%x", hdev->name, status); |
@@ -1214,7 +1228,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * | |||
1214 | 1228 | ||
1215 | hci_dev_lock(hdev); | 1229 | hci_dev_lock(hdev); |
1216 | 1230 | ||
1217 | for (; num_rsp; num_rsp--) { | 1231 | for (; num_rsp; num_rsp--, info++) { |
1218 | bacpy(&data.bdaddr, &info->bdaddr); | 1232 | bacpy(&data.bdaddr, &info->bdaddr); |
1219 | data.pscan_rep_mode = info->pscan_rep_mode; | 1233 | data.pscan_rep_mode = info->pscan_rep_mode; |
1220 | data.pscan_period_mode = info->pscan_period_mode; | 1234 | data.pscan_period_mode = info->pscan_period_mode; |
@@ -1223,8 +1237,9 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * | |||
1223 | data.clock_offset = info->clock_offset; | 1237 | data.clock_offset = info->clock_offset; |
1224 | data.rssi = 0x00; | 1238 | data.rssi = 0x00; |
1225 | data.ssp_mode = 0x00; | 1239 | data.ssp_mode = 0x00; |
1226 | info++; | ||
1227 | hci_inquiry_cache_update(hdev, &data); | 1240 | hci_inquiry_cache_update(hdev, &data); |
1241 | mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, | ||
1242 | NULL); | ||
1228 | } | 1243 | } |
1229 | 1244 | ||
1230 | hci_dev_unlock(hdev); | 1245 | hci_dev_unlock(hdev); |
@@ -1482,6 +1497,9 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb | |||
1482 | 1497 | ||
1483 | hci_dev_lock(hdev); | 1498 | hci_dev_lock(hdev); |
1484 | 1499 | ||
1500 | if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) | ||
1501 | mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); | ||
1502 | |||
1485 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 1503 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
1486 | if (conn && hci_outgoing_auth_needed(hdev, conn)) { | 1504 | if (conn && hci_outgoing_auth_needed(hdev, conn)) { |
1487 | struct hci_cp_auth_requested cp; | 1505 | struct hci_cp_auth_requested cp; |
@@ -1751,6 +1769,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1751 | hci_cc_pin_code_neg_reply(hdev, skb); | 1769 | hci_cc_pin_code_neg_reply(hdev, skb); |
1752 | break; | 1770 | break; |
1753 | 1771 | ||
1772 | case HCI_OP_READ_LOCAL_OOB_DATA: | ||
1773 | hci_cc_read_local_oob_data_reply(hdev, skb); | ||
1774 | break; | ||
1775 | |||
1754 | case HCI_OP_LE_READ_BUFFER_SIZE: | 1776 | case HCI_OP_LE_READ_BUFFER_SIZE: |
1755 | hci_cc_le_read_buffer_size(hdev, skb); | 1777 | hci_cc_le_read_buffer_size(hdev, skb); |
1756 | break; | 1778 | break; |
@@ -2140,7 +2162,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct | |||
2140 | struct inquiry_info_with_rssi_and_pscan_mode *info; | 2162 | struct inquiry_info_with_rssi_and_pscan_mode *info; |
2141 | info = (void *) (skb->data + 1); | 2163 | info = (void *) (skb->data + 1); |
2142 | 2164 | ||
2143 | for (; num_rsp; num_rsp--) { | 2165 | for (; num_rsp; num_rsp--, info++) { |
2144 | bacpy(&data.bdaddr, &info->bdaddr); | 2166 | bacpy(&data.bdaddr, &info->bdaddr); |
2145 | data.pscan_rep_mode = info->pscan_rep_mode; | 2167 | data.pscan_rep_mode = info->pscan_rep_mode; |
2146 | data.pscan_period_mode = info->pscan_period_mode; | 2168 | data.pscan_period_mode = info->pscan_period_mode; |
@@ -2149,13 +2171,15 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct | |||
2149 | data.clock_offset = info->clock_offset; | 2171 | data.clock_offset = info->clock_offset; |
2150 | data.rssi = info->rssi; | 2172 | data.rssi = info->rssi; |
2151 | data.ssp_mode = 0x00; | 2173 | data.ssp_mode = 0x00; |
2152 | info++; | ||
2153 | hci_inquiry_cache_update(hdev, &data); | 2174 | hci_inquiry_cache_update(hdev, &data); |
2175 | mgmt_device_found(hdev->id, &info->bdaddr, | ||
2176 | info->dev_class, info->rssi, | ||
2177 | NULL); | ||
2154 | } | 2178 | } |
2155 | } else { | 2179 | } else { |
2156 | struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); | 2180 | struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); |
2157 | 2181 | ||
2158 | for (; num_rsp; num_rsp--) { | 2182 | for (; num_rsp; num_rsp--, info++) { |
2159 | bacpy(&data.bdaddr, &info->bdaddr); | 2183 | bacpy(&data.bdaddr, &info->bdaddr); |
2160 | data.pscan_rep_mode = info->pscan_rep_mode; | 2184 | data.pscan_rep_mode = info->pscan_rep_mode; |
2161 | data.pscan_period_mode = info->pscan_period_mode; | 2185 | data.pscan_period_mode = info->pscan_period_mode; |
@@ -2164,8 +2188,10 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct | |||
2164 | data.clock_offset = info->clock_offset; | 2188 | data.clock_offset = info->clock_offset; |
2165 | data.rssi = info->rssi; | 2189 | data.rssi = info->rssi; |
2166 | data.ssp_mode = 0x00; | 2190 | data.ssp_mode = 0x00; |
2167 | info++; | ||
2168 | hci_inquiry_cache_update(hdev, &data); | 2191 | hci_inquiry_cache_update(hdev, &data); |
2192 | mgmt_device_found(hdev->id, &info->bdaddr, | ||
2193 | info->dev_class, info->rssi, | ||
2194 | NULL); | ||
2169 | } | 2195 | } |
2170 | } | 2196 | } |
2171 | 2197 | ||
@@ -2296,7 +2322,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct | |||
2296 | 2322 | ||
2297 | hci_dev_lock(hdev); | 2323 | hci_dev_lock(hdev); |
2298 | 2324 | ||
2299 | for (; num_rsp; num_rsp--) { | 2325 | for (; num_rsp; num_rsp--, info++) { |
2300 | bacpy(&data.bdaddr, &info->bdaddr); | 2326 | bacpy(&data.bdaddr, &info->bdaddr); |
2301 | data.pscan_rep_mode = info->pscan_rep_mode; | 2327 | data.pscan_rep_mode = info->pscan_rep_mode; |
2302 | data.pscan_period_mode = info->pscan_period_mode; | 2328 | data.pscan_period_mode = info->pscan_period_mode; |
@@ -2305,8 +2331,9 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct | |||
2305 | data.clock_offset = info->clock_offset; | 2331 | data.clock_offset = info->clock_offset; |
2306 | data.rssi = info->rssi; | 2332 | data.rssi = info->rssi; |
2307 | data.ssp_mode = 0x01; | 2333 | data.ssp_mode = 0x01; |
2308 | info++; | ||
2309 | hci_inquiry_cache_update(hdev, &data); | 2334 | hci_inquiry_cache_update(hdev, &data); |
2335 | mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, | ||
2336 | info->rssi, info->data); | ||
2310 | } | 2337 | } |
2311 | 2338 | ||
2312 | hci_dev_unlock(hdev); | 2339 | hci_dev_unlock(hdev); |
@@ -2355,9 +2382,14 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff | |||
2355 | 2382 | ||
2356 | bacpy(&cp.bdaddr, &ev->bdaddr); | 2383 | bacpy(&cp.bdaddr, &ev->bdaddr); |
2357 | cp.capability = conn->io_capability; | 2384 | cp.capability = conn->io_capability; |
2358 | cp.oob_data = 0; | ||
2359 | cp.authentication = hci_get_auth_req(conn); | 2385 | cp.authentication = hci_get_auth_req(conn); |
2360 | 2386 | ||
2387 | if ((conn->out == 0x01 || conn->remote_oob == 0x01) && | ||
2388 | hci_find_remote_oob_data(hdev, &conn->dst)) | ||
2389 | cp.oob_data = 0x01; | ||
2390 | else | ||
2391 | cp.oob_data = 0x00; | ||
2392 | |||
2361 | hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, | 2393 | hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, |
2362 | sizeof(cp), &cp); | 2394 | sizeof(cp), &cp); |
2363 | } else { | 2395 | } else { |
@@ -2455,6 +2487,37 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ | |||
2455 | hci_dev_unlock(hdev); | 2487 | hci_dev_unlock(hdev); |
2456 | } | 2488 | } |
2457 | 2489 | ||
2490 | static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, | ||
2491 | struct sk_buff *skb) | ||
2492 | { | ||
2493 | struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; | ||
2494 | struct oob_data *data; | ||
2495 | |||
2496 | BT_DBG("%s", hdev->name); | ||
2497 | |||
2498 | hci_dev_lock(hdev); | ||
2499 | |||
2500 | data = hci_find_remote_oob_data(hdev, &ev->bdaddr); | ||
2501 | if (data) { | ||
2502 | struct hci_cp_remote_oob_data_reply cp; | ||
2503 | |||
2504 | bacpy(&cp.bdaddr, &ev->bdaddr); | ||
2505 | memcpy(cp.hash, data->hash, sizeof(cp.hash)); | ||
2506 | memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); | ||
2507 | |||
2508 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), | ||
2509 | &cp); | ||
2510 | } else { | ||
2511 | struct hci_cp_remote_oob_data_neg_reply cp; | ||
2512 | |||
2513 | bacpy(&cp.bdaddr, &ev->bdaddr); | ||
2514 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), | ||
2515 | &cp); | ||
2516 | } | ||
2517 | |||
2518 | hci_dev_unlock(hdev); | ||
2519 | } | ||
2520 | |||
2458 | static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2521 | static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2459 | { | 2522 | { |
2460 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; | 2523 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; |
@@ -2657,6 +2720,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2657 | hci_le_meta_evt(hdev, skb); | 2720 | hci_le_meta_evt(hdev, skb); |
2658 | break; | 2721 | break; |
2659 | 2722 | ||
2723 | case HCI_EV_REMOTE_OOB_DATA_REQUEST: | ||
2724 | hci_remote_oob_data_request_evt(hdev, skb); | ||
2725 | break; | ||
2726 | |||
2660 | default: | 2727 | default: |
2661 | BT_DBG("%s event 0x%x", hdev->name, event); | 2728 | BT_DBG("%s event 0x%x", hdev->name, event); |
2662 | break; | 2729 | break; |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 3c838a65a75a..8775933ea837 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -216,13 +216,13 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr, char | |||
216 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | 216 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) |
217 | { | 217 | { |
218 | struct hci_dev *hdev = dev_get_drvdata(dev); | 218 | struct hci_dev *hdev = dev_get_drvdata(dev); |
219 | char name[249]; | 219 | char name[HCI_MAX_NAME_LENGTH + 1]; |
220 | int i; | 220 | int i; |
221 | 221 | ||
222 | for (i = 0; i < 248; i++) | 222 | for (i = 0; i < HCI_MAX_NAME_LENGTH; i++) |
223 | name[i] = hdev->dev_name[i]; | 223 | name[i] = hdev->dev_name[i]; |
224 | 224 | ||
225 | name[248] = '\0'; | 225 | name[HCI_MAX_NAME_LENGTH] = '\0'; |
226 | return sprintf(buf, "%s\n", name); | 226 | return sprintf(buf, "%s\n", name); |
227 | } | 227 | } |
228 | 228 | ||
@@ -277,10 +277,12 @@ static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *at | |||
277 | static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 277 | static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
278 | { | 278 | { |
279 | struct hci_dev *hdev = dev_get_drvdata(dev); | 279 | struct hci_dev *hdev = dev_get_drvdata(dev); |
280 | unsigned long val; | 280 | unsigned int val; |
281 | int rv; | ||
281 | 282 | ||
282 | if (strict_strtoul(buf, 0, &val) < 0) | 283 | rv = kstrtouint(buf, 0, &val); |
283 | return -EINVAL; | 284 | if (rv < 0) |
285 | return rv; | ||
284 | 286 | ||
285 | if (val != 0 && (val < 500 || val > 3600000)) | 287 | if (val != 0 && (val < 500 || val > 3600000)) |
286 | return -EINVAL; | 288 | return -EINVAL; |
@@ -299,15 +301,14 @@ static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribu | |||
299 | static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 301 | static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
300 | { | 302 | { |
301 | struct hci_dev *hdev = dev_get_drvdata(dev); | 303 | struct hci_dev *hdev = dev_get_drvdata(dev); |
302 | unsigned long val; | 304 | u16 val; |
303 | 305 | int rv; | |
304 | if (strict_strtoul(buf, 0, &val) < 0) | ||
305 | return -EINVAL; | ||
306 | 306 | ||
307 | if (val < 0x0002 || val > 0xFFFE || val % 2) | 307 | rv = kstrtou16(buf, 0, &val); |
308 | return -EINVAL; | 308 | if (rv < 0) |
309 | return rv; | ||
309 | 310 | ||
310 | if (val < hdev->sniff_min_interval) | 311 | if (val == 0 || val % 2 || val < hdev->sniff_min_interval) |
311 | return -EINVAL; | 312 | return -EINVAL; |
312 | 313 | ||
313 | hdev->sniff_max_interval = val; | 314 | hdev->sniff_max_interval = val; |
@@ -324,15 +325,14 @@ static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribu | |||
324 | static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 325 | static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
325 | { | 326 | { |
326 | struct hci_dev *hdev = dev_get_drvdata(dev); | 327 | struct hci_dev *hdev = dev_get_drvdata(dev); |
327 | unsigned long val; | 328 | u16 val; |
329 | int rv; | ||
328 | 330 | ||
329 | if (strict_strtoul(buf, 0, &val) < 0) | 331 | rv = kstrtou16(buf, 0, &val); |
330 | return -EINVAL; | 332 | if (rv < 0) |
331 | 333 | return rv; | |
332 | if (val < 0x0002 || val > 0xFFFE || val % 2) | ||
333 | return -EINVAL; | ||
334 | 334 | ||
335 | if (val > hdev->sniff_max_interval) | 335 | if (val == 0 || val % 2 || val > hdev->sniff_max_interval) |
336 | return -EINVAL; | 336 | return -EINVAL; |
337 | 337 | ||
338 | hdev->sniff_min_interval = val; | 338 | hdev->sniff_min_interval = val; |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 5ec12971af6b..ae6ebc6c3481 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/wait.h> | 38 | #include <linux/wait.h> |
39 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | #include <linux/kthread.h> | ||
40 | #include <net/sock.h> | 41 | #include <net/sock.h> |
41 | 42 | ||
42 | #include <linux/input.h> | 43 | #include <linux/input.h> |
@@ -55,22 +56,24 @@ static DECLARE_RWSEM(hidp_session_sem); | |||
55 | static LIST_HEAD(hidp_session_list); | 56 | static LIST_HEAD(hidp_session_list); |
56 | 57 | ||
57 | static unsigned char hidp_keycode[256] = { | 58 | static unsigned char hidp_keycode[256] = { |
58 | 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, | 59 | 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, |
59 | 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, | 60 | 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, |
60 | 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, | 61 | 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, |
61 | 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, | 62 | 14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52, |
62 | 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, | 63 | 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88, |
63 | 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, | 64 | 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69, |
64 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, | 65 | 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73, |
65 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, | 66 | 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190, |
66 | 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, | 67 | 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135, |
67 | 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 68 | 136, 113, 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94, |
68 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 69 | 95, 0, 0, 0, 122, 123, 90, 91, 85, 0, 0, 0, 0, 0, |
69 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 70 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
70 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 71 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
71 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 72 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
72 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, | 73 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
73 | 150,158,159,128,136,177,178,176,142,152,173,140 | 74 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
75 | 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115, | ||
76 | 114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140 | ||
74 | }; | 77 | }; |
75 | 78 | ||
76 | static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; | 79 | static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; |
@@ -461,8 +464,7 @@ static void hidp_idle_timeout(unsigned long arg) | |||
461 | { | 464 | { |
462 | struct hidp_session *session = (struct hidp_session *) arg; | 465 | struct hidp_session *session = (struct hidp_session *) arg; |
463 | 466 | ||
464 | atomic_inc(&session->terminate); | 467 | kthread_stop(session->task); |
465 | hidp_schedule(session); | ||
466 | } | 468 | } |
467 | 469 | ||
468 | static void hidp_set_timer(struct hidp_session *session) | 470 | static void hidp_set_timer(struct hidp_session *session) |
@@ -533,9 +535,7 @@ static void hidp_process_hid_control(struct hidp_session *session, | |||
533 | skb_queue_purge(&session->ctrl_transmit); | 535 | skb_queue_purge(&session->ctrl_transmit); |
534 | skb_queue_purge(&session->intr_transmit); | 536 | skb_queue_purge(&session->intr_transmit); |
535 | 537 | ||
536 | /* Kill session thread */ | 538 | kthread_stop(session->task); |
537 | atomic_inc(&session->terminate); | ||
538 | hidp_schedule(session); | ||
539 | } | 539 | } |
540 | } | 540 | } |
541 | 541 | ||
@@ -694,22 +694,10 @@ static int hidp_session(void *arg) | |||
694 | struct sock *ctrl_sk = session->ctrl_sock->sk; | 694 | struct sock *ctrl_sk = session->ctrl_sock->sk; |
695 | struct sock *intr_sk = session->intr_sock->sk; | 695 | struct sock *intr_sk = session->intr_sock->sk; |
696 | struct sk_buff *skb; | 696 | struct sk_buff *skb; |
697 | int vendor = 0x0000, product = 0x0000; | ||
698 | wait_queue_t ctrl_wait, intr_wait; | 697 | wait_queue_t ctrl_wait, intr_wait; |
699 | 698 | ||
700 | BT_DBG("session %p", session); | 699 | BT_DBG("session %p", session); |
701 | 700 | ||
702 | if (session->input) { | ||
703 | vendor = session->input->id.vendor; | ||
704 | product = session->input->id.product; | ||
705 | } | ||
706 | |||
707 | if (session->hid) { | ||
708 | vendor = session->hid->vendor; | ||
709 | product = session->hid->product; | ||
710 | } | ||
711 | |||
712 | daemonize("khidpd_%04x%04x", vendor, product); | ||
713 | set_user_nice(current, -15); | 701 | set_user_nice(current, -15); |
714 | 702 | ||
715 | init_waitqueue_entry(&ctrl_wait, current); | 703 | init_waitqueue_entry(&ctrl_wait, current); |
@@ -718,10 +706,11 @@ static int hidp_session(void *arg) | |||
718 | add_wait_queue(sk_sleep(intr_sk), &intr_wait); | 706 | add_wait_queue(sk_sleep(intr_sk), &intr_wait); |
719 | session->waiting_for_startup = 0; | 707 | session->waiting_for_startup = 0; |
720 | wake_up_interruptible(&session->startup_queue); | 708 | wake_up_interruptible(&session->startup_queue); |
721 | while (!atomic_read(&session->terminate)) { | 709 | while (!kthread_should_stop()) { |
722 | set_current_state(TASK_INTERRUPTIBLE); | 710 | set_current_state(TASK_INTERRUPTIBLE); |
723 | 711 | ||
724 | if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED) | 712 | if (ctrl_sk->sk_state != BT_CONNECTED || |
713 | intr_sk->sk_state != BT_CONNECTED) | ||
725 | break; | 714 | break; |
726 | 715 | ||
727 | while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { | 716 | while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { |
@@ -965,6 +954,7 @@ fault: | |||
965 | int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) | 954 | int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) |
966 | { | 955 | { |
967 | struct hidp_session *session, *s; | 956 | struct hidp_session *session, *s; |
957 | int vendor, product; | ||
968 | int err; | 958 | int err; |
969 | 959 | ||
970 | BT_DBG(""); | 960 | BT_DBG(""); |
@@ -1026,9 +1016,24 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
1026 | 1016 | ||
1027 | hidp_set_timer(session); | 1017 | hidp_set_timer(session); |
1028 | 1018 | ||
1029 | err = kernel_thread(hidp_session, session, CLONE_KERNEL); | 1019 | if (session->hid) { |
1030 | if (err < 0) | 1020 | vendor = session->hid->vendor; |
1021 | product = session->hid->product; | ||
1022 | } else if (session->input) { | ||
1023 | vendor = session->input->id.vendor; | ||
1024 | product = session->input->id.product; | ||
1025 | } else { | ||
1026 | vendor = 0x0000; | ||
1027 | product = 0x0000; | ||
1028 | } | ||
1029 | |||
1030 | session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x", | ||
1031 | vendor, product); | ||
1032 | if (IS_ERR(session->task)) { | ||
1033 | err = PTR_ERR(session->task); | ||
1031 | goto unlink; | 1034 | goto unlink; |
1035 | } | ||
1036 | |||
1032 | while (session->waiting_for_startup) { | 1037 | while (session->waiting_for_startup) { |
1033 | wait_event_interruptible(session->startup_queue, | 1038 | wait_event_interruptible(session->startup_queue, |
1034 | !session->waiting_for_startup); | 1039 | !session->waiting_for_startup); |
@@ -1053,8 +1058,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
1053 | err_add_device: | 1058 | err_add_device: |
1054 | hid_destroy_device(session->hid); | 1059 | hid_destroy_device(session->hid); |
1055 | session->hid = NULL; | 1060 | session->hid = NULL; |
1056 | atomic_inc(&session->terminate); | 1061 | kthread_stop(session->task); |
1057 | hidp_schedule(session); | ||
1058 | 1062 | ||
1059 | unlink: | 1063 | unlink: |
1060 | hidp_del_timer(session); | 1064 | hidp_del_timer(session); |
@@ -1105,13 +1109,7 @@ int hidp_del_connection(struct hidp_conndel_req *req) | |||
1105 | skb_queue_purge(&session->ctrl_transmit); | 1109 | skb_queue_purge(&session->ctrl_transmit); |
1106 | skb_queue_purge(&session->intr_transmit); | 1110 | skb_queue_purge(&session->intr_transmit); |
1107 | 1111 | ||
1108 | /* Wakeup user-space polling for socket errors */ | 1112 | kthread_stop(session->task); |
1109 | session->intr_sock->sk->sk_err = EUNATCH; | ||
1110 | session->ctrl_sock->sk->sk_err = EUNATCH; | ||
1111 | |||
1112 | /* Kill session thread */ | ||
1113 | atomic_inc(&session->terminate); | ||
1114 | hidp_schedule(session); | ||
1115 | } | 1113 | } |
1116 | } else | 1114 | } else |
1117 | err = -ENOENT; | 1115 | err = -ENOENT; |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index 13de5fa03480..12822cde4b49 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
@@ -84,8 +84,8 @@ | |||
84 | #define HIDP_WAITING_FOR_SEND_ACK 11 | 84 | #define HIDP_WAITING_FOR_SEND_ACK 11 |
85 | 85 | ||
86 | struct hidp_connadd_req { | 86 | struct hidp_connadd_req { |
87 | int ctrl_sock; // Connected control socket | 87 | int ctrl_sock; /* Connected control socket */ |
88 | int intr_sock; // Connteted interrupt socket | 88 | int intr_sock; /* Connected interrupt socket */ |
89 | __u16 parser; | 89 | __u16 parser; |
90 | __u16 rd_size; | 90 | __u16 rd_size; |
91 | __u8 __user *rd_data; | 91 | __u8 __user *rd_data; |
@@ -142,7 +142,7 @@ struct hidp_session { | |||
142 | uint ctrl_mtu; | 142 | uint ctrl_mtu; |
143 | uint intr_mtu; | 143 | uint intr_mtu; |
144 | 144 | ||
145 | atomic_t terminate; | 145 | struct task_struct *task; |
146 | 146 | ||
147 | unsigned char keys[8]; | 147 | unsigned char keys[8]; |
148 | unsigned char leds; | 148 | unsigned char leds; |
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 250dfd46237d..178ac7f127ad 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c | |||
@@ -85,7 +85,8 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long | |||
85 | return err; | 85 | return err; |
86 | } | 86 | } |
87 | 87 | ||
88 | if (csock->sk->sk_state != BT_CONNECTED || isock->sk->sk_state != BT_CONNECTED) { | 88 | if (csock->sk->sk_state != BT_CONNECTED || |
89 | isock->sk->sk_state != BT_CONNECTED) { | ||
89 | sockfd_put(csock); | 90 | sockfd_put(csock); |
90 | sockfd_put(isock); | 91 | sockfd_put(isock); |
91 | return -EBADFD; | 92 | return -EBADFD; |
@@ -140,8 +141,8 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long | |||
140 | 141 | ||
141 | #ifdef CONFIG_COMPAT | 142 | #ifdef CONFIG_COMPAT |
142 | struct compat_hidp_connadd_req { | 143 | struct compat_hidp_connadd_req { |
143 | int ctrl_sock; // Connected control socket | 144 | int ctrl_sock; /* Connected control socket */ |
144 | int intr_sock; // Connteted interrupt socket | 145 | int intr_sock; /* Connected interrupt socket */ |
145 | __u16 parser; | 146 | __u16 parser; |
146 | __u16 rd_size; | 147 | __u16 rd_size; |
147 | compat_uptr_t rd_data; | 148 | compat_uptr_t rd_data; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index ca27f3a41536..c3cebed205cc 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -169,7 +169,7 @@ static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk) | |||
169 | __sock_put(sk); | 169 | __sock_put(sk); |
170 | } | 170 | } |
171 | 171 | ||
172 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) | 172 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) |
173 | { | 173 | { |
174 | struct l2cap_chan_list *l = &conn->chan_list; | 174 | struct l2cap_chan_list *l = &conn->chan_list; |
175 | 175 | ||
@@ -204,9 +204,6 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so | |||
204 | } | 204 | } |
205 | 205 | ||
206 | __l2cap_chan_link(l, sk); | 206 | __l2cap_chan_link(l, sk); |
207 | |||
208 | if (parent) | ||
209 | bt_accept_enqueue(parent, sk); | ||
210 | } | 207 | } |
211 | 208 | ||
212 | /* Delete channel. | 209 | /* Delete channel. |
@@ -652,7 +649,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
652 | bacpy(&bt_sk(sk)->src, conn->src); | 649 | bacpy(&bt_sk(sk)->src, conn->src); |
653 | bacpy(&bt_sk(sk)->dst, conn->dst); | 650 | bacpy(&bt_sk(sk)->dst, conn->dst); |
654 | 651 | ||
655 | __l2cap_chan_add(conn, sk, parent); | 652 | bt_accept_enqueue(parent, sk); |
653 | |||
654 | __l2cap_chan_add(conn, sk); | ||
656 | 655 | ||
657 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 656 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
658 | 657 | ||
@@ -793,11 +792,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
793 | kfree(conn); | 792 | kfree(conn); |
794 | } | 793 | } |
795 | 794 | ||
796 | static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) | 795 | static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) |
797 | { | 796 | { |
798 | struct l2cap_chan_list *l = &conn->chan_list; | 797 | struct l2cap_chan_list *l = &conn->chan_list; |
799 | write_lock_bh(&l->lock); | 798 | write_lock_bh(&l->lock); |
800 | __l2cap_chan_add(conn, sk, parent); | 799 | __l2cap_chan_add(conn, sk); |
801 | write_unlock_bh(&l->lock); | 800 | write_unlock_bh(&l->lock); |
802 | } | 801 | } |
803 | 802 | ||
@@ -876,7 +875,7 @@ int l2cap_do_connect(struct sock *sk) | |||
876 | /* Update source addr of the socket */ | 875 | /* Update source addr of the socket */ |
877 | bacpy(src, conn->src); | 876 | bacpy(src, conn->src); |
878 | 877 | ||
879 | l2cap_chan_add(conn, sk, NULL); | 878 | l2cap_chan_add(conn, sk); |
880 | 879 | ||
881 | sk->sk_state = BT_CONNECT; | 880 | sk->sk_state = BT_CONNECT; |
882 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 881 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
@@ -2032,7 +2031,9 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2032 | l2cap_pi(sk)->psm = psm; | 2031 | l2cap_pi(sk)->psm = psm; |
2033 | l2cap_pi(sk)->dcid = scid; | 2032 | l2cap_pi(sk)->dcid = scid; |
2034 | 2033 | ||
2035 | __l2cap_chan_add(conn, sk, parent); | 2034 | bt_accept_enqueue(parent, sk); |
2035 | |||
2036 | __l2cap_chan_add(conn, sk); | ||
2036 | dcid = l2cap_pi(sk)->scid; | 2037 | dcid = l2cap_pi(sk)->scid; |
2037 | 2038 | ||
2038 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 2039 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
@@ -2462,6 +2463,11 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm | |||
2462 | 2463 | ||
2463 | BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); | 2464 | BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); |
2464 | 2465 | ||
2466 | /* L2CAP Info req/rsp are unbound to channels, add extra checks */ | ||
2467 | if (cmd->ident != conn->info_ident || | ||
2468 | conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) | ||
2469 | return 0; | ||
2470 | |||
2465 | del_timer(&conn->info_timer); | 2471 | del_timer(&conn->info_timer); |
2466 | 2472 | ||
2467 | if (result != L2CAP_IR_SUCCESS) { | 2473 | if (result != L2CAP_IR_SUCCESS) { |
@@ -2672,7 +2678,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, | |||
2672 | 2678 | ||
2673 | if (err) { | 2679 | if (err) { |
2674 | struct l2cap_cmd_rej rej; | 2680 | struct l2cap_cmd_rej rej; |
2675 | BT_DBG("error %d", err); | 2681 | |
2682 | BT_ERR("Wrong link type (%d)", err); | ||
2676 | 2683 | ||
2677 | /* FIXME: Map err to a valid reason */ | 2684 | /* FIXME: Map err to a valid reason */ |
2678 | rej.reason = cpu_to_le16(0); | 2685 | rej.reason = cpu_to_le16(0); |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 4476d8e3c0f2..c304688252b8 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -36,7 +36,7 @@ struct pending_cmd { | |||
36 | struct list_head list; | 36 | struct list_head list; |
37 | __u16 opcode; | 37 | __u16 opcode; |
38 | int index; | 38 | int index; |
39 | void *cmd; | 39 | void *param; |
40 | struct sock *sk; | 40 | struct sock *sk; |
41 | void *user_data; | 41 | void *user_data; |
42 | }; | 42 | }; |
@@ -179,10 +179,12 @@ static int read_controller_info(struct sock *sk, u16 index) | |||
179 | 179 | ||
180 | hci_del_off_timer(hdev); | 180 | hci_del_off_timer(hdev); |
181 | 181 | ||
182 | hci_dev_lock_bh(hdev); | 182 | hci_dev_lock(hdev); |
183 | 183 | ||
184 | set_bit(HCI_MGMT, &hdev->flags); | 184 | set_bit(HCI_MGMT, &hdev->flags); |
185 | 185 | ||
186 | memset(&rp, 0, sizeof(rp)); | ||
187 | |||
186 | rp.type = hdev->dev_type; | 188 | rp.type = hdev->dev_type; |
187 | 189 | ||
188 | rp.powered = test_bit(HCI_UP, &hdev->flags); | 190 | rp.powered = test_bit(HCI_UP, &hdev->flags); |
@@ -204,7 +206,9 @@ static int read_controller_info(struct sock *sk, u16 index) | |||
204 | rp.hci_ver = hdev->hci_ver; | 206 | rp.hci_ver = hdev->hci_ver; |
205 | put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); | 207 | put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); |
206 | 208 | ||
207 | hci_dev_unlock_bh(hdev); | 209 | memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); |
210 | |||
211 | hci_dev_unlock(hdev); | ||
208 | hci_dev_put(hdev); | 212 | hci_dev_put(hdev); |
209 | 213 | ||
210 | return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp)); | 214 | return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp)); |
@@ -213,7 +217,7 @@ static int read_controller_info(struct sock *sk, u16 index) | |||
213 | static void mgmt_pending_free(struct pending_cmd *cmd) | 217 | static void mgmt_pending_free(struct pending_cmd *cmd) |
214 | { | 218 | { |
215 | sock_put(cmd->sk); | 219 | sock_put(cmd->sk); |
216 | kfree(cmd->cmd); | 220 | kfree(cmd->param); |
217 | kfree(cmd); | 221 | kfree(cmd); |
218 | } | 222 | } |
219 | 223 | ||
@@ -229,13 +233,14 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, | |||
229 | cmd->opcode = opcode; | 233 | cmd->opcode = opcode; |
230 | cmd->index = index; | 234 | cmd->index = index; |
231 | 235 | ||
232 | cmd->cmd = kmalloc(len, GFP_ATOMIC); | 236 | cmd->param = kmalloc(len, GFP_ATOMIC); |
233 | if (!cmd->cmd) { | 237 | if (!cmd->param) { |
234 | kfree(cmd); | 238 | kfree(cmd); |
235 | return NULL; | 239 | return NULL; |
236 | } | 240 | } |
237 | 241 | ||
238 | memcpy(cmd->cmd, data, len); | 242 | if (data) |
243 | memcpy(cmd->param, data, len); | ||
239 | 244 | ||
240 | cmd->sk = sk; | 245 | cmd->sk = sk; |
241 | sock_hold(sk); | 246 | sock_hold(sk); |
@@ -311,7 +316,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
311 | if (!hdev) | 316 | if (!hdev) |
312 | return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV); | 317 | return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV); |
313 | 318 | ||
314 | hci_dev_lock_bh(hdev); | 319 | hci_dev_lock(hdev); |
315 | 320 | ||
316 | up = test_bit(HCI_UP, &hdev->flags); | 321 | up = test_bit(HCI_UP, &hdev->flags); |
317 | if ((cp->val && up) || (!cp->val && !up)) { | 322 | if ((cp->val && up) || (!cp->val && !up)) { |
@@ -338,7 +343,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
338 | err = 0; | 343 | err = 0; |
339 | 344 | ||
340 | failed: | 345 | failed: |
341 | hci_dev_unlock_bh(hdev); | 346 | hci_dev_unlock(hdev); |
342 | hci_dev_put(hdev); | 347 | hci_dev_put(hdev); |
343 | return err; | 348 | return err; |
344 | } | 349 | } |
@@ -363,7 +368,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, | |||
363 | if (!hdev) | 368 | if (!hdev) |
364 | return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV); | 369 | return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV); |
365 | 370 | ||
366 | hci_dev_lock_bh(hdev); | 371 | hci_dev_lock(hdev); |
367 | 372 | ||
368 | if (!test_bit(HCI_UP, &hdev->flags)) { | 373 | if (!test_bit(HCI_UP, &hdev->flags)) { |
369 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN); | 374 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN); |
@@ -398,7 +403,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, | |||
398 | mgmt_pending_remove(cmd); | 403 | mgmt_pending_remove(cmd); |
399 | 404 | ||
400 | failed: | 405 | failed: |
401 | hci_dev_unlock_bh(hdev); | 406 | hci_dev_unlock(hdev); |
402 | hci_dev_put(hdev); | 407 | hci_dev_put(hdev); |
403 | 408 | ||
404 | return err; | 409 | return err; |
@@ -424,7 +429,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, | |||
424 | if (!hdev) | 429 | if (!hdev) |
425 | return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV); | 430 | return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV); |
426 | 431 | ||
427 | hci_dev_lock_bh(hdev); | 432 | hci_dev_lock(hdev); |
428 | 433 | ||
429 | if (!test_bit(HCI_UP, &hdev->flags)) { | 434 | if (!test_bit(HCI_UP, &hdev->flags)) { |
430 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN); | 435 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN); |
@@ -458,7 +463,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, | |||
458 | mgmt_pending_remove(cmd); | 463 | mgmt_pending_remove(cmd); |
459 | 464 | ||
460 | failed: | 465 | failed: |
461 | hci_dev_unlock_bh(hdev); | 466 | hci_dev_unlock(hdev); |
462 | hci_dev_put(hdev); | 467 | hci_dev_put(hdev); |
463 | 468 | ||
464 | return err; | 469 | return err; |
@@ -517,7 +522,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, | |||
517 | if (!hdev) | 522 | if (!hdev) |
518 | return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV); | 523 | return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV); |
519 | 524 | ||
520 | hci_dev_lock_bh(hdev); | 525 | hci_dev_lock(hdev); |
521 | 526 | ||
522 | if (cp->val) | 527 | if (cp->val) |
523 | set_bit(HCI_PAIRABLE, &hdev->flags); | 528 | set_bit(HCI_PAIRABLE, &hdev->flags); |
@@ -533,12 +538,156 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, | |||
533 | err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk); | 538 | err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk); |
534 | 539 | ||
535 | failed: | 540 | failed: |
536 | hci_dev_unlock_bh(hdev); | 541 | hci_dev_unlock(hdev); |
537 | hci_dev_put(hdev); | 542 | hci_dev_put(hdev); |
538 | 543 | ||
539 | return err; | 544 | return err; |
540 | } | 545 | } |
541 | 546 | ||
547 | #define EIR_FLAGS 0x01 /* flags */ | ||
548 | #define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ | ||
549 | #define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ | ||
550 | #define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */ | ||
551 | #define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ | ||
552 | #define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */ | ||
553 | #define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ | ||
554 | #define EIR_NAME_SHORT 0x08 /* shortened local name */ | ||
555 | #define EIR_NAME_COMPLETE 0x09 /* complete local name */ | ||
556 | #define EIR_TX_POWER 0x0A /* transmit power level */ | ||
557 | #define EIR_DEVICE_ID 0x10 /* device ID */ | ||
558 | |||
559 | #define PNP_INFO_SVCLASS_ID 0x1200 | ||
560 | |||
561 | static u8 bluetooth_base_uuid[] = { | ||
562 | 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, | ||
563 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
564 | }; | ||
565 | |||
566 | static u16 get_uuid16(u8 *uuid128) | ||
567 | { | ||
568 | u32 val; | ||
569 | int i; | ||
570 | |||
571 | for (i = 0; i < 12; i++) { | ||
572 | if (bluetooth_base_uuid[i] != uuid128[i]) | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | memcpy(&val, &uuid128[12], 4); | ||
577 | |||
578 | val = le32_to_cpu(val); | ||
579 | if (val > 0xffff) | ||
580 | return 0; | ||
581 | |||
582 | return (u16) val; | ||
583 | } | ||
584 | |||
585 | static void create_eir(struct hci_dev *hdev, u8 *data) | ||
586 | { | ||
587 | u8 *ptr = data; | ||
588 | u16 eir_len = 0; | ||
589 | u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)]; | ||
590 | int i, truncated = 0; | ||
591 | struct list_head *p; | ||
592 | size_t name_len; | ||
593 | |||
594 | name_len = strlen(hdev->dev_name); | ||
595 | |||
596 | if (name_len > 0) { | ||
597 | /* EIR Data type */ | ||
598 | if (name_len > 48) { | ||
599 | name_len = 48; | ||
600 | ptr[1] = EIR_NAME_SHORT; | ||
601 | } else | ||
602 | ptr[1] = EIR_NAME_COMPLETE; | ||
603 | |||
604 | /* EIR Data length */ | ||
605 | ptr[0] = name_len + 1; | ||
606 | |||
607 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
608 | |||
609 | eir_len += (name_len + 2); | ||
610 | ptr += (name_len + 2); | ||
611 | } | ||
612 | |||
613 | memset(uuid16_list, 0, sizeof(uuid16_list)); | ||
614 | |||
615 | /* Group all UUID16 types */ | ||
616 | list_for_each(p, &hdev->uuids) { | ||
617 | struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list); | ||
618 | u16 uuid16; | ||
619 | |||
620 | uuid16 = get_uuid16(uuid->uuid); | ||
621 | if (uuid16 == 0) | ||
622 | return; | ||
623 | |||
624 | if (uuid16 < 0x1100) | ||
625 | continue; | ||
626 | |||
627 | if (uuid16 == PNP_INFO_SVCLASS_ID) | ||
628 | continue; | ||
629 | |||
630 | /* Stop if not enough space to put next UUID */ | ||
631 | if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) { | ||
632 | truncated = 1; | ||
633 | break; | ||
634 | } | ||
635 | |||
636 | /* Check for duplicates */ | ||
637 | for (i = 0; uuid16_list[i] != 0; i++) | ||
638 | if (uuid16_list[i] == uuid16) | ||
639 | break; | ||
640 | |||
641 | if (uuid16_list[i] == 0) { | ||
642 | uuid16_list[i] = uuid16; | ||
643 | eir_len += sizeof(u16); | ||
644 | } | ||
645 | } | ||
646 | |||
647 | if (uuid16_list[0] != 0) { | ||
648 | u8 *length = ptr; | ||
649 | |||
650 | /* EIR Data type */ | ||
651 | ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL; | ||
652 | |||
653 | ptr += 2; | ||
654 | eir_len += 2; | ||
655 | |||
656 | for (i = 0; uuid16_list[i] != 0; i++) { | ||
657 | *ptr++ = (uuid16_list[i] & 0x00ff); | ||
658 | *ptr++ = (uuid16_list[i] & 0xff00) >> 8; | ||
659 | } | ||
660 | |||
661 | /* EIR Data length */ | ||
662 | *length = (i * sizeof(u16)) + 1; | ||
663 | } | ||
664 | } | ||
665 | |||
666 | static int update_eir(struct hci_dev *hdev) | ||
667 | { | ||
668 | struct hci_cp_write_eir cp; | ||
669 | |||
670 | if (!(hdev->features[6] & LMP_EXT_INQ)) | ||
671 | return 0; | ||
672 | |||
673 | if (hdev->ssp_mode == 0) | ||
674 | return 0; | ||
675 | |||
676 | if (test_bit(HCI_SERVICE_CACHE, &hdev->flags)) | ||
677 | return 0; | ||
678 | |||
679 | memset(&cp, 0, sizeof(cp)); | ||
680 | |||
681 | create_eir(hdev, cp.data); | ||
682 | |||
683 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) | ||
684 | return 0; | ||
685 | |||
686 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); | ||
687 | |||
688 | return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | ||
689 | } | ||
690 | |||
542 | static u8 get_service_classes(struct hci_dev *hdev) | 691 | static u8 get_service_classes(struct hci_dev *hdev) |
543 | { | 692 | { |
544 | struct list_head *p; | 693 | struct list_head *p; |
@@ -590,7 +739,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
590 | if (!hdev) | 739 | if (!hdev) |
591 | return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV); | 740 | return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV); |
592 | 741 | ||
593 | hci_dev_lock_bh(hdev); | 742 | hci_dev_lock(hdev); |
594 | 743 | ||
595 | uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC); | 744 | uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC); |
596 | if (!uuid) { | 745 | if (!uuid) { |
@@ -607,10 +756,14 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
607 | if (err < 0) | 756 | if (err < 0) |
608 | goto failed; | 757 | goto failed; |
609 | 758 | ||
759 | err = update_eir(hdev); | ||
760 | if (err < 0) | ||
761 | goto failed; | ||
762 | |||
610 | err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0); | 763 | err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0); |
611 | 764 | ||
612 | failed: | 765 | failed: |
613 | hci_dev_unlock_bh(hdev); | 766 | hci_dev_unlock(hdev); |
614 | hci_dev_put(hdev); | 767 | hci_dev_put(hdev); |
615 | 768 | ||
616 | return err; | 769 | return err; |
@@ -635,7 +788,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
635 | if (!hdev) | 788 | if (!hdev) |
636 | return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV); | 789 | return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV); |
637 | 790 | ||
638 | hci_dev_lock_bh(hdev); | 791 | hci_dev_lock(hdev); |
639 | 792 | ||
640 | if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) { | 793 | if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) { |
641 | err = hci_uuids_clear(hdev); | 794 | err = hci_uuids_clear(hdev); |
@@ -663,10 +816,14 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
663 | if (err < 0) | 816 | if (err < 0) |
664 | goto unlock; | 817 | goto unlock; |
665 | 818 | ||
819 | err = update_eir(hdev); | ||
820 | if (err < 0) | ||
821 | goto unlock; | ||
822 | |||
666 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0); | 823 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0); |
667 | 824 | ||
668 | unlock: | 825 | unlock: |
669 | hci_dev_unlock_bh(hdev); | 826 | hci_dev_unlock(hdev); |
670 | hci_dev_put(hdev); | 827 | hci_dev_put(hdev); |
671 | 828 | ||
672 | return err; | 829 | return err; |
@@ -690,7 +847,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, | |||
690 | if (!hdev) | 847 | if (!hdev) |
691 | return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV); | 848 | return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV); |
692 | 849 | ||
693 | hci_dev_lock_bh(hdev); | 850 | hci_dev_lock(hdev); |
694 | 851 | ||
695 | hdev->major_class = cp->major; | 852 | hdev->major_class = cp->major; |
696 | hdev->minor_class = cp->minor; | 853 | hdev->minor_class = cp->minor; |
@@ -700,7 +857,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, | |||
700 | if (err == 0) | 857 | if (err == 0) |
701 | err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0); | 858 | err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0); |
702 | 859 | ||
703 | hci_dev_unlock_bh(hdev); | 860 | hci_dev_unlock(hdev); |
704 | hci_dev_put(hdev); | 861 | hci_dev_put(hdev); |
705 | 862 | ||
706 | return err; | 863 | return err; |
@@ -722,7 +879,7 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, | |||
722 | if (!hdev) | 879 | if (!hdev) |
723 | return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV); | 880 | return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV); |
724 | 881 | ||
725 | hci_dev_lock_bh(hdev); | 882 | hci_dev_lock(hdev); |
726 | 883 | ||
727 | BT_DBG("hci%u enable %d", index, cp->enable); | 884 | BT_DBG("hci%u enable %d", index, cp->enable); |
728 | 885 | ||
@@ -732,13 +889,15 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, | |||
732 | } else { | 889 | } else { |
733 | clear_bit(HCI_SERVICE_CACHE, &hdev->flags); | 890 | clear_bit(HCI_SERVICE_CACHE, &hdev->flags); |
734 | err = update_class(hdev); | 891 | err = update_class(hdev); |
892 | if (err == 0) | ||
893 | err = update_eir(hdev); | ||
735 | } | 894 | } |
736 | 895 | ||
737 | if (err == 0) | 896 | if (err == 0) |
738 | err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL, | 897 | err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL, |
739 | 0); | 898 | 0); |
740 | 899 | ||
741 | hci_dev_unlock_bh(hdev); | 900 | hci_dev_unlock(hdev); |
742 | hci_dev_put(hdev); | 901 | hci_dev_put(hdev); |
743 | 902 | ||
744 | return err; | 903 | return err; |
@@ -772,7 +931,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
772 | BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, | 931 | BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, |
773 | key_count); | 932 | key_count); |
774 | 933 | ||
775 | hci_dev_lock_bh(hdev); | 934 | hci_dev_lock(hdev); |
776 | 935 | ||
777 | hci_link_keys_clear(hdev); | 936 | hci_link_keys_clear(hdev); |
778 | 937 | ||
@@ -790,7 +949,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
790 | key->pin_len); | 949 | key->pin_len); |
791 | } | 950 | } |
792 | 951 | ||
793 | hci_dev_unlock_bh(hdev); | 952 | hci_dev_unlock(hdev); |
794 | hci_dev_put(hdev); | 953 | hci_dev_put(hdev); |
795 | 954 | ||
796 | return 0; | 955 | return 0; |
@@ -812,7 +971,7 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
812 | if (!hdev) | 971 | if (!hdev) |
813 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV); | 972 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV); |
814 | 973 | ||
815 | hci_dev_lock_bh(hdev); | 974 | hci_dev_lock(hdev); |
816 | 975 | ||
817 | err = hci_remove_link_key(hdev, &cp->bdaddr); | 976 | err = hci_remove_link_key(hdev, &cp->bdaddr); |
818 | if (err < 0) { | 977 | if (err < 0) { |
@@ -835,7 +994,7 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
835 | } | 994 | } |
836 | 995 | ||
837 | unlock: | 996 | unlock: |
838 | hci_dev_unlock_bh(hdev); | 997 | hci_dev_unlock(hdev); |
839 | hci_dev_put(hdev); | 998 | hci_dev_put(hdev); |
840 | 999 | ||
841 | return err; | 1000 | return err; |
@@ -861,7 +1020,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
861 | if (!hdev) | 1020 | if (!hdev) |
862 | return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV); | 1021 | return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV); |
863 | 1022 | ||
864 | hci_dev_lock_bh(hdev); | 1023 | hci_dev_lock(hdev); |
865 | 1024 | ||
866 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1025 | if (!test_bit(HCI_UP, &hdev->flags)) { |
867 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN); | 1026 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN); |
@@ -893,7 +1052,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
893 | mgmt_pending_remove(cmd); | 1052 | mgmt_pending_remove(cmd); |
894 | 1053 | ||
895 | failed: | 1054 | failed: |
896 | hci_dev_unlock_bh(hdev); | 1055 | hci_dev_unlock(hdev); |
897 | hci_dev_put(hdev); | 1056 | hci_dev_put(hdev); |
898 | 1057 | ||
899 | return err; | 1058 | return err; |
@@ -914,7 +1073,7 @@ static int get_connections(struct sock *sk, u16 index) | |||
914 | if (!hdev) | 1073 | if (!hdev) |
915 | return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV); | 1074 | return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV); |
916 | 1075 | ||
917 | hci_dev_lock_bh(hdev); | 1076 | hci_dev_lock(hdev); |
918 | 1077 | ||
919 | count = 0; | 1078 | count = 0; |
920 | list_for_each(p, &hdev->conn_hash.list) { | 1079 | list_for_each(p, &hdev->conn_hash.list) { |
@@ -945,7 +1104,7 @@ static int get_connections(struct sock *sk, u16 index) | |||
945 | 1104 | ||
946 | unlock: | 1105 | unlock: |
947 | kfree(rp); | 1106 | kfree(rp); |
948 | hci_dev_unlock_bh(hdev); | 1107 | hci_dev_unlock(hdev); |
949 | hci_dev_put(hdev); | 1108 | hci_dev_put(hdev); |
950 | return err; | 1109 | return err; |
951 | } | 1110 | } |
@@ -970,7 +1129,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, | |||
970 | if (!hdev) | 1129 | if (!hdev) |
971 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV); | 1130 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV); |
972 | 1131 | ||
973 | hci_dev_lock_bh(hdev); | 1132 | hci_dev_lock(hdev); |
974 | 1133 | ||
975 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1134 | if (!test_bit(HCI_UP, &hdev->flags)) { |
976 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN); | 1135 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN); |
@@ -992,7 +1151,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, | |||
992 | mgmt_pending_remove(cmd); | 1151 | mgmt_pending_remove(cmd); |
993 | 1152 | ||
994 | failed: | 1153 | failed: |
995 | hci_dev_unlock_bh(hdev); | 1154 | hci_dev_unlock(hdev); |
996 | hci_dev_put(hdev); | 1155 | hci_dev_put(hdev); |
997 | 1156 | ||
998 | return err; | 1157 | return err; |
@@ -1019,7 +1178,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1019 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, | 1178 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, |
1020 | ENODEV); | 1179 | ENODEV); |
1021 | 1180 | ||
1022 | hci_dev_lock_bh(hdev); | 1181 | hci_dev_lock(hdev); |
1023 | 1182 | ||
1024 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1183 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1025 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, | 1184 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, |
@@ -1040,7 +1199,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1040 | mgmt_pending_remove(cmd); | 1199 | mgmt_pending_remove(cmd); |
1041 | 1200 | ||
1042 | failed: | 1201 | failed: |
1043 | hci_dev_unlock_bh(hdev); | 1202 | hci_dev_unlock(hdev); |
1044 | hci_dev_put(hdev); | 1203 | hci_dev_put(hdev); |
1045 | 1204 | ||
1046 | return err; | 1205 | return err; |
@@ -1063,14 +1222,14 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data, | |||
1063 | if (!hdev) | 1222 | if (!hdev) |
1064 | return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV); | 1223 | return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV); |
1065 | 1224 | ||
1066 | hci_dev_lock_bh(hdev); | 1225 | hci_dev_lock(hdev); |
1067 | 1226 | ||
1068 | hdev->io_capability = cp->io_capability; | 1227 | hdev->io_capability = cp->io_capability; |
1069 | 1228 | ||
1070 | BT_DBG("%s IO capability set to 0x%02x", hdev->name, | 1229 | BT_DBG("%s IO capability set to 0x%02x", hdev->name, |
1071 | hdev->io_capability); | 1230 | hdev->io_capability); |
1072 | 1231 | ||
1073 | hci_dev_unlock_bh(hdev); | 1232 | hci_dev_unlock(hdev); |
1074 | hci_dev_put(hdev); | 1233 | hci_dev_put(hdev); |
1075 | 1234 | ||
1076 | return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0); | 1235 | return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0); |
@@ -1156,7 +1315,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1156 | if (!hdev) | 1315 | if (!hdev) |
1157 | return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV); | 1316 | return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV); |
1158 | 1317 | ||
1159 | hci_dev_lock_bh(hdev); | 1318 | hci_dev_lock(hdev); |
1160 | 1319 | ||
1161 | if (cp->io_cap == 0x03) { | 1320 | if (cp->io_cap == 0x03) { |
1162 | sec_level = BT_SECURITY_MEDIUM; | 1321 | sec_level = BT_SECURITY_MEDIUM; |
@@ -1198,7 +1357,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1198 | err = 0; | 1357 | err = 0; |
1199 | 1358 | ||
1200 | unlock: | 1359 | unlock: |
1201 | hci_dev_unlock_bh(hdev); | 1360 | hci_dev_unlock(hdev); |
1202 | hci_dev_put(hdev); | 1361 | hci_dev_put(hdev); |
1203 | 1362 | ||
1204 | return err; | 1363 | return err; |
@@ -1230,7 +1389,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1230 | if (!hdev) | 1389 | if (!hdev) |
1231 | return cmd_status(sk, index, mgmt_op, ENODEV); | 1390 | return cmd_status(sk, index, mgmt_op, ENODEV); |
1232 | 1391 | ||
1233 | hci_dev_lock_bh(hdev); | 1392 | hci_dev_lock(hdev); |
1234 | 1393 | ||
1235 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1394 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1236 | err = cmd_status(sk, index, mgmt_op, ENETDOWN); | 1395 | err = cmd_status(sk, index, mgmt_op, ENETDOWN); |
@@ -1248,7 +1407,163 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1248 | mgmt_pending_remove(cmd); | 1407 | mgmt_pending_remove(cmd); |
1249 | 1408 | ||
1250 | failed: | 1409 | failed: |
1251 | hci_dev_unlock_bh(hdev); | 1410 | hci_dev_unlock(hdev); |
1411 | hci_dev_put(hdev); | ||
1412 | |||
1413 | return err; | ||
1414 | } | ||
1415 | |||
1416 | static int set_local_name(struct sock *sk, u16 index, unsigned char *data, | ||
1417 | u16 len) | ||
1418 | { | ||
1419 | struct mgmt_cp_set_local_name *mgmt_cp = (void *) data; | ||
1420 | struct hci_cp_write_local_name hci_cp; | ||
1421 | struct hci_dev *hdev; | ||
1422 | struct pending_cmd *cmd; | ||
1423 | int err; | ||
1424 | |||
1425 | BT_DBG(""); | ||
1426 | |||
1427 | if (len != sizeof(*mgmt_cp)) | ||
1428 | return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL); | ||
1429 | |||
1430 | hdev = hci_dev_get(index); | ||
1431 | if (!hdev) | ||
1432 | return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV); | ||
1433 | |||
1434 | hci_dev_lock(hdev); | ||
1435 | |||
1436 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len); | ||
1437 | if (!cmd) { | ||
1438 | err = -ENOMEM; | ||
1439 | goto failed; | ||
1440 | } | ||
1441 | |||
1442 | memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name)); | ||
1443 | err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp), | ||
1444 | &hci_cp); | ||
1445 | if (err < 0) | ||
1446 | mgmt_pending_remove(cmd); | ||
1447 | |||
1448 | failed: | ||
1449 | hci_dev_unlock(hdev); | ||
1450 | hci_dev_put(hdev); | ||
1451 | |||
1452 | return err; | ||
1453 | } | ||
1454 | |||
1455 | static int read_local_oob_data(struct sock *sk, u16 index) | ||
1456 | { | ||
1457 | struct hci_dev *hdev; | ||
1458 | struct pending_cmd *cmd; | ||
1459 | int err; | ||
1460 | |||
1461 | BT_DBG("hci%u", index); | ||
1462 | |||
1463 | hdev = hci_dev_get(index); | ||
1464 | if (!hdev) | ||
1465 | return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
1466 | ENODEV); | ||
1467 | |||
1468 | hci_dev_lock(hdev); | ||
1469 | |||
1470 | if (!test_bit(HCI_UP, &hdev->flags)) { | ||
1471 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
1472 | ENETDOWN); | ||
1473 | goto unlock; | ||
1474 | } | ||
1475 | |||
1476 | if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { | ||
1477 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
1478 | EOPNOTSUPP); | ||
1479 | goto unlock; | ||
1480 | } | ||
1481 | |||
1482 | if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) { | ||
1483 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); | ||
1484 | goto unlock; | ||
1485 | } | ||
1486 | |||
1487 | cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0); | ||
1488 | if (!cmd) { | ||
1489 | err = -ENOMEM; | ||
1490 | goto unlock; | ||
1491 | } | ||
1492 | |||
1493 | err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL); | ||
1494 | if (err < 0) | ||
1495 | mgmt_pending_remove(cmd); | ||
1496 | |||
1497 | unlock: | ||
1498 | hci_dev_unlock(hdev); | ||
1499 | hci_dev_put(hdev); | ||
1500 | |||
1501 | return err; | ||
1502 | } | ||
1503 | |||
1504 | static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, | ||
1505 | u16 len) | ||
1506 | { | ||
1507 | struct hci_dev *hdev; | ||
1508 | struct mgmt_cp_add_remote_oob_data *cp = (void *) data; | ||
1509 | int err; | ||
1510 | |||
1511 | BT_DBG("hci%u ", index); | ||
1512 | |||
1513 | if (len != sizeof(*cp)) | ||
1514 | return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, | ||
1515 | EINVAL); | ||
1516 | |||
1517 | hdev = hci_dev_get(index); | ||
1518 | if (!hdev) | ||
1519 | return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, | ||
1520 | ENODEV); | ||
1521 | |||
1522 | hci_dev_lock(hdev); | ||
1523 | |||
1524 | err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, | ||
1525 | cp->randomizer); | ||
1526 | if (err < 0) | ||
1527 | err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err); | ||
1528 | else | ||
1529 | err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, | ||
1530 | 0); | ||
1531 | |||
1532 | hci_dev_unlock(hdev); | ||
1533 | hci_dev_put(hdev); | ||
1534 | |||
1535 | return err; | ||
1536 | } | ||
1537 | |||
1538 | static int remove_remote_oob_data(struct sock *sk, u16 index, | ||
1539 | unsigned char *data, u16 len) | ||
1540 | { | ||
1541 | struct hci_dev *hdev; | ||
1542 | struct mgmt_cp_remove_remote_oob_data *cp = (void *) data; | ||
1543 | int err; | ||
1544 | |||
1545 | BT_DBG("hci%u ", index); | ||
1546 | |||
1547 | if (len != sizeof(*cp)) | ||
1548 | return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | ||
1549 | EINVAL); | ||
1550 | |||
1551 | hdev = hci_dev_get(index); | ||
1552 | if (!hdev) | ||
1553 | return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | ||
1554 | ENODEV); | ||
1555 | |||
1556 | hci_dev_lock(hdev); | ||
1557 | |||
1558 | err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); | ||
1559 | if (err < 0) | ||
1560 | err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | ||
1561 | -err); | ||
1562 | else | ||
1563 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | ||
1564 | NULL, 0); | ||
1565 | |||
1566 | hci_dev_unlock(hdev); | ||
1252 | hci_dev_put(hdev); | 1567 | hci_dev_put(hdev); |
1253 | 1568 | ||
1254 | return err; | 1569 | return err; |
@@ -1266,7 +1581,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1266 | if (msglen < sizeof(*hdr)) | 1581 | if (msglen < sizeof(*hdr)) |
1267 | return -EINVAL; | 1582 | return -EINVAL; |
1268 | 1583 | ||
1269 | buf = kmalloc(msglen, GFP_ATOMIC); | 1584 | buf = kmalloc(msglen, GFP_KERNEL); |
1270 | if (!buf) | 1585 | if (!buf) |
1271 | return -ENOMEM; | 1586 | return -ENOMEM; |
1272 | 1587 | ||
@@ -1349,6 +1664,20 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1349 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: | 1664 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: |
1350 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); | 1665 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); |
1351 | break; | 1666 | break; |
1667 | case MGMT_OP_SET_LOCAL_NAME: | ||
1668 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); | ||
1669 | break; | ||
1670 | case MGMT_OP_READ_LOCAL_OOB_DATA: | ||
1671 | err = read_local_oob_data(sk, index); | ||
1672 | break; | ||
1673 | case MGMT_OP_ADD_REMOTE_OOB_DATA: | ||
1674 | err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len); | ||
1675 | break; | ||
1676 | case MGMT_OP_REMOVE_REMOTE_OOB_DATA: | ||
1677 | err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr), | ||
1678 | len); | ||
1679 | break; | ||
1680 | |||
1352 | default: | 1681 | default: |
1353 | BT_DBG("Unknown op %u", opcode); | 1682 | BT_DBG("Unknown op %u", opcode); |
1354 | err = cmd_status(sk, index, opcode, 0x01); | 1683 | err = cmd_status(sk, index, opcode, 0x01); |
@@ -1382,7 +1711,7 @@ struct cmd_lookup { | |||
1382 | 1711 | ||
1383 | static void mode_rsp(struct pending_cmd *cmd, void *data) | 1712 | static void mode_rsp(struct pending_cmd *cmd, void *data) |
1384 | { | 1713 | { |
1385 | struct mgmt_mode *cp = cmd->cmd; | 1714 | struct mgmt_mode *cp = cmd->param; |
1386 | struct cmd_lookup *match = data; | 1715 | struct cmd_lookup *match = data; |
1387 | 1716 | ||
1388 | if (cp->val != match->val) | 1717 | if (cp->val != match->val) |
@@ -1481,7 +1810,7 @@ int mgmt_connected(u16 index, bdaddr_t *bdaddr) | |||
1481 | 1810 | ||
1482 | static void disconnect_rsp(struct pending_cmd *cmd, void *data) | 1811 | static void disconnect_rsp(struct pending_cmd *cmd, void *data) |
1483 | { | 1812 | { |
1484 | struct mgmt_cp_disconnect *cp = cmd->cmd; | 1813 | struct mgmt_cp_disconnect *cp = cmd->param; |
1485 | struct sock **sk = data; | 1814 | struct sock **sk = data; |
1486 | struct mgmt_rp_disconnect rp; | 1815 | struct mgmt_rp_disconnect rp; |
1487 | 1816 | ||
@@ -1645,3 +1974,104 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status) | |||
1645 | 1974 | ||
1646 | return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); | 1975 | return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); |
1647 | } | 1976 | } |
1977 | |||
1978 | int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) | ||
1979 | { | ||
1980 | struct pending_cmd *cmd; | ||
1981 | struct hci_dev *hdev; | ||
1982 | struct mgmt_cp_set_local_name ev; | ||
1983 | int err; | ||
1984 | |||
1985 | memset(&ev, 0, sizeof(ev)); | ||
1986 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | ||
1987 | |||
1988 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index); | ||
1989 | if (!cmd) | ||
1990 | goto send_event; | ||
1991 | |||
1992 | if (status) { | ||
1993 | err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO); | ||
1994 | goto failed; | ||
1995 | } | ||
1996 | |||
1997 | hdev = hci_dev_get(index); | ||
1998 | if (hdev) { | ||
1999 | hci_dev_lock_bh(hdev); | ||
2000 | update_eir(hdev); | ||
2001 | hci_dev_unlock_bh(hdev); | ||
2002 | hci_dev_put(hdev); | ||
2003 | } | ||
2004 | |||
2005 | err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev, | ||
2006 | sizeof(ev)); | ||
2007 | if (err < 0) | ||
2008 | goto failed; | ||
2009 | |||
2010 | send_event: | ||
2011 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev), | ||
2012 | cmd ? cmd->sk : NULL); | ||
2013 | |||
2014 | failed: | ||
2015 | if (cmd) | ||
2016 | mgmt_pending_remove(cmd); | ||
2017 | return err; | ||
2018 | } | ||
2019 | |||
2020 | int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, | ||
2021 | u8 status) | ||
2022 | { | ||
2023 | struct pending_cmd *cmd; | ||
2024 | int err; | ||
2025 | |||
2026 | BT_DBG("hci%u status %u", index, status); | ||
2027 | |||
2028 | cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index); | ||
2029 | if (!cmd) | ||
2030 | return -ENOENT; | ||
2031 | |||
2032 | if (status) { | ||
2033 | err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
2034 | EIO); | ||
2035 | } else { | ||
2036 | struct mgmt_rp_read_local_oob_data rp; | ||
2037 | |||
2038 | memcpy(rp.hash, hash, sizeof(rp.hash)); | ||
2039 | memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); | ||
2040 | |||
2041 | err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
2042 | &rp, sizeof(rp)); | ||
2043 | } | ||
2044 | |||
2045 | mgmt_pending_remove(cmd); | ||
2046 | |||
2047 | return err; | ||
2048 | } | ||
2049 | |||
2050 | int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, | ||
2051 | u8 *eir) | ||
2052 | { | ||
2053 | struct mgmt_ev_device_found ev; | ||
2054 | |||
2055 | memset(&ev, 0, sizeof(ev)); | ||
2056 | |||
2057 | bacpy(&ev.bdaddr, bdaddr); | ||
2058 | memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class)); | ||
2059 | ev.rssi = rssi; | ||
2060 | |||
2061 | if (eir) | ||
2062 | memcpy(ev.eir, eir, sizeof(ev.eir)); | ||
2063 | |||
2064 | return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); | ||
2065 | } | ||
2066 | |||
2067 | int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name) | ||
2068 | { | ||
2069 | struct mgmt_ev_remote_name ev; | ||
2070 | |||
2071 | memset(&ev, 0, sizeof(ev)); | ||
2072 | |||
2073 | bacpy(&ev.bdaddr, bdaddr); | ||
2074 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | ||
2075 | |||
2076 | return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL); | ||
2077 | } | ||
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 513f85cc2ae1..f5fdfcbf552a 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -2,7 +2,6 @@ config MAC80211 | |||
2 | tristate "Generic IEEE 802.11 Networking Stack (mac80211)" | 2 | tristate "Generic IEEE 802.11 Networking Stack (mac80211)" |
3 | depends on CFG80211 | 3 | depends on CFG80211 |
4 | select CRYPTO | 4 | select CRYPTO |
5 | select CRYPTO_ECB | ||
6 | select CRYPTO_ARC4 | 5 | select CRYPTO_ARC4 |
7 | select CRYPTO_AES | 6 | select CRYPTO_AES |
8 | select CRC32 | 7 | select CRC32 |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 334213571ad0..bf5d28da46e6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -342,7 +342,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
342 | STATION_INFO_TX_FAILED | | 342 | STATION_INFO_TX_FAILED | |
343 | STATION_INFO_TX_BITRATE | | 343 | STATION_INFO_TX_BITRATE | |
344 | STATION_INFO_RX_BITRATE | | 344 | STATION_INFO_RX_BITRATE | |
345 | STATION_INFO_RX_DROP_MISC; | 345 | STATION_INFO_RX_DROP_MISC | |
346 | STATION_INFO_BSS_PARAM; | ||
346 | 347 | ||
347 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 348 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
348 | sinfo->rx_bytes = sta->rx_bytes; | 349 | sinfo->rx_bytes = sta->rx_bytes; |
@@ -389,6 +390,16 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
389 | sinfo->plink_state = sta->plink_state; | 390 | sinfo->plink_state = sta->plink_state; |
390 | #endif | 391 | #endif |
391 | } | 392 | } |
393 | |||
394 | sinfo->bss_param.flags = 0; | ||
395 | if (sdata->vif.bss_conf.use_cts_prot) | ||
396 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; | ||
397 | if (sdata->vif.bss_conf.use_short_preamble) | ||
398 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; | ||
399 | if (sdata->vif.bss_conf.use_short_slot) | ||
400 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | ||
401 | sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; | ||
402 | sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; | ||
392 | } | 403 | } |
393 | 404 | ||
394 | 405 | ||
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 51f0d780dafa..0a602dbfdb2b 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -37,7 +37,7 @@ int mac80211_format_buffer(char __user *userbuf, size_t count, | |||
37 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 37 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
38 | } | 38 | } |
39 | 39 | ||
40 | #define DEBUGFS_READONLY_FILE(name, fmt, value...) \ | 40 | #define DEBUGFS_READONLY_FILE_FN(name, fmt, value...) \ |
41 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ | 41 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ |
42 | size_t count, loff_t *ppos) \ | 42 | size_t count, loff_t *ppos) \ |
43 | { \ | 43 | { \ |
@@ -45,14 +45,19 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ | |||
45 | \ | 45 | \ |
46 | return mac80211_format_buffer(userbuf, count, ppos, \ | 46 | return mac80211_format_buffer(userbuf, count, ppos, \ |
47 | fmt "\n", ##value); \ | 47 | fmt "\n", ##value); \ |
48 | } \ | 48 | } |
49 | \ | 49 | |
50 | #define DEBUGFS_READONLY_FILE_OPS(name) \ | ||
50 | static const struct file_operations name## _ops = { \ | 51 | static const struct file_operations name## _ops = { \ |
51 | .read = name## _read, \ | 52 | .read = name## _read, \ |
52 | .open = mac80211_open_file_generic, \ | 53 | .open = mac80211_open_file_generic, \ |
53 | .llseek = generic_file_llseek, \ | 54 | .llseek = generic_file_llseek, \ |
54 | }; | 55 | }; |
55 | 56 | ||
57 | #define DEBUGFS_READONLY_FILE(name, fmt, value...) \ | ||
58 | DEBUGFS_READONLY_FILE_FN(name, fmt, value) \ | ||
59 | DEBUGFS_READONLY_FILE_OPS(name) | ||
60 | |||
56 | #define DEBUGFS_ADD(name) \ | 61 | #define DEBUGFS_ADD(name) \ |
57 | debugfs_create_file(#name, 0400, phyd, local, &name## _ops); | 62 | debugfs_create_file(#name, 0400, phyd, local, &name## _ops); |
58 | 63 | ||
@@ -291,11 +296,70 @@ static ssize_t channel_type_read(struct file *file, char __user *user_buf, | |||
291 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | 296 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); |
292 | } | 297 | } |
293 | 298 | ||
294 | static const struct file_operations channel_type_ops = { | 299 | static ssize_t hwflags_read(struct file *file, char __user *user_buf, |
295 | .read = channel_type_read, | 300 | size_t count, loff_t *ppos) |
296 | .open = mac80211_open_file_generic, | 301 | { |
297 | .llseek = default_llseek, | 302 | struct ieee80211_local *local = file->private_data; |
298 | }; | 303 | int mxln = 500; |
304 | ssize_t rv; | ||
305 | char *buf = kzalloc(mxln, GFP_KERNEL); | ||
306 | int sf = 0; /* how many written so far */ | ||
307 | |||
308 | sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); | ||
309 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | ||
310 | sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); | ||
311 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | ||
312 | sf += snprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); | ||
313 | if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) | ||
314 | sf += snprintf(buf + sf, mxln - sf, | ||
315 | "HOST_BCAST_PS_BUFFERING\n"); | ||
316 | if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) | ||
317 | sf += snprintf(buf + sf, mxln - sf, | ||
318 | "2GHZ_SHORT_SLOT_INCAPABLE\n"); | ||
319 | if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) | ||
320 | sf += snprintf(buf + sf, mxln - sf, | ||
321 | "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); | ||
322 | if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | ||
323 | sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); | ||
324 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
325 | sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); | ||
326 | if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) | ||
327 | sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n"); | ||
328 | if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) | ||
329 | sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); | ||
330 | if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) | ||
331 | sf += snprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); | ||
332 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS) | ||
333 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); | ||
334 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | ||
335 | sf += snprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); | ||
336 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | ||
337 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); | ||
338 | if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) | ||
339 | sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); | ||
340 | if (local->hw.flags & IEEE80211_HW_BEACON_FILTER) | ||
341 | sf += snprintf(buf + sf, mxln - sf, "BEACON_FILTER\n"); | ||
342 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) | ||
343 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); | ||
344 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) | ||
345 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_SMPS\n"); | ||
346 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | ||
347 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); | ||
348 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | ||
349 | sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); | ||
350 | if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
351 | sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); | ||
352 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) | ||
353 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_CQM_RSSI\n"); | ||
354 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) | ||
355 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); | ||
356 | if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) | ||
357 | sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); | ||
358 | |||
359 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | ||
360 | kfree(buf); | ||
361 | return rv; | ||
362 | } | ||
299 | 363 | ||
300 | static ssize_t queues_read(struct file *file, char __user *user_buf, | 364 | static ssize_t queues_read(struct file *file, char __user *user_buf, |
301 | size_t count, loff_t *ppos) | 365 | size_t count, loff_t *ppos) |
@@ -315,11 +379,9 @@ static ssize_t queues_read(struct file *file, char __user *user_buf, | |||
315 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | 379 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); |
316 | } | 380 | } |
317 | 381 | ||
318 | static const struct file_operations queues_ops = { | 382 | DEBUGFS_READONLY_FILE_OPS(hwflags); |
319 | .read = queues_read, | 383 | DEBUGFS_READONLY_FILE_OPS(channel_type); |
320 | .open = mac80211_open_file_generic, | 384 | DEBUGFS_READONLY_FILE_OPS(queues); |
321 | .llseek = default_llseek, | ||
322 | }; | ||
323 | 385 | ||
324 | /* statistics stuff */ | 386 | /* statistics stuff */ |
325 | 387 | ||
@@ -395,6 +457,7 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
395 | DEBUGFS_ADD(uapsd_queues); | 457 | DEBUGFS_ADD(uapsd_queues); |
396 | DEBUGFS_ADD(uapsd_max_sp_len); | 458 | DEBUGFS_ADD(uapsd_max_sp_len); |
397 | DEBUGFS_ADD(channel_type); | 459 | DEBUGFS_ADD(channel_type); |
460 | DEBUGFS_ADD(hwflags); | ||
398 | DEBUGFS_ADD(user_power); | 461 | DEBUGFS_ADD(user_power); |
399 | DEBUGFS_ADD(power); | 462 | DEBUGFS_ADD(power); |
400 | 463 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3e81af1fce58..14883966374e 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -661,7 +661,6 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
661 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | 661 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, |
662 | struct sk_buff *req) | 662 | struct sk_buff *req) |
663 | { | 663 | { |
664 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req); | ||
665 | struct ieee80211_mgmt *mgmt = (void *)req->data; | 664 | struct ieee80211_mgmt *mgmt = (void *)req->data; |
666 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 665 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
667 | struct ieee80211_local *local = sdata->local; | 666 | struct ieee80211_local *local = sdata->local; |
@@ -685,7 +684,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
685 | mgmt->bssid, tx_last_beacon); | 684 | mgmt->bssid, tx_last_beacon); |
686 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 685 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
687 | 686 | ||
688 | if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH)) | 687 | if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) |
689 | return; | 688 | return; |
690 | 689 | ||
691 | if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && | 690 | if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c18396c248d7..89ce1e329b5d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -809,8 +809,8 @@ struct ieee80211_local { | |||
809 | 809 | ||
810 | struct rate_control_ref *rate_ctrl; | 810 | struct rate_control_ref *rate_ctrl; |
811 | 811 | ||
812 | struct crypto_blkcipher *wep_tx_tfm; | 812 | struct crypto_cipher *wep_tx_tfm; |
813 | struct crypto_blkcipher *wep_rx_tfm; | 813 | struct crypto_cipher *wep_rx_tfm; |
814 | u32 wep_iv; | 814 | u32 wep_iv; |
815 | 815 | ||
816 | /* see iface.c */ | 816 | /* see iface.c */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 562d2984c482..dc50fc3153e5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -879,10 +879,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
879 | 879 | ||
880 | local->dynamic_ps_forced_timeout = -1; | 880 | local->dynamic_ps_forced_timeout = -1; |
881 | 881 | ||
882 | result = sta_info_start(local); | ||
883 | if (result < 0) | ||
884 | goto fail_sta_info; | ||
885 | |||
886 | result = ieee80211_wep_init(local); | 882 | result = ieee80211_wep_init(local); |
887 | if (result < 0) | 883 | if (result < 0) |
888 | wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", | 884 | wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", |
@@ -945,7 +941,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
945 | rtnl_unlock(); | 941 | rtnl_unlock(); |
946 | ieee80211_wep_free(local); | 942 | ieee80211_wep_free(local); |
947 | sta_info_stop(local); | 943 | sta_info_stop(local); |
948 | fail_sta_info: | ||
949 | destroy_workqueue(local->workqueue); | 944 | destroy_workqueue(local->workqueue); |
950 | fail_workqueue: | 945 | fail_workqueue: |
951 | wiphy_unregister(local->hw.wiphy); | 946 | wiphy_unregister(local->hw.wiphy); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 64d92d5a7f40..865fed4cc18b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -90,20 +90,11 @@ enum rx_mgmt_action { | |||
90 | /* no action required */ | 90 | /* no action required */ |
91 | RX_MGMT_NONE, | 91 | RX_MGMT_NONE, |
92 | 92 | ||
93 | /* caller must call cfg80211_send_rx_auth() */ | ||
94 | RX_MGMT_CFG80211_AUTH, | ||
95 | |||
96 | /* caller must call cfg80211_send_rx_assoc() */ | ||
97 | RX_MGMT_CFG80211_ASSOC, | ||
98 | |||
99 | /* caller must call cfg80211_send_deauth() */ | 93 | /* caller must call cfg80211_send_deauth() */ |
100 | RX_MGMT_CFG80211_DEAUTH, | 94 | RX_MGMT_CFG80211_DEAUTH, |
101 | 95 | ||
102 | /* caller must call cfg80211_send_disassoc() */ | 96 | /* caller must call cfg80211_send_disassoc() */ |
103 | RX_MGMT_CFG80211_DISASSOC, | 97 | RX_MGMT_CFG80211_DISASSOC, |
104 | |||
105 | /* caller must tell cfg80211 about internal error */ | ||
106 | RX_MGMT_CFG80211_ASSOC_ERROR, | ||
107 | }; | 98 | }; |
108 | 99 | ||
109 | /* utils */ | 100 | /* utils */ |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c5d4530d8284..1f0b010904b8 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -707,6 +707,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
707 | /* | 707 | /* |
708 | * If the current MPDU is in the right order and nothing else | 708 | * If the current MPDU is in the right order and nothing else |
709 | * is stored we can process it directly, no need to buffer it. | 709 | * is stored we can process it directly, no need to buffer it. |
710 | * If it is first but there's something stored, we may be able | ||
711 | * to release frames after this one. | ||
710 | */ | 712 | */ |
711 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 713 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
712 | tid_agg_rx->stored_mpdu_num == 0) { | 714 | tid_agg_rx->stored_mpdu_num == 0) { |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 13e8c30adf01..52d4b1a695c9 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -698,6 +698,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
698 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 698 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
699 | cancel_work_sync(&sta->drv_unblock_wk); | 699 | cancel_work_sync(&sta->drv_unblock_wk); |
700 | 700 | ||
701 | cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL); | ||
702 | |||
701 | rate_control_remove_sta_debugfs(sta); | 703 | rate_control_remove_sta_debugfs(sta); |
702 | ieee80211_sta_debugfs_remove(sta); | 704 | ieee80211_sta_debugfs_remove(sta); |
703 | 705 | ||
@@ -766,9 +768,8 @@ static void sta_info_cleanup(unsigned long data) | |||
766 | if (!timer_needed) | 768 | if (!timer_needed) |
767 | return; | 769 | return; |
768 | 770 | ||
769 | local->sta_cleanup.expires = | 771 | mod_timer(&local->sta_cleanup, |
770 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 772 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL)); |
771 | add_timer(&local->sta_cleanup); | ||
772 | } | 773 | } |
773 | 774 | ||
774 | void sta_info_init(struct ieee80211_local *local) | 775 | void sta_info_init(struct ieee80211_local *local) |
@@ -781,14 +782,6 @@ void sta_info_init(struct ieee80211_local *local) | |||
781 | 782 | ||
782 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 783 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
783 | (unsigned long)local); | 784 | (unsigned long)local); |
784 | local->sta_cleanup.expires = | ||
785 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | ||
786 | } | ||
787 | |||
788 | int sta_info_start(struct ieee80211_local *local) | ||
789 | { | ||
790 | add_timer(&local->sta_cleanup); | ||
791 | return 0; | ||
792 | } | 785 | } |
793 | 786 | ||
794 | void sta_info_stop(struct ieee80211_local *local) | 787 | void sta_info_stop(struct ieee80211_local *local) |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b2f95966c7f4..87b18ba1e0e9 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -497,7 +497,6 @@ void sta_info_set_tim_bit(struct sta_info *sta); | |||
497 | void sta_info_clear_tim_bit(struct sta_info *sta); | 497 | void sta_info_clear_tim_bit(struct sta_info *sta); |
498 | 498 | ||
499 | void sta_info_init(struct ieee80211_local *local); | 499 | void sta_info_init(struct ieee80211_local *local); |
500 | int sta_info_start(struct ieee80211_local *local); | ||
501 | void sta_info_stop(struct ieee80211_local *local); | 500 | void sta_info_stop(struct ieee80211_local *local); |
502 | int sta_info_flush(struct ieee80211_local *local, | 501 | int sta_info_flush(struct ieee80211_local *local, |
503 | struct ieee80211_sub_if_data *sdata); | 502 | struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index b936dd29e92b..3ed3c835fbbf 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -189,16 +189,19 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
189 | bool acked; | 189 | bool acked; |
190 | 190 | ||
191 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 191 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
192 | /* the HW cannot have attempted that rate */ | 192 | if (info->status.rates[i].idx < 0) { |
193 | if (i >= hw->max_report_rates) { | 193 | break; |
194 | } else if (i >= hw->max_report_rates) { | ||
195 | /* the HW cannot have attempted that rate */ | ||
194 | info->status.rates[i].idx = -1; | 196 | info->status.rates[i].idx = -1; |
195 | info->status.rates[i].count = 0; | 197 | info->status.rates[i].count = 0; |
196 | } else if (info->status.rates[i].idx >= 0) { | 198 | break; |
197 | rates_idx = i; | ||
198 | } | 199 | } |
199 | 200 | ||
200 | retry_count += info->status.rates[i].count; | 201 | retry_count += info->status.rates[i].count; |
201 | } | 202 | } |
203 | rates_idx = i - 1; | ||
204 | |||
202 | if (retry_count < 0) | 205 | if (retry_count < 0) |
203 | retry_count = 0; | 206 | retry_count = 0; |
204 | 207 | ||
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index e840c9cd46db..757e4eb2baf7 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -202,7 +202,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key); | |||
202 | * @payload_len is the length of payload (_not_ including IV/ICV length). | 202 | * @payload_len is the length of payload (_not_ including IV/ICV length). |
203 | * @ta is the transmitter addresses. | 203 | * @ta is the transmitter addresses. |
204 | */ | 204 | */ |
205 | int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | 205 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, |
206 | struct ieee80211_key *key, | 206 | struct ieee80211_key *key, |
207 | u8 *pos, size_t payload_len, u8 *ta) | 207 | u8 *pos, size_t payload_len, u8 *ta) |
208 | { | 208 | { |
@@ -223,7 +223,7 @@ int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | |||
223 | * beginning of the buffer containing IEEE 802.11 header payload, i.e., | 223 | * beginning of the buffer containing IEEE 802.11 header payload, i.e., |
224 | * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the | 224 | * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the |
225 | * length of payload, including IV, Ext. IV, MIC, ICV. */ | 225 | * length of payload, including IV, Ext. IV, MIC, ICV. */ |
226 | int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | 226 | int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, |
227 | struct ieee80211_key *key, | 227 | struct ieee80211_key *key, |
228 | u8 *payload, size_t payload_len, u8 *ta, | 228 | u8 *payload, size_t payload_len, u8 *ta, |
229 | u8 *ra, int only_iv, int queue, | 229 | u8 *ra, int only_iv, int queue, |
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h index 7e83dee976fa..1cab9c86978f 100644 --- a/net/mac80211/tkip.h +++ b/net/mac80211/tkip.h | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16); | 16 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16); |
17 | 17 | ||
18 | int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | 18 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, |
19 | struct ieee80211_key *key, | 19 | struct ieee80211_key *key, |
20 | u8 *pos, size_t payload_len, u8 *ta); | 20 | u8 *pos, size_t payload_len, u8 *ta); |
21 | enum { | 21 | enum { |
@@ -24,7 +24,7 @@ enum { | |||
24 | TKIP_DECRYPT_INVALID_KEYIDX = -2, | 24 | TKIP_DECRYPT_INVALID_KEYIDX = -2, |
25 | TKIP_DECRYPT_REPLAY = -3, | 25 | TKIP_DECRYPT_REPLAY = -3, |
26 | }; | 26 | }; |
27 | int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | 27 | int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, |
28 | struct ieee80211_key *key, | 28 | struct ieee80211_key *key, |
29 | u8 *payload, size_t payload_len, u8 *ta, | 29 | u8 *payload, size_t payload_len, u8 *ta, |
30 | u8 *ra, int only_iv, int queue, | 30 | u8 *ra, int only_iv, int queue, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 556647a910ac..ef0560a2346a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1290,7 +1290,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1290 | } | 1290 | } |
1291 | } | 1291 | } |
1292 | 1292 | ||
1293 | add_timer(&local->sta_cleanup); | 1293 | mod_timer(&local->sta_cleanup, jiffies + 1); |
1294 | 1294 | ||
1295 | mutex_lock(&local->sta_mtx); | 1295 | mutex_lock(&local->sta_mtx); |
1296 | list_for_each_entry(sta, &local->sta_list, list) | 1296 | list_for_each_entry(sta, &local->sta_list, list) |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 2ff6d1e3ed21..a1c6bfd55f0f 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -30,17 +30,15 @@ int ieee80211_wep_init(struct ieee80211_local *local) | |||
30 | /* start WEP IV from a random value */ | 30 | /* start WEP IV from a random value */ |
31 | get_random_bytes(&local->wep_iv, WEP_IV_LEN); | 31 | get_random_bytes(&local->wep_iv, WEP_IV_LEN); |
32 | 32 | ||
33 | local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, | 33 | local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); |
34 | CRYPTO_ALG_ASYNC); | ||
35 | if (IS_ERR(local->wep_tx_tfm)) { | 34 | if (IS_ERR(local->wep_tx_tfm)) { |
36 | local->wep_rx_tfm = ERR_PTR(-EINVAL); | 35 | local->wep_rx_tfm = ERR_PTR(-EINVAL); |
37 | return PTR_ERR(local->wep_tx_tfm); | 36 | return PTR_ERR(local->wep_tx_tfm); |
38 | } | 37 | } |
39 | 38 | ||
40 | local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, | 39 | local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); |
41 | CRYPTO_ALG_ASYNC); | ||
42 | if (IS_ERR(local->wep_rx_tfm)) { | 40 | if (IS_ERR(local->wep_rx_tfm)) { |
43 | crypto_free_blkcipher(local->wep_tx_tfm); | 41 | crypto_free_cipher(local->wep_tx_tfm); |
44 | local->wep_tx_tfm = ERR_PTR(-EINVAL); | 42 | local->wep_tx_tfm = ERR_PTR(-EINVAL); |
45 | return PTR_ERR(local->wep_rx_tfm); | 43 | return PTR_ERR(local->wep_rx_tfm); |
46 | } | 44 | } |
@@ -51,9 +49,9 @@ int ieee80211_wep_init(struct ieee80211_local *local) | |||
51 | void ieee80211_wep_free(struct ieee80211_local *local) | 49 | void ieee80211_wep_free(struct ieee80211_local *local) |
52 | { | 50 | { |
53 | if (!IS_ERR(local->wep_tx_tfm)) | 51 | if (!IS_ERR(local->wep_tx_tfm)) |
54 | crypto_free_blkcipher(local->wep_tx_tfm); | 52 | crypto_free_cipher(local->wep_tx_tfm); |
55 | if (!IS_ERR(local->wep_rx_tfm)) | 53 | if (!IS_ERR(local->wep_rx_tfm)) |
56 | crypto_free_blkcipher(local->wep_rx_tfm); | 54 | crypto_free_cipher(local->wep_rx_tfm); |
57 | } | 55 | } |
58 | 56 | ||
59 | static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) | 57 | static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) |
@@ -127,12 +125,11 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, | |||
127 | /* Perform WEP encryption using given key. data buffer must have tailroom | 125 | /* Perform WEP encryption using given key. data buffer must have tailroom |
128 | * for 4-byte ICV. data_len must not include this ICV. Note: this function | 126 | * for 4-byte ICV. data_len must not include this ICV. Note: this function |
129 | * does _not_ add IV. data = RC4(data | CRC32(data)) */ | 127 | * does _not_ add IV. data = RC4(data | CRC32(data)) */ |
130 | int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | 128 | int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, |
131 | size_t klen, u8 *data, size_t data_len) | 129 | size_t klen, u8 *data, size_t data_len) |
132 | { | 130 | { |
133 | struct blkcipher_desc desc = { .tfm = tfm }; | ||
134 | struct scatterlist sg; | ||
135 | __le32 icv; | 131 | __le32 icv; |
132 | int i; | ||
136 | 133 | ||
137 | if (IS_ERR(tfm)) | 134 | if (IS_ERR(tfm)) |
138 | return -1; | 135 | return -1; |
@@ -140,9 +137,9 @@ int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | |||
140 | icv = cpu_to_le32(~crc32_le(~0, data, data_len)); | 137 | icv = cpu_to_le32(~crc32_le(~0, data, data_len)); |
141 | put_unaligned(icv, (__le32 *)(data + data_len)); | 138 | put_unaligned(icv, (__le32 *)(data + data_len)); |
142 | 139 | ||
143 | crypto_blkcipher_setkey(tfm, rc4key, klen); | 140 | crypto_cipher_setkey(tfm, rc4key, klen); |
144 | sg_init_one(&sg, data, data_len + WEP_ICV_LEN); | 141 | for (i = 0; i < data_len + WEP_ICV_LEN; i++) |
145 | crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); | 142 | crypto_cipher_encrypt_one(tfm, data + i, data + i); |
146 | 143 | ||
147 | return 0; | 144 | return 0; |
148 | } | 145 | } |
@@ -186,19 +183,18 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, | |||
186 | /* Perform WEP decryption using given key. data buffer includes encrypted | 183 | /* Perform WEP decryption using given key. data buffer includes encrypted |
187 | * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. | 184 | * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. |
188 | * Return 0 on success and -1 on ICV mismatch. */ | 185 | * Return 0 on success and -1 on ICV mismatch. */ |
189 | int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | 186 | int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, |
190 | size_t klen, u8 *data, size_t data_len) | 187 | size_t klen, u8 *data, size_t data_len) |
191 | { | 188 | { |
192 | struct blkcipher_desc desc = { .tfm = tfm }; | ||
193 | struct scatterlist sg; | ||
194 | __le32 crc; | 189 | __le32 crc; |
190 | int i; | ||
195 | 191 | ||
196 | if (IS_ERR(tfm)) | 192 | if (IS_ERR(tfm)) |
197 | return -1; | 193 | return -1; |
198 | 194 | ||
199 | crypto_blkcipher_setkey(tfm, rc4key, klen); | 195 | crypto_cipher_setkey(tfm, rc4key, klen); |
200 | sg_init_one(&sg, data, data_len + WEP_ICV_LEN); | 196 | for (i = 0; i < data_len + WEP_ICV_LEN; i++) |
201 | crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); | 197 | crypto_cipher_decrypt_one(tfm, data + i, data + i); |
202 | 198 | ||
203 | crc = cpu_to_le32(~crc32_le(~0, data, data_len)); | 199 | crc = cpu_to_le32(~crc32_le(~0, data, data_len)); |
204 | if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0) | 200 | if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0) |
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h index 58654ee33518..01e54840a628 100644 --- a/net/mac80211/wep.h +++ b/net/mac80211/wep.h | |||
@@ -18,12 +18,12 @@ | |||
18 | 18 | ||
19 | int ieee80211_wep_init(struct ieee80211_local *local); | 19 | int ieee80211_wep_init(struct ieee80211_local *local); |
20 | void ieee80211_wep_free(struct ieee80211_local *local); | 20 | void ieee80211_wep_free(struct ieee80211_local *local); |
21 | int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | 21 | int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, |
22 | size_t klen, u8 *data, size_t data_len); | 22 | size_t klen, u8 *data, size_t data_len); |
23 | int ieee80211_wep_encrypt(struct ieee80211_local *local, | 23 | int ieee80211_wep_encrypt(struct ieee80211_local *local, |
24 | struct sk_buff *skb, | 24 | struct sk_buff *skb, |
25 | const u8 *key, int keylen, int keyidx); | 25 | const u8 *key, int keylen, int keyidx); |
26 | int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | 26 | int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, |
27 | size_t klen, u8 *data, size_t data_len); | 27 | size_t klen, u8 *data, size_t data_len); |
28 | bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); | 28 | bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); |
29 | 29 | ||
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index aa5df8865ff7..16881fea4ce6 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -770,6 +770,15 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
770 | } | 770 | } |
771 | EXPORT_SYMBOL(cfg80211_new_sta); | 771 | EXPORT_SYMBOL(cfg80211_new_sta); |
772 | 772 | ||
773 | void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) | ||
774 | { | ||
775 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
776 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
777 | |||
778 | nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp); | ||
779 | } | ||
780 | EXPORT_SYMBOL(cfg80211_del_sta); | ||
781 | |||
773 | struct cfg80211_mgmt_registration { | 782 | struct cfg80211_mgmt_registration { |
774 | struct list_head list; | 783 | struct list_head list; |
775 | 784 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4ebce4284e9d..297d7ce4117b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2002,7 +2002,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
2002 | const u8 *mac_addr, struct station_info *sinfo) | 2002 | const u8 *mac_addr, struct station_info *sinfo) |
2003 | { | 2003 | { |
2004 | void *hdr; | 2004 | void *hdr; |
2005 | struct nlattr *sinfoattr; | 2005 | struct nlattr *sinfoattr, *bss_param; |
2006 | 2006 | ||
2007 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); | 2007 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); |
2008 | if (!hdr) | 2008 | if (!hdr) |
@@ -2062,6 +2062,25 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
2062 | if (sinfo->filled & STATION_INFO_TX_FAILED) | 2062 | if (sinfo->filled & STATION_INFO_TX_FAILED) |
2063 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, | 2063 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, |
2064 | sinfo->tx_failed); | 2064 | sinfo->tx_failed); |
2065 | if (sinfo->filled & STATION_INFO_BSS_PARAM) { | ||
2066 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); | ||
2067 | if (!bss_param) | ||
2068 | goto nla_put_failure; | ||
2069 | |||
2070 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) | ||
2071 | NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_CTS_PROT); | ||
2072 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) | ||
2073 | NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE); | ||
2074 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) | ||
2075 | NLA_PUT_FLAG(msg, | ||
2076 | NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME); | ||
2077 | NLA_PUT_U8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, | ||
2078 | sinfo->bss_param.dtim_period); | ||
2079 | NLA_PUT_U16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, | ||
2080 | sinfo->bss_param.beacon_interval); | ||
2081 | |||
2082 | nla_nest_end(msg, bss_param); | ||
2083 | } | ||
2065 | nla_nest_end(msg, sinfoattr); | 2084 | nla_nest_end(msg, sinfoattr); |
2066 | 2085 | ||
2067 | return genlmsg_end(msg, hdr); | 2086 | return genlmsg_end(msg, hdr); |
@@ -5966,6 +5985,40 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
5966 | nl80211_mlme_mcgrp.id, gfp); | 5985 | nl80211_mlme_mcgrp.id, gfp); |
5967 | } | 5986 | } |
5968 | 5987 | ||
5988 | void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | ||
5989 | struct net_device *dev, const u8 *mac_addr, | ||
5990 | gfp_t gfp) | ||
5991 | { | ||
5992 | struct sk_buff *msg; | ||
5993 | void *hdr; | ||
5994 | |||
5995 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
5996 | if (!msg) | ||
5997 | return; | ||
5998 | |||
5999 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION); | ||
6000 | if (!hdr) { | ||
6001 | nlmsg_free(msg); | ||
6002 | return; | ||
6003 | } | ||
6004 | |||
6005 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | ||
6006 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); | ||
6007 | |||
6008 | if (genlmsg_end(msg, hdr) < 0) { | ||
6009 | nlmsg_free(msg); | ||
6010 | return; | ||
6011 | } | ||
6012 | |||
6013 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
6014 | nl80211_mlme_mcgrp.id, gfp); | ||
6015 | return; | ||
6016 | |||
6017 | nla_put_failure: | ||
6018 | genlmsg_cancel(msg, hdr); | ||
6019 | nlmsg_free(msg); | ||
6020 | } | ||
6021 | |||
5969 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 6022 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
5970 | struct net_device *netdev, u32 nlpid, | 6023 | struct net_device *netdev, u32 nlpid, |
5971 | int freq, const u8 *buf, size_t len, gfp_t gfp) | 6024 | int freq, const u8 *buf, size_t len, gfp_t gfp) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index e3f7fa886966..dcac5cd6f017 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -79,6 +79,9 @@ void nl80211_send_remain_on_channel_cancel( | |||
79 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | 79 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, |
80 | struct net_device *dev, const u8 *mac_addr, | 80 | struct net_device *dev, const u8 *mac_addr, |
81 | struct station_info *sinfo, gfp_t gfp); | 81 | struct station_info *sinfo, gfp_t gfp); |
82 | void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | ||
83 | struct net_device *dev, const u8 *mac_addr, | ||
84 | gfp_t gfp); | ||
82 | 85 | ||
83 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 86 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
84 | struct net_device *netdev, u32 nlpid, int freq, | 87 | struct net_device *netdev, u32 nlpid, int freq, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index ab801a1097b2..58d69959ab28 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -106,6 +106,9 @@ struct reg_beacon { | |||
106 | static void reg_todo(struct work_struct *work); | 106 | static void reg_todo(struct work_struct *work); |
107 | static DECLARE_WORK(reg_work, reg_todo); | 107 | static DECLARE_WORK(reg_work, reg_todo); |
108 | 108 | ||
109 | static void reg_timeout_work(struct work_struct *work); | ||
110 | static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work); | ||
111 | |||
109 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | 112 | /* We keep a static world regulatory domain in case of the absence of CRDA */ |
110 | static const struct ieee80211_regdomain world_regdom = { | 113 | static const struct ieee80211_regdomain world_regdom = { |
111 | .n_reg_rules = 5, | 114 | .n_reg_rules = 5, |
@@ -1330,6 +1333,9 @@ static void reg_set_request_processed(void) | |||
1330 | need_more_processing = true; | 1333 | need_more_processing = true; |
1331 | spin_unlock(®_requests_lock); | 1334 | spin_unlock(®_requests_lock); |
1332 | 1335 | ||
1336 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) | ||
1337 | cancel_delayed_work_sync(®_timeout); | ||
1338 | |||
1333 | if (need_more_processing) | 1339 | if (need_more_processing) |
1334 | schedule_work(®_work); | 1340 | schedule_work(®_work); |
1335 | } | 1341 | } |
@@ -1440,8 +1446,17 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1440 | r = __regulatory_hint(wiphy, reg_request); | 1446 | r = __regulatory_hint(wiphy, reg_request); |
1441 | /* This is required so that the orig_* parameters are saved */ | 1447 | /* This is required so that the orig_* parameters are saved */ |
1442 | if (r == -EALREADY && wiphy && | 1448 | if (r == -EALREADY && wiphy && |
1443 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) | 1449 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { |
1444 | wiphy_update_regulatory(wiphy, initiator); | 1450 | wiphy_update_regulatory(wiphy, initiator); |
1451 | return; | ||
1452 | } | ||
1453 | |||
1454 | /* | ||
1455 | * We only time out user hints, given that they should be the only | ||
1456 | * source of bogus requests. | ||
1457 | */ | ||
1458 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER) | ||
1459 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | ||
1445 | } | 1460 | } |
1446 | 1461 | ||
1447 | /* | 1462 | /* |
@@ -1744,6 +1759,8 @@ static void restore_regulatory_settings(bool reset_user) | |||
1744 | { | 1759 | { |
1745 | char alpha2[2]; | 1760 | char alpha2[2]; |
1746 | struct reg_beacon *reg_beacon, *btmp; | 1761 | struct reg_beacon *reg_beacon, *btmp; |
1762 | struct regulatory_request *reg_request, *tmp; | ||
1763 | LIST_HEAD(tmp_reg_req_list); | ||
1747 | 1764 | ||
1748 | mutex_lock(&cfg80211_mutex); | 1765 | mutex_lock(&cfg80211_mutex); |
1749 | mutex_lock(®_mutex); | 1766 | mutex_lock(®_mutex); |
@@ -1751,6 +1768,25 @@ static void restore_regulatory_settings(bool reset_user) | |||
1751 | reset_regdomains(); | 1768 | reset_regdomains(); |
1752 | restore_alpha2(alpha2, reset_user); | 1769 | restore_alpha2(alpha2, reset_user); |
1753 | 1770 | ||
1771 | /* | ||
1772 | * If there's any pending requests we simply | ||
1773 | * stash them to a temporary pending queue and | ||
1774 | * add then after we've restored regulatory | ||
1775 | * settings. | ||
1776 | */ | ||
1777 | spin_lock(®_requests_lock); | ||
1778 | if (!list_empty(®_requests_list)) { | ||
1779 | list_for_each_entry_safe(reg_request, tmp, | ||
1780 | ®_requests_list, list) { | ||
1781 | if (reg_request->initiator != | ||
1782 | NL80211_REGDOM_SET_BY_USER) | ||
1783 | continue; | ||
1784 | list_del(®_request->list); | ||
1785 | list_add_tail(®_request->list, &tmp_reg_req_list); | ||
1786 | } | ||
1787 | } | ||
1788 | spin_unlock(®_requests_lock); | ||
1789 | |||
1754 | /* Clear beacon hints */ | 1790 | /* Clear beacon hints */ |
1755 | spin_lock_bh(®_pending_beacons_lock); | 1791 | spin_lock_bh(®_pending_beacons_lock); |
1756 | if (!list_empty(®_pending_beacons)) { | 1792 | if (!list_empty(®_pending_beacons)) { |
@@ -1785,8 +1821,31 @@ static void restore_regulatory_settings(bool reset_user) | |||
1785 | */ | 1821 | */ |
1786 | if (is_an_alpha2(alpha2)) | 1822 | if (is_an_alpha2(alpha2)) |
1787 | regulatory_hint_user(user_alpha2); | 1823 | regulatory_hint_user(user_alpha2); |
1788 | } | ||
1789 | 1824 | ||
1825 | if (list_empty(&tmp_reg_req_list)) | ||
1826 | return; | ||
1827 | |||
1828 | mutex_lock(&cfg80211_mutex); | ||
1829 | mutex_lock(®_mutex); | ||
1830 | |||
1831 | spin_lock(®_requests_lock); | ||
1832 | list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) { | ||
1833 | REG_DBG_PRINT("Adding request for country %c%c back " | ||
1834 | "into the queue\n", | ||
1835 | reg_request->alpha2[0], | ||
1836 | reg_request->alpha2[1]); | ||
1837 | list_del(®_request->list); | ||
1838 | list_add_tail(®_request->list, ®_requests_list); | ||
1839 | } | ||
1840 | spin_unlock(®_requests_lock); | ||
1841 | |||
1842 | mutex_unlock(®_mutex); | ||
1843 | mutex_unlock(&cfg80211_mutex); | ||
1844 | |||
1845 | REG_DBG_PRINT("Kicking the queue\n"); | ||
1846 | |||
1847 | schedule_work(®_work); | ||
1848 | } | ||
1790 | 1849 | ||
1791 | void regulatory_hint_disconnect(void) | 1850 | void regulatory_hint_disconnect(void) |
1792 | { | 1851 | { |
@@ -2125,6 +2184,13 @@ out: | |||
2125 | mutex_unlock(®_mutex); | 2184 | mutex_unlock(®_mutex); |
2126 | } | 2185 | } |
2127 | 2186 | ||
2187 | static void reg_timeout_work(struct work_struct *work) | ||
2188 | { | ||
2189 | REG_DBG_PRINT("Timeout while waiting for CRDA to reply, " | ||
2190 | "restoring regulatory settings"); | ||
2191 | restore_regulatory_settings(true); | ||
2192 | } | ||
2193 | |||
2128 | int __init regulatory_init(void) | 2194 | int __init regulatory_init(void) |
2129 | { | 2195 | { |
2130 | int err = 0; | 2196 | int err = 0; |
@@ -2178,6 +2244,7 @@ void /* __init_or_exit */ regulatory_exit(void) | |||
2178 | struct reg_beacon *reg_beacon, *btmp; | 2244 | struct reg_beacon *reg_beacon, *btmp; |
2179 | 2245 | ||
2180 | cancel_work_sync(®_work); | 2246 | cancel_work_sync(®_work); |
2247 | cancel_delayed_work_sync(®_timeout); | ||
2181 | 2248 | ||
2182 | mutex_lock(&cfg80211_mutex); | 2249 | mutex_lock(&cfg80211_mutex); |
2183 | mutex_lock(®_mutex); | 2250 | mutex_lock(®_mutex); |