diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-11-11 16:30:48 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-11-11 16:30:48 -0500 |
commit | 6164c202289f4718acf00c0dbe5f130b07330ab2 (patch) | |
tree | 8c0e1f685b811030080344eba161314939e49f78 /net | |
parent | bf515fb11ab539c76d04f0e3c5216ed41f41d81f (diff) | |
parent | 56b2c3eea398c772dd895dc62c18cbdd1ba127b1 (diff) |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Diffstat (limited to 'net')
-rw-r--r-- | net/6lowpan/iphc.c | 41 | ||||
-rw-r--r-- | net/bluetooth/6lowpan.c | 15 | ||||
-rw-r--r-- | net/bluetooth/Kconfig | 20 | ||||
-rw-r--r-- | net/bluetooth/bnep/Kconfig | 2 | ||||
-rw-r--r-- | net/bluetooth/cmtp/Kconfig | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 72 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 61 | ||||
-rw-r--r-- | net/bluetooth/hidp/Kconfig | 2 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 56 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/Kconfig | 2 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 6 | ||||
-rw-r--r-- | net/ieee802154/6lowpan_rtnl.c | 38 | ||||
-rw-r--r-- | net/ieee802154/core.c | 64 | ||||
-rw-r--r-- | net/ieee802154/core.h | 29 | ||||
-rw-r--r-- | net/ieee802154/nl-mac.c | 203 | ||||
-rw-r--r-- | net/ieee802154/nl-phy.c | 23 | ||||
-rw-r--r-- | net/ieee802154/rdev-ops.h | 23 | ||||
-rw-r--r-- | net/ieee802154/sysfs.c | 16 | ||||
-rw-r--r-- | net/mac802154/Makefile | 2 | ||||
-rw-r--r-- | net/mac802154/cfg.c | 47 | ||||
-rw-r--r-- | net/mac802154/cfg.h | 9 | ||||
-rw-r--r-- | net/mac802154/ieee802154_i.h | 17 | ||||
-rw-r--r-- | net/mac802154/iface.c | 195 | ||||
-rw-r--r-- | net/mac802154/mac_cmd.c | 42 | ||||
-rw-r--r-- | net/mac802154/main.c | 102 | ||||
-rw-r--r-- | net/mac802154/mib.c | 71 | ||||
-rw-r--r-- | net/mac802154/rx.c | 4 |
27 files changed, 536 insertions, 628 deletions
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 73a7065f0c6b..aced97db62f0 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c | |||
@@ -319,7 +319,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
319 | if (iphc1 & LOWPAN_IPHC_CID) { | 319 | if (iphc1 & LOWPAN_IPHC_CID) { |
320 | pr_debug("CID flag is set, increase header with one\n"); | 320 | pr_debug("CID flag is set, increase header with one\n"); |
321 | if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context))) | 321 | if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context))) |
322 | goto drop; | 322 | return -EINVAL; |
323 | } | 323 | } |
324 | 324 | ||
325 | hdr.version = 6; | 325 | hdr.version = 6; |
@@ -331,7 +331,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
331 | */ | 331 | */ |
332 | case 0: /* 00b */ | 332 | case 0: /* 00b */ |
333 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) | 333 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
334 | goto drop; | 334 | return -EINVAL; |
335 | 335 | ||
336 | memcpy(&hdr.flow_lbl, &skb->data[0], 3); | 336 | memcpy(&hdr.flow_lbl, &skb->data[0], 3); |
337 | skb_pull(skb, 3); | 337 | skb_pull(skb, 3); |
@@ -344,7 +344,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
344 | */ | 344 | */ |
345 | case 2: /* 10b */ | 345 | case 2: /* 10b */ |
346 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) | 346 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
347 | goto drop; | 347 | return -EINVAL; |
348 | 348 | ||
349 | hdr.priority = ((tmp >> 2) & 0x0f); | 349 | hdr.priority = ((tmp >> 2) & 0x0f); |
350 | hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); | 350 | hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); |
@@ -354,7 +354,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
354 | */ | 354 | */ |
355 | case 1: /* 01b */ | 355 | case 1: /* 01b */ |
356 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) | 356 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
357 | goto drop; | 357 | return -EINVAL; |
358 | 358 | ||
359 | hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); | 359 | hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); |
360 | memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); | 360 | memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); |
@@ -371,7 +371,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
371 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | 371 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { |
372 | /* Next header is carried inline */ | 372 | /* Next header is carried inline */ |
373 | if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr))) | 373 | if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr))) |
374 | goto drop; | 374 | return -EINVAL; |
375 | 375 | ||
376 | pr_debug("NH flag is set, next header carried inline: %02x\n", | 376 | pr_debug("NH flag is set, next header carried inline: %02x\n", |
377 | hdr.nexthdr); | 377 | hdr.nexthdr); |
@@ -383,7 +383,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
383 | } else { | 383 | } else { |
384 | if (lowpan_fetch_skb(skb, &hdr.hop_limit, | 384 | if (lowpan_fetch_skb(skb, &hdr.hop_limit, |
385 | sizeof(hdr.hop_limit))) | 385 | sizeof(hdr.hop_limit))) |
386 | goto drop; | 386 | return -EINVAL; |
387 | } | 387 | } |
388 | 388 | ||
389 | /* Extract SAM to the tmp variable */ | 389 | /* Extract SAM to the tmp variable */ |
@@ -402,7 +402,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
402 | 402 | ||
403 | /* Check on error of previous branch */ | 403 | /* Check on error of previous branch */ |
404 | if (err) | 404 | if (err) |
405 | goto drop; | 405 | return -EINVAL; |
406 | 406 | ||
407 | /* Extract DAM to the tmp variable */ | 407 | /* Extract DAM to the tmp variable */ |
408 | tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; | 408 | tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; |
@@ -417,7 +417,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
417 | tmp); | 417 | tmp); |
418 | 418 | ||
419 | if (err) | 419 | if (err) |
420 | goto drop; | 420 | return -EINVAL; |
421 | } | 421 | } |
422 | } else { | 422 | } else { |
423 | err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, | 423 | err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, |
@@ -425,7 +425,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
425 | pr_debug("dest: stateless compression mode %d dest %pI6c\n", | 425 | pr_debug("dest: stateless compression mode %d dest %pI6c\n", |
426 | tmp, &hdr.daddr); | 426 | tmp, &hdr.daddr); |
427 | if (err) | 427 | if (err) |
428 | goto drop; | 428 | return -EINVAL; |
429 | } | 429 | } |
430 | 430 | ||
431 | /* UDP data uncompression */ | 431 | /* UDP data uncompression */ |
@@ -434,16 +434,14 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
434 | const int needed = sizeof(struct udphdr) + sizeof(hdr); | 434 | const int needed = sizeof(struct udphdr) + sizeof(hdr); |
435 | 435 | ||
436 | if (uncompress_udp_header(skb, &uh)) | 436 | if (uncompress_udp_header(skb, &uh)) |
437 | goto drop; | 437 | return -EINVAL; |
438 | 438 | ||
439 | /* replace the compressed UDP head by the uncompressed UDP | 439 | /* replace the compressed UDP head by the uncompressed UDP |
440 | * header | 440 | * header |
441 | */ | 441 | */ |
442 | err = skb_cow(skb, needed); | 442 | err = skb_cow(skb, needed); |
443 | if (unlikely(err)) { | 443 | if (unlikely(err)) |
444 | kfree_skb(skb); | ||
445 | return err; | 444 | return err; |
446 | } | ||
447 | 445 | ||
448 | skb_push(skb, sizeof(struct udphdr)); | 446 | skb_push(skb, sizeof(struct udphdr)); |
449 | skb_reset_transport_header(skb); | 447 | skb_reset_transport_header(skb); |
@@ -455,10 +453,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
455 | hdr.nexthdr = UIP_PROTO_UDP; | 453 | hdr.nexthdr = UIP_PROTO_UDP; |
456 | } else { | 454 | } else { |
457 | err = skb_cow(skb, sizeof(hdr)); | 455 | err = skb_cow(skb, sizeof(hdr)); |
458 | if (unlikely(err)) { | 456 | if (unlikely(err)) |
459 | kfree_skb(skb); | ||
460 | return err; | 457 | return err; |
461 | } | ||
462 | } | 458 | } |
463 | 459 | ||
464 | hdr.payload_len = htons(skb->len); | 460 | hdr.payload_len = htons(skb->len); |
@@ -478,9 +474,6 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, | |||
478 | raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); | 474 | raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); |
479 | 475 | ||
480 | return 0; | 476 | return 0; |
481 | drop: | ||
482 | kfree_skb(skb); | ||
483 | return -EINVAL; | ||
484 | } | 477 | } |
485 | EXPORT_SYMBOL_GPL(lowpan_header_decompress); | 478 | EXPORT_SYMBOL_GPL(lowpan_header_decompress); |
486 | 479 | ||
@@ -512,9 +505,17 @@ static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift, | |||
512 | 505 | ||
513 | static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb) | 506 | static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb) |
514 | { | 507 | { |
515 | struct udphdr *uh = udp_hdr(skb); | 508 | struct udphdr *uh; |
516 | u8 tmp; | 509 | u8 tmp; |
517 | 510 | ||
511 | /* In the case of RAW sockets the transport header is not set by | ||
512 | * the ip6 stack so we must set it ourselves | ||
513 | */ | ||
514 | if (skb->transport_header == skb->network_header) | ||
515 | skb_set_transport_header(skb, sizeof(struct ipv6hdr)); | ||
516 | |||
517 | uh = udp_hdr(skb); | ||
518 | |||
518 | if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) == | 519 | if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) == |
519 | LOWPAN_NHC_UDP_4BIT_PORT) && | 520 | LOWPAN_NHC_UDP_4BIT_PORT) && |
520 | ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) == | 521 | ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) == |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index eef298d17452..dc23c55f1ab6 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
@@ -294,20 +294,20 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev, | |||
294 | peer = __peer_lookup_chan(dev, chan); | 294 | peer = __peer_lookup_chan(dev, chan); |
295 | rcu_read_unlock(); | 295 | rcu_read_unlock(); |
296 | if (!peer) | 296 | if (!peer) |
297 | goto drop; | 297 | return -EINVAL; |
298 | 298 | ||
299 | saddr = peer->eui64_addr; | 299 | saddr = peer->eui64_addr; |
300 | daddr = dev->netdev->dev_addr; | 300 | daddr = dev->netdev->dev_addr; |
301 | 301 | ||
302 | /* at least two bytes will be used for the encoding */ | 302 | /* at least two bytes will be used for the encoding */ |
303 | if (skb->len < 2) | 303 | if (skb->len < 2) |
304 | goto drop; | 304 | return -EINVAL; |
305 | 305 | ||
306 | if (lowpan_fetch_skb_u8(skb, &iphc0)) | 306 | if (lowpan_fetch_skb_u8(skb, &iphc0)) |
307 | goto drop; | 307 | return -EINVAL; |
308 | 308 | ||
309 | if (lowpan_fetch_skb_u8(skb, &iphc1)) | 309 | if (lowpan_fetch_skb_u8(skb, &iphc1)) |
310 | goto drop; | 310 | return -EINVAL; |
311 | 311 | ||
312 | return lowpan_header_decompress(skb, netdev, | 312 | return lowpan_header_decompress(skb, netdev, |
313 | saddr, IEEE802154_ADDR_LONG, | 313 | saddr, IEEE802154_ADDR_LONG, |
@@ -315,9 +315,6 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev, | |||
315 | IEEE802154_ADDR_LONG, EUI64_ADDR_LEN, | 315 | IEEE802154_ADDR_LONG, EUI64_ADDR_LEN, |
316 | iphc0, iphc1); | 316 | iphc0, iphc1); |
317 | 317 | ||
318 | drop: | ||
319 | kfree_skb(skb); | ||
320 | return -EINVAL; | ||
321 | } | 318 | } |
322 | 319 | ||
323 | static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | 320 | static int recv_pkt(struct sk_buff *skb, struct net_device *dev, |
@@ -370,8 +367,10 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
370 | goto drop; | 367 | goto drop; |
371 | 368 | ||
372 | ret = iphc_decompress(local_skb, dev, chan); | 369 | ret = iphc_decompress(local_skb, dev, chan); |
373 | if (ret < 0) | 370 | if (ret < 0) { |
371 | kfree_skb(local_skb); | ||
374 | goto drop; | 372 | goto drop; |
373 | } | ||
375 | 374 | ||
376 | local_skb->protocol = htons(ETH_P_IPV6); | 375 | local_skb->protocol = htons(ETH_P_IPV6); |
377 | local_skb->pkt_type = PACKET_HOST; | 376 | local_skb->pkt_type = PACKET_HOST; |
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 600fb29288f4..5e97a8ff850b 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -39,11 +39,10 @@ menuconfig BT | |||
39 | to Bluetooth kernel modules are provided in the BlueZ packages. For | 39 | to Bluetooth kernel modules are provided in the BlueZ packages. For |
40 | more information, see <http://www.bluez.org/>. | 40 | more information, see <http://www.bluez.org/>. |
41 | 41 | ||
42 | config BT_6LOWPAN | 42 | config BT_BREDR |
43 | tristate "Bluetooth 6LoWPAN support" | 43 | bool "Bluetooth Classic (BR/EDR) features" |
44 | depends on BT && 6LOWPAN | 44 | depends on BT |
45 | help | 45 | default y |
46 | IPv6 compression over Bluetooth Low Energy. | ||
47 | 46 | ||
48 | source "net/bluetooth/rfcomm/Kconfig" | 47 | source "net/bluetooth/rfcomm/Kconfig" |
49 | 48 | ||
@@ -53,4 +52,15 @@ source "net/bluetooth/cmtp/Kconfig" | |||
53 | 52 | ||
54 | source "net/bluetooth/hidp/Kconfig" | 53 | source "net/bluetooth/hidp/Kconfig" |
55 | 54 | ||
55 | config BT_LE | ||
56 | bool "Bluetooth Low Energy (LE) features" | ||
57 | depends on BT | ||
58 | default y | ||
59 | |||
60 | config BT_6LOWPAN | ||
61 | tristate "Bluetooth 6LoWPAN support" | ||
62 | depends on BT_LE && 6LOWPAN | ||
63 | help | ||
64 | IPv6 compression over Bluetooth Low Energy. | ||
65 | |||
56 | source "drivers/bluetooth/Kconfig" | 66 | source "drivers/bluetooth/Kconfig" |
diff --git a/net/bluetooth/bnep/Kconfig b/net/bluetooth/bnep/Kconfig index 71791fc9f6b1..9b70317c49dc 100644 --- a/net/bluetooth/bnep/Kconfig +++ b/net/bluetooth/bnep/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config BT_BNEP | 1 | config BT_BNEP |
2 | tristate "BNEP protocol support" | 2 | tristate "BNEP protocol support" |
3 | depends on BT | 3 | depends on BT_BREDR |
4 | select CRC32 | 4 | select CRC32 |
5 | help | 5 | help |
6 | BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet | 6 | BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet |
diff --git a/net/bluetooth/cmtp/Kconfig b/net/bluetooth/cmtp/Kconfig index 94cbf42ce155..939da0fbdd88 100644 --- a/net/bluetooth/cmtp/Kconfig +++ b/net/bluetooth/cmtp/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config BT_CMTP | 1 | config BT_CMTP |
2 | tristate "CMTP protocol support" | 2 | tristate "CMTP protocol support" |
3 | depends on BT && ISDN_CAPI | 3 | depends on BT_BREDR && ISDN_CAPI |
4 | help | 4 | help |
5 | CMTP (CAPI Message Transport Protocol) is a transport layer | 5 | CMTP (CAPI Message Transport Protocol) is a transport layer |
6 | for CAPI messages. CMTP is required for the Bluetooth Common | 6 | for CAPI messages. CMTP is required for the Bluetooth Common |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 91995f8ab0a0..6c162c8809cf 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -200,31 +200,6 @@ static const struct file_operations blacklist_fops = { | |||
200 | .release = single_release, | 200 | .release = single_release, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | static int whitelist_show(struct seq_file *f, void *p) | ||
204 | { | ||
205 | struct hci_dev *hdev = f->private; | ||
206 | struct bdaddr_list *b; | ||
207 | |||
208 | hci_dev_lock(hdev); | ||
209 | list_for_each_entry(b, &hdev->whitelist, list) | ||
210 | seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type); | ||
211 | hci_dev_unlock(hdev); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int whitelist_open(struct inode *inode, struct file *file) | ||
217 | { | ||
218 | return single_open(file, whitelist_show, inode->i_private); | ||
219 | } | ||
220 | |||
221 | static const struct file_operations whitelist_fops = { | ||
222 | .open = whitelist_open, | ||
223 | .read = seq_read, | ||
224 | .llseek = seq_lseek, | ||
225 | .release = single_release, | ||
226 | }; | ||
227 | |||
228 | static int uuids_show(struct seq_file *f, void *p) | 203 | static int uuids_show(struct seq_file *f, void *p) |
229 | { | 204 | { |
230 | struct hci_dev *hdev = f->private; | 205 | struct hci_dev *hdev = f->private; |
@@ -1030,10 +1005,13 @@ static int device_list_show(struct seq_file *f, void *ptr) | |||
1030 | { | 1005 | { |
1031 | struct hci_dev *hdev = f->private; | 1006 | struct hci_dev *hdev = f->private; |
1032 | struct hci_conn_params *p; | 1007 | struct hci_conn_params *p; |
1008 | struct bdaddr_list *b; | ||
1033 | 1009 | ||
1034 | hci_dev_lock(hdev); | 1010 | hci_dev_lock(hdev); |
1011 | list_for_each_entry(b, &hdev->whitelist, list) | ||
1012 | seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type); | ||
1035 | list_for_each_entry(p, &hdev->le_conn_params, list) { | 1013 | list_for_each_entry(p, &hdev->le_conn_params, list) { |
1036 | seq_printf(f, "%pMR %u %u\n", &p->addr, p->addr_type, | 1014 | seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type, |
1037 | p->auto_connect); | 1015 | p->auto_connect); |
1038 | } | 1016 | } |
1039 | hci_dev_unlock(hdev); | 1017 | hci_dev_unlock(hdev); |
@@ -1147,13 +1125,15 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, | |||
1147 | 1125 | ||
1148 | hdev->req_status = HCI_REQ_PEND; | 1126 | hdev->req_status = HCI_REQ_PEND; |
1149 | 1127 | ||
1150 | err = hci_req_run(&req, hci_req_sync_complete); | ||
1151 | if (err < 0) | ||
1152 | return ERR_PTR(err); | ||
1153 | |||
1154 | add_wait_queue(&hdev->req_wait_q, &wait); | 1128 | add_wait_queue(&hdev->req_wait_q, &wait); |
1155 | set_current_state(TASK_INTERRUPTIBLE); | 1129 | set_current_state(TASK_INTERRUPTIBLE); |
1156 | 1130 | ||
1131 | err = hci_req_run(&req, hci_req_sync_complete); | ||
1132 | if (err < 0) { | ||
1133 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
1134 | return ERR_PTR(err); | ||
1135 | } | ||
1136 | |||
1157 | schedule_timeout(timeout); | 1137 | schedule_timeout(timeout); |
1158 | 1138 | ||
1159 | remove_wait_queue(&hdev->req_wait_q, &wait); | 1139 | remove_wait_queue(&hdev->req_wait_q, &wait); |
@@ -1211,10 +1191,15 @@ static int __hci_req_sync(struct hci_dev *hdev, | |||
1211 | 1191 | ||
1212 | func(&req, opt); | 1192 | func(&req, opt); |
1213 | 1193 | ||
1194 | add_wait_queue(&hdev->req_wait_q, &wait); | ||
1195 | set_current_state(TASK_INTERRUPTIBLE); | ||
1196 | |||
1214 | err = hci_req_run(&req, hci_req_sync_complete); | 1197 | err = hci_req_run(&req, hci_req_sync_complete); |
1215 | if (err < 0) { | 1198 | if (err < 0) { |
1216 | hdev->req_status = 0; | 1199 | hdev->req_status = 0; |
1217 | 1200 | ||
1201 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
1202 | |||
1218 | /* ENODATA means the HCI request command queue is empty. | 1203 | /* ENODATA means the HCI request command queue is empty. |
1219 | * This can happen when a request with conditionals doesn't | 1204 | * This can happen when a request with conditionals doesn't |
1220 | * trigger any commands to be sent. This is normal behavior | 1205 | * trigger any commands to be sent. This is normal behavior |
@@ -1226,9 +1211,6 @@ static int __hci_req_sync(struct hci_dev *hdev, | |||
1226 | return err; | 1211 | return err; |
1227 | } | 1212 | } |
1228 | 1213 | ||
1229 | add_wait_queue(&hdev->req_wait_q, &wait); | ||
1230 | set_current_state(TASK_INTERRUPTIBLE); | ||
1231 | |||
1232 | schedule_timeout(timeout); | 1214 | schedule_timeout(timeout); |
1233 | 1215 | ||
1234 | remove_wait_queue(&hdev->req_wait_q, &wait); | 1216 | remove_wait_queue(&hdev->req_wait_q, &wait); |
@@ -1811,10 +1793,10 @@ static int __hci_init(struct hci_dev *hdev) | |||
1811 | &hdev->manufacturer); | 1793 | &hdev->manufacturer); |
1812 | debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver); | 1794 | debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver); |
1813 | debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); | 1795 | debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); |
1796 | debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, | ||
1797 | &device_list_fops); | ||
1814 | debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, | 1798 | debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, |
1815 | &blacklist_fops); | 1799 | &blacklist_fops); |
1816 | debugfs_create_file("whitelist", 0444, hdev->debugfs, hdev, | ||
1817 | &whitelist_fops); | ||
1818 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); | 1800 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); |
1819 | 1801 | ||
1820 | debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev, | 1802 | debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev, |
@@ -1893,8 +1875,6 @@ static int __hci_init(struct hci_dev *hdev) | |||
1893 | hdev, &adv_min_interval_fops); | 1875 | hdev, &adv_min_interval_fops); |
1894 | debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, | 1876 | debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, |
1895 | hdev, &adv_max_interval_fops); | 1877 | hdev, &adv_max_interval_fops); |
1896 | debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, | ||
1897 | &device_list_fops); | ||
1898 | debugfs_create_u16("discov_interleaved_timeout", 0644, | 1878 | debugfs_create_u16("discov_interleaved_timeout", 0644, |
1899 | hdev->debugfs, | 1879 | hdev->debugfs, |
1900 | &hdev->discov_interleaved_timeout); | 1880 | &hdev->discov_interleaved_timeout); |
@@ -4244,6 +4224,24 @@ int hci_resume_dev(struct hci_dev *hdev) | |||
4244 | } | 4224 | } |
4245 | EXPORT_SYMBOL(hci_resume_dev); | 4225 | EXPORT_SYMBOL(hci_resume_dev); |
4246 | 4226 | ||
4227 | /* Reset HCI device */ | ||
4228 | int hci_reset_dev(struct hci_dev *hdev) | ||
4229 | { | ||
4230 | const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 }; | ||
4231 | struct sk_buff *skb; | ||
4232 | |||
4233 | skb = bt_skb_alloc(3, GFP_ATOMIC); | ||
4234 | if (!skb) | ||
4235 | return -ENOMEM; | ||
4236 | |||
4237 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; | ||
4238 | memcpy(skb_put(skb, 3), hw_err, 3); | ||
4239 | |||
4240 | /* Send Hardware Error to upper stack */ | ||
4241 | return hci_recv_frame(hdev, skb); | ||
4242 | } | ||
4243 | EXPORT_SYMBOL(hci_reset_dev); | ||
4244 | |||
4247 | /* Receive frame from HCI drivers */ | 4245 | /* Receive frame from HCI drivers */ |
4248 | int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) | 4246 | int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) |
4249 | { | 4247 | { |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index aa152140c3e2..5e7be804c709 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -189,6 +189,9 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
189 | 189 | ||
190 | clear_bit(HCI_RESET, &hdev->flags); | 190 | clear_bit(HCI_RESET, &hdev->flags); |
191 | 191 | ||
192 | if (status) | ||
193 | return; | ||
194 | |||
192 | /* Reset all non-persistent flags */ | 195 | /* Reset all non-persistent flags */ |
193 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; | 196 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; |
194 | 197 | ||
@@ -1944,6 +1947,29 @@ unlock: | |||
1944 | hci_dev_unlock(hdev); | 1947 | hci_dev_unlock(hdev); |
1945 | } | 1948 | } |
1946 | 1949 | ||
1950 | static void hci_cs_switch_role(struct hci_dev *hdev, u8 status) | ||
1951 | { | ||
1952 | struct hci_cp_switch_role *cp; | ||
1953 | struct hci_conn *conn; | ||
1954 | |||
1955 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1956 | |||
1957 | if (!status) | ||
1958 | return; | ||
1959 | |||
1960 | cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE); | ||
1961 | if (!cp) | ||
1962 | return; | ||
1963 | |||
1964 | hci_dev_lock(hdev); | ||
1965 | |||
1966 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | ||
1967 | if (conn) | ||
1968 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); | ||
1969 | |||
1970 | hci_dev_unlock(hdev); | ||
1971 | } | ||
1972 | |||
1947 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1973 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1948 | { | 1974 | { |
1949 | __u8 status = *((__u8 *) skb->data); | 1975 | __u8 status = *((__u8 *) skb->data); |
@@ -2847,6 +2873,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2847 | hci_cs_create_conn(hdev, ev->status); | 2873 | hci_cs_create_conn(hdev, ev->status); |
2848 | break; | 2874 | break; |
2849 | 2875 | ||
2876 | case HCI_OP_DISCONNECT: | ||
2877 | hci_cs_disconnect(hdev, ev->status); | ||
2878 | break; | ||
2879 | |||
2850 | case HCI_OP_ADD_SCO: | 2880 | case HCI_OP_ADD_SCO: |
2851 | hci_cs_add_sco(hdev, ev->status); | 2881 | hci_cs_add_sco(hdev, ev->status); |
2852 | break; | 2882 | break; |
@@ -2875,24 +2905,24 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2875 | hci_cs_setup_sync_conn(hdev, ev->status); | 2905 | hci_cs_setup_sync_conn(hdev, ev->status); |
2876 | break; | 2906 | break; |
2877 | 2907 | ||
2878 | case HCI_OP_SNIFF_MODE: | 2908 | case HCI_OP_CREATE_PHY_LINK: |
2879 | hci_cs_sniff_mode(hdev, ev->status); | 2909 | hci_cs_create_phylink(hdev, ev->status); |
2880 | break; | 2910 | break; |
2881 | 2911 | ||
2882 | case HCI_OP_EXIT_SNIFF_MODE: | 2912 | case HCI_OP_ACCEPT_PHY_LINK: |
2883 | hci_cs_exit_sniff_mode(hdev, ev->status); | 2913 | hci_cs_accept_phylink(hdev, ev->status); |
2884 | break; | 2914 | break; |
2885 | 2915 | ||
2886 | case HCI_OP_DISCONNECT: | 2916 | case HCI_OP_SNIFF_MODE: |
2887 | hci_cs_disconnect(hdev, ev->status); | 2917 | hci_cs_sniff_mode(hdev, ev->status); |
2888 | break; | 2918 | break; |
2889 | 2919 | ||
2890 | case HCI_OP_CREATE_PHY_LINK: | 2920 | case HCI_OP_EXIT_SNIFF_MODE: |
2891 | hci_cs_create_phylink(hdev, ev->status); | 2921 | hci_cs_exit_sniff_mode(hdev, ev->status); |
2892 | break; | 2922 | break; |
2893 | 2923 | ||
2894 | case HCI_OP_ACCEPT_PHY_LINK: | 2924 | case HCI_OP_SWITCH_ROLE: |
2895 | hci_cs_accept_phylink(hdev, ev->status); | 2925 | hci_cs_switch_role(hdev, ev->status); |
2896 | break; | 2926 | break; |
2897 | 2927 | ||
2898 | case HCI_OP_LE_CREATE_CONN: | 2928 | case HCI_OP_LE_CREATE_CONN: |
@@ -2922,6 +2952,13 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2922 | } | 2952 | } |
2923 | } | 2953 | } |
2924 | 2954 | ||
2955 | static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
2956 | { | ||
2957 | struct hci_ev_hardware_error *ev = (void *) skb->data; | ||
2958 | |||
2959 | BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code); | ||
2960 | } | ||
2961 | |||
2925 | static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2962 | static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2926 | { | 2963 | { |
2927 | struct hci_ev_role_change *ev = (void *) skb->data; | 2964 | struct hci_ev_role_change *ev = (void *) skb->data; |
@@ -4743,6 +4780,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
4743 | hci_cmd_status_evt(hdev, skb); | 4780 | hci_cmd_status_evt(hdev, skb); |
4744 | break; | 4781 | break; |
4745 | 4782 | ||
4783 | case HCI_EV_HARDWARE_ERROR: | ||
4784 | hci_hardware_error_evt(hdev, skb); | ||
4785 | break; | ||
4786 | |||
4746 | case HCI_EV_ROLE_CHANGE: | 4787 | case HCI_EV_ROLE_CHANGE: |
4747 | hci_role_change_evt(hdev, skb); | 4788 | hci_role_change_evt(hdev, skb); |
4748 | break; | 4789 | break; |
diff --git a/net/bluetooth/hidp/Kconfig b/net/bluetooth/hidp/Kconfig index 9332bc7aa851..bc8610b24077 100644 --- a/net/bluetooth/hidp/Kconfig +++ b/net/bluetooth/hidp/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config BT_HIDP | 1 | config BT_HIDP |
2 | tristate "HIDP protocol support" | 2 | tristate "HIDP protocol support" |
3 | depends on BT && INPUT | 3 | depends on BT_BREDR && INPUT |
4 | select HID | 4 | select HID |
5 | help | 5 | help |
6 | HIDP (Human Interface Device Protocol) is a transport layer | 6 | HIDP (Human Interface Device Protocol) is a transport layer |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9c4daf715cf8..ce0272c6f71f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -3727,20 +3727,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
3727 | hci_dev_lock(hdev); | 3727 | hci_dev_lock(hdev); |
3728 | 3728 | ||
3729 | if (!hdev_is_powered(hdev)) { | 3729 | if (!hdev_is_powered(hdev)) { |
3730 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3730 | err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
3731 | MGMT_STATUS_NOT_POWERED); | 3731 | MGMT_STATUS_NOT_POWERED, |
3732 | &cp->type, sizeof(cp->type)); | ||
3732 | goto failed; | 3733 | goto failed; |
3733 | } | 3734 | } |
3734 | 3735 | ||
3735 | if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) { | 3736 | if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) { |
3736 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3737 | err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
3737 | MGMT_STATUS_BUSY); | 3738 | MGMT_STATUS_BUSY, &cp->type, |
3739 | sizeof(cp->type)); | ||
3738 | goto failed; | 3740 | goto failed; |
3739 | } | 3741 | } |
3740 | 3742 | ||
3741 | if (hdev->discovery.state != DISCOVERY_STOPPED) { | 3743 | if (hdev->discovery.state != DISCOVERY_STOPPED) { |
3742 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3744 | err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
3743 | MGMT_STATUS_BUSY); | 3745 | MGMT_STATUS_BUSY, &cp->type, |
3746 | sizeof(cp->type)); | ||
3744 | goto failed; | 3747 | goto failed; |
3745 | } | 3748 | } |
3746 | 3749 | ||
@@ -3758,15 +3761,18 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
3758 | case DISCOV_TYPE_BREDR: | 3761 | case DISCOV_TYPE_BREDR: |
3759 | status = mgmt_bredr_support(hdev); | 3762 | status = mgmt_bredr_support(hdev); |
3760 | if (status) { | 3763 | if (status) { |
3761 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3764 | err = cmd_complete(sk, hdev->id, |
3762 | status); | 3765 | MGMT_OP_START_DISCOVERY, status, |
3766 | &cp->type, sizeof(cp->type)); | ||
3763 | mgmt_pending_remove(cmd); | 3767 | mgmt_pending_remove(cmd); |
3764 | goto failed; | 3768 | goto failed; |
3765 | } | 3769 | } |
3766 | 3770 | ||
3767 | if (test_bit(HCI_INQUIRY, &hdev->flags)) { | 3771 | if (test_bit(HCI_INQUIRY, &hdev->flags)) { |
3768 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3772 | err = cmd_complete(sk, hdev->id, |
3769 | MGMT_STATUS_BUSY); | 3773 | MGMT_OP_START_DISCOVERY, |
3774 | MGMT_STATUS_BUSY, &cp->type, | ||
3775 | sizeof(cp->type)); | ||
3770 | mgmt_pending_remove(cmd); | 3776 | mgmt_pending_remove(cmd); |
3771 | goto failed; | 3777 | goto failed; |
3772 | } | 3778 | } |
@@ -3783,16 +3789,19 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
3783 | case DISCOV_TYPE_INTERLEAVED: | 3789 | case DISCOV_TYPE_INTERLEAVED: |
3784 | status = mgmt_le_support(hdev); | 3790 | status = mgmt_le_support(hdev); |
3785 | if (status) { | 3791 | if (status) { |
3786 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3792 | err = cmd_complete(sk, hdev->id, |
3787 | status); | 3793 | MGMT_OP_START_DISCOVERY, status, |
3794 | &cp->type, sizeof(cp->type)); | ||
3788 | mgmt_pending_remove(cmd); | 3795 | mgmt_pending_remove(cmd); |
3789 | goto failed; | 3796 | goto failed; |
3790 | } | 3797 | } |
3791 | 3798 | ||
3792 | if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && | 3799 | if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && |
3793 | !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | 3800 | !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { |
3794 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3801 | err = cmd_complete(sk, hdev->id, |
3795 | MGMT_STATUS_NOT_SUPPORTED); | 3802 | MGMT_OP_START_DISCOVERY, |
3803 | MGMT_STATUS_NOT_SUPPORTED, | ||
3804 | &cp->type, sizeof(cp->type)); | ||
3796 | mgmt_pending_remove(cmd); | 3805 | mgmt_pending_remove(cmd); |
3797 | goto failed; | 3806 | goto failed; |
3798 | } | 3807 | } |
@@ -3804,9 +3813,11 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
3804 | */ | 3813 | */ |
3805 | if (hci_conn_hash_lookup_state(hdev, LE_LINK, | 3814 | if (hci_conn_hash_lookup_state(hdev, LE_LINK, |
3806 | BT_CONNECT)) { | 3815 | BT_CONNECT)) { |
3807 | err = cmd_status(sk, hdev->id, | 3816 | err = cmd_complete(sk, hdev->id, |
3808 | MGMT_OP_START_DISCOVERY, | 3817 | MGMT_OP_START_DISCOVERY, |
3809 | MGMT_STATUS_REJECTED); | 3818 | MGMT_STATUS_REJECTED, |
3819 | &cp->type, | ||
3820 | sizeof(cp->type)); | ||
3810 | mgmt_pending_remove(cmd); | 3821 | mgmt_pending_remove(cmd); |
3811 | goto failed; | 3822 | goto failed; |
3812 | } | 3823 | } |
@@ -3829,8 +3840,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
3829 | */ | 3840 | */ |
3830 | err = hci_update_random_address(&req, true, &own_addr_type); | 3841 | err = hci_update_random_address(&req, true, &own_addr_type); |
3831 | if (err < 0) { | 3842 | if (err < 0) { |
3832 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3843 | err = cmd_complete(sk, hdev->id, |
3833 | MGMT_STATUS_FAILED); | 3844 | MGMT_OP_START_DISCOVERY, |
3845 | MGMT_STATUS_FAILED, | ||
3846 | &cp->type, sizeof(cp->type)); | ||
3834 | mgmt_pending_remove(cmd); | 3847 | mgmt_pending_remove(cmd); |
3835 | goto failed; | 3848 | goto failed; |
3836 | } | 3849 | } |
@@ -3850,8 +3863,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
3850 | break; | 3863 | break; |
3851 | 3864 | ||
3852 | default: | 3865 | default: |
3853 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3866 | err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
3854 | MGMT_STATUS_INVALID_PARAMS); | 3867 | MGMT_STATUS_INVALID_PARAMS, |
3868 | &cp->type, sizeof(cp->type)); | ||
3855 | mgmt_pending_remove(cmd); | 3869 | mgmt_pending_remove(cmd); |
3856 | goto failed; | 3870 | goto failed; |
3857 | } | 3871 | } |
diff --git a/net/bluetooth/rfcomm/Kconfig b/net/bluetooth/rfcomm/Kconfig index 18d352ea2bc7..335df7515220 100644 --- a/net/bluetooth/rfcomm/Kconfig +++ b/net/bluetooth/rfcomm/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config BT_RFCOMM | 1 | config BT_RFCOMM |
2 | tristate "RFCOMM protocol support" | 2 | tristate "RFCOMM protocol support" |
3 | depends on BT | 3 | depends on BT_BREDR |
4 | help | 4 | help |
5 | RFCOMM provides connection oriented stream transport. RFCOMM | 5 | RFCOMM provides connection oriented stream transport. RFCOMM |
6 | support is required for Dialup Networking, OBEX and other Bluetooth | 6 | support is required for Dialup Networking, OBEX and other Bluetooth |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index bce9c3d39324..64e20dde4837 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -81,6 +81,8 @@ static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s); | |||
81 | #define __test_cr(b) (!!(b & 0x02)) | 81 | #define __test_cr(b) (!!(b & 0x02)) |
82 | #define __test_pf(b) (!!(b & 0x10)) | 82 | #define __test_pf(b) (!!(b & 0x10)) |
83 | 83 | ||
84 | #define __session_dir(s) ((s)->initiator ? 0x00 : 0x01) | ||
85 | |||
84 | #define __addr(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01) | 86 | #define __addr(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01) |
85 | #define __ctrl(type, pf) (((type & 0xef) | (pf << 4))) | 87 | #define __ctrl(type, pf) (((type & 0xef) | (pf << 4))) |
86 | #define __dlci(dir, chn) (((chn & 0x1f) << 1) | dir) | 88 | #define __dlci(dir, chn) (((chn & 0x1f) << 1) | dir) |
@@ -388,7 +390,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, | |||
388 | return err; | 390 | return err; |
389 | } | 391 | } |
390 | 392 | ||
391 | dlci = __dlci(!s->initiator, channel); | 393 | dlci = __dlci(__session_dir(s), channel); |
392 | 394 | ||
393 | /* Check if DLCI already exists */ | 395 | /* Check if DLCI already exists */ |
394 | if (rfcomm_dlc_get(s, dlci)) | 396 | if (rfcomm_dlc_get(s, dlci)) |
@@ -543,7 +545,7 @@ struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel) | |||
543 | rfcomm_lock(); | 545 | rfcomm_lock(); |
544 | s = rfcomm_session_get(src, dst); | 546 | s = rfcomm_session_get(src, dst); |
545 | if (s) { | 547 | if (s) { |
546 | dlci = __dlci(!s->initiator, channel); | 548 | dlci = __dlci(__session_dir(s), channel); |
547 | dlc = rfcomm_dlc_get(s, dlci); | 549 | dlc = rfcomm_dlc_get(s, dlci); |
548 | } | 550 | } |
549 | rfcomm_unlock(); | 551 | rfcomm_unlock(); |
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index 519a65452d90..290e14f2e92e 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c | |||
@@ -176,13 +176,13 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) | |||
176 | raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); | 176 | raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); |
177 | /* at least two bytes will be used for the encoding */ | 177 | /* at least two bytes will be used for the encoding */ |
178 | if (skb->len < 2) | 178 | if (skb->len < 2) |
179 | goto drop; | 179 | return -EINVAL; |
180 | 180 | ||
181 | if (lowpan_fetch_skb_u8(skb, &iphc0)) | 181 | if (lowpan_fetch_skb_u8(skb, &iphc0)) |
182 | goto drop; | 182 | return -EINVAL; |
183 | 183 | ||
184 | if (lowpan_fetch_skb_u8(skb, &iphc1)) | 184 | if (lowpan_fetch_skb_u8(skb, &iphc1)) |
185 | goto drop; | 185 | return -EINVAL; |
186 | 186 | ||
187 | ieee802154_addr_to_sa(&sa, &hdr->source); | 187 | ieee802154_addr_to_sa(&sa, &hdr->source); |
188 | ieee802154_addr_to_sa(&da, &hdr->dest); | 188 | ieee802154_addr_to_sa(&da, &hdr->dest); |
@@ -200,23 +200,6 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) | |||
200 | return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type, | 200 | return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type, |
201 | IEEE802154_ADDR_LEN, dap, da.addr_type, | 201 | IEEE802154_ADDR_LEN, dap, da.addr_type, |
202 | IEEE802154_ADDR_LEN, iphc0, iphc1); | 202 | IEEE802154_ADDR_LEN, iphc0, iphc1); |
203 | |||
204 | drop: | ||
205 | kfree_skb(skb); | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | |||
209 | static int lowpan_set_address(struct net_device *dev, void *p) | ||
210 | { | ||
211 | struct sockaddr *sa = p; | ||
212 | |||
213 | if (netif_running(dev)) | ||
214 | return -EBUSY; | ||
215 | |||
216 | /* TODO: validate addr */ | ||
217 | memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); | ||
218 | |||
219 | return 0; | ||
220 | } | 203 | } |
221 | 204 | ||
222 | static struct sk_buff* | 205 | static struct sk_buff* |
@@ -420,13 +403,6 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
420 | } | 403 | } |
421 | } | 404 | } |
422 | 405 | ||
423 | static struct wpan_phy *lowpan_get_phy(const struct net_device *dev) | ||
424 | { | ||
425 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | ||
426 | |||
427 | return ieee802154_mlme_ops(real_dev)->get_phy(real_dev); | ||
428 | } | ||
429 | |||
430 | static __le16 lowpan_get_pan_id(const struct net_device *dev) | 406 | static __le16 lowpan_get_pan_id(const struct net_device *dev) |
431 | { | 407 | { |
432 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | 408 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; |
@@ -474,12 +450,10 @@ static int lowpan_dev_init(struct net_device *dev) | |||
474 | static const struct net_device_ops lowpan_netdev_ops = { | 450 | static const struct net_device_ops lowpan_netdev_ops = { |
475 | .ndo_init = lowpan_dev_init, | 451 | .ndo_init = lowpan_dev_init, |
476 | .ndo_start_xmit = lowpan_xmit, | 452 | .ndo_start_xmit = lowpan_xmit, |
477 | .ndo_set_mac_address = lowpan_set_address, | ||
478 | }; | 453 | }; |
479 | 454 | ||
480 | static struct ieee802154_mlme_ops lowpan_mlme = { | 455 | static struct ieee802154_mlme_ops lowpan_mlme = { |
481 | .get_pan_id = lowpan_get_pan_id, | 456 | .get_pan_id = lowpan_get_pan_id, |
482 | .get_phy = lowpan_get_phy, | ||
483 | .get_short_addr = lowpan_get_short_addr, | 457 | .get_short_addr = lowpan_get_short_addr, |
484 | .get_dsn = lowpan_get_dsn, | 458 | .get_dsn = lowpan_get_dsn, |
485 | }; | 459 | }; |
@@ -544,7 +518,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | |||
544 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ | 518 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ |
545 | ret = iphc_decompress(skb, &hdr); | 519 | ret = iphc_decompress(skb, &hdr); |
546 | if (ret < 0) | 520 | if (ret < 0) |
547 | goto drop; | 521 | goto drop_skb; |
548 | 522 | ||
549 | return lowpan_give_skb_to_devices(skb, NULL); | 523 | return lowpan_give_skb_to_devices(skb, NULL); |
550 | case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ | 524 | case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ |
@@ -552,7 +526,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | |||
552 | if (ret == 1) { | 526 | if (ret == 1) { |
553 | ret = iphc_decompress(skb, &hdr); | 527 | ret = iphc_decompress(skb, &hdr); |
554 | if (ret < 0) | 528 | if (ret < 0) |
555 | goto drop; | 529 | goto drop_skb; |
556 | 530 | ||
557 | return lowpan_give_skb_to_devices(skb, NULL); | 531 | return lowpan_give_skb_to_devices(skb, NULL); |
558 | } else if (ret == -1) { | 532 | } else if (ret == -1) { |
@@ -565,7 +539,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | |||
565 | if (ret == 1) { | 539 | if (ret == 1) { |
566 | ret = iphc_decompress(skb, &hdr); | 540 | ret = iphc_decompress(skb, &hdr); |
567 | if (ret < 0) | 541 | if (ret < 0) |
568 | goto drop; | 542 | goto drop_skb; |
569 | 543 | ||
570 | return lowpan_give_skb_to_devices(skb, NULL); | 544 | return lowpan_give_skb_to_devices(skb, NULL); |
571 | } else if (ret == -1) { | 545 | } else if (ret == -1) { |
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c index 620abc2ba5fc..d1cd0edfb149 100644 --- a/net/ieee802154/core.c +++ b/net/ieee802154/core.c | |||
@@ -21,9 +21,7 @@ | |||
21 | 21 | ||
22 | #include "ieee802154.h" | 22 | #include "ieee802154.h" |
23 | #include "sysfs.h" | 23 | #include "sysfs.h" |
24 | 24 | #include "core.h" | |
25 | static DEFINE_MUTEX(wpan_phy_mutex); | ||
26 | static int wpan_phy_idx; | ||
27 | 25 | ||
28 | static int wpan_phy_match(struct device *dev, const void *data) | 26 | static int wpan_phy_match(struct device *dev, const void *data) |
29 | { | 27 | { |
@@ -71,42 +69,41 @@ int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), | |||
71 | } | 69 | } |
72 | EXPORT_SYMBOL(wpan_phy_for_each); | 70 | EXPORT_SYMBOL(wpan_phy_for_each); |
73 | 71 | ||
74 | static int wpan_phy_idx_valid(int idx) | 72 | struct wpan_phy * |
73 | wpan_phy_alloc(const struct cfg802154_ops *ops, size_t priv_size) | ||
75 | { | 74 | { |
76 | return idx >= 0; | 75 | static atomic_t wpan_phy_counter = ATOMIC_INIT(0); |
77 | } | 76 | struct cfg802154_registered_device *rdev; |
77 | size_t alloc_size; | ||
78 | 78 | ||
79 | struct wpan_phy *wpan_phy_alloc(size_t priv_size) | 79 | alloc_size = sizeof(*rdev) + priv_size; |
80 | { | 80 | rdev = kzalloc(alloc_size, GFP_KERNEL); |
81 | struct wpan_phy *phy = kzalloc(sizeof(*phy) + priv_size, | 81 | if (!rdev) |
82 | GFP_KERNEL); | 82 | return NULL; |
83 | 83 | ||
84 | if (!phy) | 84 | rdev->ops = ops; |
85 | goto out; | ||
86 | mutex_lock(&wpan_phy_mutex); | ||
87 | phy->idx = wpan_phy_idx++; | ||
88 | if (unlikely(!wpan_phy_idx_valid(phy->idx))) { | ||
89 | wpan_phy_idx--; | ||
90 | mutex_unlock(&wpan_phy_mutex); | ||
91 | kfree(phy); | ||
92 | goto out; | ||
93 | } | ||
94 | mutex_unlock(&wpan_phy_mutex); | ||
95 | 85 | ||
96 | mutex_init(&phy->pib_lock); | 86 | rdev->wpan_phy_idx = atomic_inc_return(&wpan_phy_counter); |
97 | 87 | ||
98 | device_initialize(&phy->dev); | 88 | if (unlikely(rdev->wpan_phy_idx < 0)) { |
99 | dev_set_name(&phy->dev, "wpan-phy%d", phy->idx); | 89 | /* ugh, wrapped! */ |
90 | atomic_dec(&wpan_phy_counter); | ||
91 | kfree(rdev); | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | /* atomic_inc_return makes it start at 1, make it start at 0 */ | ||
96 | rdev->wpan_phy_idx--; | ||
100 | 97 | ||
101 | phy->dev.class = &wpan_phy_class; | 98 | mutex_init(&rdev->wpan_phy.pib_lock); |
102 | 99 | ||
103 | phy->current_channel = -1; /* not initialised */ | 100 | device_initialize(&rdev->wpan_phy.dev); |
104 | phy->current_page = 0; /* for compatibility */ | 101 | dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy_idx); |
105 | 102 | ||
106 | return phy; | 103 | rdev->wpan_phy.dev.class = &wpan_phy_class; |
104 | rdev->wpan_phy.dev.platform_data = rdev; | ||
107 | 105 | ||
108 | out: | 106 | return &rdev->wpan_phy; |
109 | return NULL; | ||
110 | } | 107 | } |
111 | EXPORT_SYMBOL(wpan_phy_alloc); | 108 | EXPORT_SYMBOL(wpan_phy_alloc); |
112 | 109 | ||
@@ -128,6 +125,11 @@ void wpan_phy_free(struct wpan_phy *phy) | |||
128 | } | 125 | } |
129 | EXPORT_SYMBOL(wpan_phy_free); | 126 | EXPORT_SYMBOL(wpan_phy_free); |
130 | 127 | ||
128 | void cfg802154_dev_free(struct cfg802154_registered_device *rdev) | ||
129 | { | ||
130 | kfree(rdev); | ||
131 | } | ||
132 | |||
131 | static int __init wpan_phy_class_init(void) | 133 | static int __init wpan_phy_class_init(void) |
132 | { | 134 | { |
133 | int rc; | 135 | int rc; |
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h new file mode 100644 index 000000000000..fea60b3a8846 --- /dev/null +++ b/net/ieee802154/core.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef __IEEE802154_CORE_H | ||
2 | #define __IEEE802154_CORE_H | ||
3 | |||
4 | #include <net/cfg802154.h> | ||
5 | |||
6 | struct cfg802154_registered_device { | ||
7 | const struct cfg802154_ops *ops; | ||
8 | |||
9 | /* wpan_phy index, internal only */ | ||
10 | int wpan_phy_idx; | ||
11 | |||
12 | /* must be last because of the way we do wpan_phy_priv(), | ||
13 | * and it should at least be aligned to NETDEV_ALIGN | ||
14 | */ | ||
15 | struct wpan_phy wpan_phy __aligned(NETDEV_ALIGN); | ||
16 | }; | ||
17 | |||
18 | static inline struct cfg802154_registered_device * | ||
19 | wpan_phy_to_rdev(struct wpan_phy *wpan_phy) | ||
20 | { | ||
21 | BUG_ON(!wpan_phy); | ||
22 | return container_of(wpan_phy, struct cfg802154_registered_device, | ||
23 | wpan_phy); | ||
24 | } | ||
25 | |||
26 | /* free object */ | ||
27 | void cfg802154_dev_free(struct cfg802154_registered_device *rdev); | ||
28 | |||
29 | #endif /* __IEEE802154_CORE_H */ | ||
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index abd0f31bdc66..7127b9d1a684 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/nl802154.h> | 29 | #include <linux/nl802154.h> |
30 | #include <linux/export.h> | 30 | #include <linux/export.h> |
31 | #include <net/af_ieee802154.h> | 31 | #include <net/af_ieee802154.h> |
32 | #include <net/nl802154.h> | ||
33 | #include <net/ieee802154_netdev.h> | 32 | #include <net/ieee802154_netdev.h> |
34 | #include <net/cfg802154.h> | 33 | #include <net/cfg802154.h> |
35 | 34 | ||
@@ -55,186 +54,7 @@ static __le16 nla_get_shortaddr(const struct nlattr *nla) | |||
55 | return cpu_to_le16(nla_get_u16(nla)); | 54 | return cpu_to_le16(nla_get_u16(nla)); |
56 | } | 55 | } |
57 | 56 | ||
58 | int ieee802154_nl_assoc_indic(struct net_device *dev, | 57 | static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) |
59 | struct ieee802154_addr *addr, | ||
60 | u8 cap) | ||
61 | { | ||
62 | struct sk_buff *msg; | ||
63 | |||
64 | pr_debug("%s\n", __func__); | ||
65 | |||
66 | if (addr->mode != IEEE802154_ADDR_LONG) { | ||
67 | pr_err("%s: received non-long source address!\n", __func__); | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | |||
71 | msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC); | ||
72 | if (!msg) | ||
73 | return -ENOBUFS; | ||
74 | |||
75 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || | ||
76 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | ||
77 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
78 | dev->dev_addr) || | ||
79 | nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, | ||
80 | addr->extended_addr) || | ||
81 | nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap)) | ||
82 | goto nla_put_failure; | ||
83 | |||
84 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); | ||
85 | |||
86 | nla_put_failure: | ||
87 | nlmsg_free(msg); | ||
88 | return -ENOBUFS; | ||
89 | } | ||
90 | EXPORT_SYMBOL(ieee802154_nl_assoc_indic); | ||
91 | |||
92 | int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr, | ||
93 | u8 status) | ||
94 | { | ||
95 | struct sk_buff *msg; | ||
96 | |||
97 | pr_debug("%s\n", __func__); | ||
98 | |||
99 | msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF); | ||
100 | if (!msg) | ||
101 | return -ENOBUFS; | ||
102 | |||
103 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || | ||
104 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | ||
105 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
106 | dev->dev_addr) || | ||
107 | nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || | ||
108 | nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) | ||
109 | goto nla_put_failure; | ||
110 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); | ||
111 | |||
112 | nla_put_failure: | ||
113 | nlmsg_free(msg); | ||
114 | return -ENOBUFS; | ||
115 | } | ||
116 | EXPORT_SYMBOL(ieee802154_nl_assoc_confirm); | ||
117 | |||
118 | int ieee802154_nl_disassoc_indic(struct net_device *dev, | ||
119 | struct ieee802154_addr *addr, | ||
120 | u8 reason) | ||
121 | { | ||
122 | struct sk_buff *msg; | ||
123 | |||
124 | pr_debug("%s\n", __func__); | ||
125 | |||
126 | msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC); | ||
127 | if (!msg) | ||
128 | return -ENOBUFS; | ||
129 | |||
130 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || | ||
131 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | ||
132 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
133 | dev->dev_addr)) | ||
134 | goto nla_put_failure; | ||
135 | if (addr->mode == IEEE802154_ADDR_LONG) { | ||
136 | if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, | ||
137 | addr->extended_addr)) | ||
138 | goto nla_put_failure; | ||
139 | } else { | ||
140 | if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, | ||
141 | addr->short_addr)) | ||
142 | goto nla_put_failure; | ||
143 | } | ||
144 | if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason)) | ||
145 | goto nla_put_failure; | ||
146 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); | ||
147 | |||
148 | nla_put_failure: | ||
149 | nlmsg_free(msg); | ||
150 | return -ENOBUFS; | ||
151 | } | ||
152 | EXPORT_SYMBOL(ieee802154_nl_disassoc_indic); | ||
153 | |||
154 | int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status) | ||
155 | { | ||
156 | struct sk_buff *msg; | ||
157 | |||
158 | pr_debug("%s\n", __func__); | ||
159 | |||
160 | msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF); | ||
161 | if (!msg) | ||
162 | return -ENOBUFS; | ||
163 | |||
164 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || | ||
165 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | ||
166 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
167 | dev->dev_addr) || | ||
168 | nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) | ||
169 | goto nla_put_failure; | ||
170 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); | ||
171 | |||
172 | nla_put_failure: | ||
173 | nlmsg_free(msg); | ||
174 | return -ENOBUFS; | ||
175 | } | ||
176 | EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm); | ||
177 | |||
178 | int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid, | ||
179 | __le16 coord_addr) | ||
180 | { | ||
181 | struct sk_buff *msg; | ||
182 | |||
183 | pr_debug("%s\n", __func__); | ||
184 | |||
185 | msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC); | ||
186 | if (!msg) | ||
187 | return -ENOBUFS; | ||
188 | |||
189 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || | ||
190 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | ||
191 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
192 | dev->dev_addr) || | ||
193 | nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, | ||
194 | coord_addr) || | ||
195 | nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid)) | ||
196 | goto nla_put_failure; | ||
197 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); | ||
198 | |||
199 | nla_put_failure: | ||
200 | nlmsg_free(msg); | ||
201 | return -ENOBUFS; | ||
202 | } | ||
203 | EXPORT_SYMBOL(ieee802154_nl_beacon_indic); | ||
204 | |||
205 | int ieee802154_nl_scan_confirm(struct net_device *dev, | ||
206 | u8 status, u8 scan_type, | ||
207 | u32 unscanned, u8 page, | ||
208 | u8 *edl/* , struct list_head *pan_desc_list */) | ||
209 | { | ||
210 | struct sk_buff *msg; | ||
211 | |||
212 | pr_debug("%s\n", __func__); | ||
213 | |||
214 | msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF); | ||
215 | if (!msg) | ||
216 | return -ENOBUFS; | ||
217 | |||
218 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || | ||
219 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | ||
220 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
221 | dev->dev_addr) || | ||
222 | nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) || | ||
223 | nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) || | ||
224 | nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) || | ||
225 | nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) || | ||
226 | (edl && | ||
227 | nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl))) | ||
228 | goto nla_put_failure; | ||
229 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); | ||
230 | |||
231 | nla_put_failure: | ||
232 | nlmsg_free(msg); | ||
233 | return -ENOBUFS; | ||
234 | } | ||
235 | EXPORT_SYMBOL(ieee802154_nl_scan_confirm); | ||
236 | |||
237 | int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) | ||
238 | { | 58 | { |
239 | struct sk_buff *msg; | 59 | struct sk_buff *msg; |
240 | 60 | ||
@@ -274,8 +94,9 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, | |||
274 | goto out; | 94 | goto out; |
275 | 95 | ||
276 | ops = ieee802154_mlme_ops(dev); | 96 | ops = ieee802154_mlme_ops(dev); |
277 | phy = ops->get_phy(dev); | 97 | phy = dev->ieee802154_ptr->wpan_phy; |
278 | BUG_ON(!phy); | 98 | BUG_ON(!phy); |
99 | get_device(&phy->dev); | ||
279 | 100 | ||
280 | short_addr = ops->get_short_addr(dev); | 101 | short_addr = ops->get_short_addr(dev); |
281 | pan_id = ops->get_pan_id(dev); | 102 | pan_id = ops->get_pan_id(dev); |
@@ -477,7 +298,7 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) | |||
477 | u8 channel, bcn_ord, sf_ord; | 298 | u8 channel, bcn_ord, sf_ord; |
478 | u8 page; | 299 | u8 page; |
479 | int pan_coord, blx, coord_realign; | 300 | int pan_coord, blx, coord_realign; |
480 | int ret = -EOPNOTSUPP; | 301 | int ret = -EBUSY; |
481 | 302 | ||
482 | if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || | 303 | if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || |
483 | !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || | 304 | !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || |
@@ -493,8 +314,14 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) | |||
493 | dev = ieee802154_nl_get_dev(info); | 314 | dev = ieee802154_nl_get_dev(info); |
494 | if (!dev) | 315 | if (!dev) |
495 | return -ENODEV; | 316 | return -ENODEV; |
496 | if (!ieee802154_mlme_ops(dev)->start_req) | 317 | |
318 | if (netif_running(dev)) | ||
319 | goto out; | ||
320 | |||
321 | if (!ieee802154_mlme_ops(dev)->start_req) { | ||
322 | ret = -EOPNOTSUPP; | ||
497 | goto out; | 323 | goto out; |
324 | } | ||
498 | 325 | ||
499 | addr.mode = IEEE802154_ADDR_SHORT; | 326 | addr.mode = IEEE802154_ADDR_SHORT; |
500 | addr.short_addr = nla_get_shortaddr( | 327 | addr.short_addr = nla_get_shortaddr( |
@@ -524,6 +351,11 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) | |||
524 | ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, | 351 | ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, |
525 | bcn_ord, sf_ord, pan_coord, blx, coord_realign); | 352 | bcn_ord, sf_ord, pan_coord, blx, coord_realign); |
526 | 353 | ||
354 | /* FIXME: add validation for unused parameters to be sane | ||
355 | * for SoftMAC | ||
356 | */ | ||
357 | ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS); | ||
358 | |||
527 | out: | 359 | out: |
528 | dev_put(dev); | 360 | dev_put(dev); |
529 | return ret; | 361 | return ret; |
@@ -662,7 +494,8 @@ int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info) | |||
662 | !info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) | 494 | !info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) |
663 | goto out; | 495 | goto out; |
664 | 496 | ||
665 | phy = ops->get_phy(dev); | 497 | phy = dev->ieee802154_ptr->wpan_phy; |
498 | get_device(&phy->dev); | ||
666 | 499 | ||
667 | ops->get_mac_params(dev, ¶ms); | 500 | ops->get_mac_params(dev, ¶ms); |
668 | 501 | ||
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 0afe760ff512..80a946dddd90 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/nl802154.h> | 30 | #include <linux/nl802154.h> |
31 | 31 | ||
32 | #include "ieee802154.h" | 32 | #include "ieee802154.h" |
33 | #include "rdev-ops.h" | ||
34 | #include "core.h" | ||
33 | 35 | ||
34 | static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, | 36 | static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, |
35 | u32 seq, int flags, struct wpan_phy *phy) | 37 | u32 seq, int flags, struct wpan_phy *phy) |
@@ -203,11 +205,6 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
203 | if (!msg) | 205 | if (!msg) |
204 | goto out_dev; | 206 | goto out_dev; |
205 | 207 | ||
206 | if (!phy->add_iface) { | ||
207 | rc = -EINVAL; | ||
208 | goto nla_put_failure; | ||
209 | } | ||
210 | |||
211 | if (info->attrs[IEEE802154_ATTR_HW_ADDR] && | 208 | if (info->attrs[IEEE802154_ATTR_HW_ADDR] && |
212 | nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) != | 209 | nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) != |
213 | IEEE802154_ADDR_LEN) { | 210 | IEEE802154_ADDR_LEN) { |
@@ -223,11 +220,13 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
223 | } | 220 | } |
224 | } | 221 | } |
225 | 222 | ||
226 | dev = phy->add_iface(phy, devname, type); | 223 | dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname, |
224 | type); | ||
227 | if (IS_ERR(dev)) { | 225 | if (IS_ERR(dev)) { |
228 | rc = PTR_ERR(dev); | 226 | rc = PTR_ERR(dev); |
229 | goto nla_put_failure; | 227 | goto nla_put_failure; |
230 | } | 228 | } |
229 | dev_hold(dev); | ||
231 | 230 | ||
232 | if (info->attrs[IEEE802154_ATTR_HW_ADDR]) { | 231 | if (info->attrs[IEEE802154_ATTR_HW_ADDR]) { |
233 | struct sockaddr addr; | 232 | struct sockaddr addr; |
@@ -257,7 +256,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
257 | 256 | ||
258 | dev_unregister: | 257 | dev_unregister: |
259 | rtnl_lock(); /* del_iface must be called with RTNL lock */ | 258 | rtnl_lock(); /* del_iface must be called with RTNL lock */ |
260 | phy->del_iface(phy, dev); | 259 | rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev); |
261 | dev_put(dev); | 260 | dev_put(dev); |
262 | rtnl_unlock(); | 261 | rtnl_unlock(); |
263 | nla_put_failure: | 262 | nla_put_failure: |
@@ -288,8 +287,9 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info) | |||
288 | if (!dev) | 287 | if (!dev) |
289 | return -ENODEV; | 288 | return -ENODEV; |
290 | 289 | ||
291 | phy = ieee802154_mlme_ops(dev)->get_phy(dev); | 290 | phy = dev->ieee802154_ptr->wpan_phy; |
292 | BUG_ON(!phy); | 291 | BUG_ON(!phy); |
292 | get_device(&phy->dev); | ||
293 | 293 | ||
294 | rc = -EINVAL; | 294 | rc = -EINVAL; |
295 | /* phy name is optional, but should be checked if it's given */ | 295 | /* phy name is optional, but should be checked if it's given */ |
@@ -319,13 +319,8 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info) | |||
319 | if (!msg) | 319 | if (!msg) |
320 | goto out_dev; | 320 | goto out_dev; |
321 | 321 | ||
322 | if (!phy->del_iface) { | ||
323 | rc = -EINVAL; | ||
324 | goto nla_put_failure; | ||
325 | } | ||
326 | |||
327 | rtnl_lock(); | 322 | rtnl_lock(); |
328 | phy->del_iface(phy, dev); | 323 | rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev); |
329 | 324 | ||
330 | /* We don't have device anymore */ | 325 | /* We don't have device anymore */ |
331 | dev_put(dev); | 326 | dev_put(dev); |
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h new file mode 100644 index 000000000000..ac8824ec168c --- /dev/null +++ b/net/ieee802154/rdev-ops.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef __CFG802154_RDEV_OPS | ||
2 | #define __CFG802154_RDEV_OPS | ||
3 | |||
4 | #include <net/cfg802154.h> | ||
5 | |||
6 | #include "core.h" | ||
7 | |||
8 | static inline struct net_device * | ||
9 | rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, | ||
10 | const char *name, int type) | ||
11 | { | ||
12 | return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name, | ||
13 | type); | ||
14 | } | ||
15 | |||
16 | static inline void | ||
17 | rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, | ||
18 | struct net_device *dev) | ||
19 | { | ||
20 | rdev->ops->del_virtual_intf_deprecated(&rdev->wpan_phy, dev); | ||
21 | } | ||
22 | |||
23 | #endif /* __CFG802154_RDEV_OPS */ | ||
diff --git a/net/ieee802154/sysfs.c b/net/ieee802154/sysfs.c index eb9ca6f99122..88199980dae9 100644 --- a/net/ieee802154/sysfs.c +++ b/net/ieee802154/sysfs.c | |||
@@ -17,6 +17,16 @@ | |||
17 | 17 | ||
18 | #include <net/cfg802154.h> | 18 | #include <net/cfg802154.h> |
19 | 19 | ||
20 | #include "core.h" | ||
21 | #include "sysfs.h" | ||
22 | |||
23 | static inline struct cfg802154_registered_device * | ||
24 | dev_to_rdev(struct device *dev) | ||
25 | { | ||
26 | return container_of(dev, struct cfg802154_registered_device, | ||
27 | wpan_phy.dev); | ||
28 | } | ||
29 | |||
20 | #define MASTER_SHOW_COMPLEX(name, format_string, args...) \ | 30 | #define MASTER_SHOW_COMPLEX(name, format_string, args...) \ |
21 | static ssize_t name ## _show(struct device *dev, \ | 31 | static ssize_t name ## _show(struct device *dev, \ |
22 | struct device_attribute *attr, char *buf) \ | 32 | struct device_attribute *attr, char *buf) \ |
@@ -60,11 +70,11 @@ static ssize_t channels_supported_show(struct device *dev, | |||
60 | } | 70 | } |
61 | static DEVICE_ATTR_RO(channels_supported); | 71 | static DEVICE_ATTR_RO(channels_supported); |
62 | 72 | ||
63 | static void wpan_phy_release(struct device *d) | 73 | static void wpan_phy_release(struct device *dev) |
64 | { | 74 | { |
65 | struct wpan_phy *phy = container_of(d, struct wpan_phy, dev); | 75 | struct cfg802154_registered_device *rdev = dev_to_rdev(dev); |
66 | 76 | ||
67 | kfree(phy); | 77 | cfg802154_dev_free(rdev); |
68 | } | 78 | } |
69 | 79 | ||
70 | static struct attribute *pmib_attrs[] = { | 80 | static struct attribute *pmib_attrs[] = { |
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile index 2e497d0c829a..702d8b466317 100644 --- a/net/mac802154/Makefile +++ b/net/mac802154/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_MAC802154) += mac802154.o | 1 | obj-$(CONFIG_MAC802154) += mac802154.o |
2 | mac802154-objs := main.o rx.o tx.o mac_cmd.o mib.o \ | 2 | mac802154-objs := main.o rx.o tx.o mac_cmd.o mib.o \ |
3 | iface.o llsec.o util.o | 3 | iface.o llsec.o util.o cfg.o |
4 | 4 | ||
5 | ccflags-y += -D__CHECK_ENDIAN__ | 5 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c new file mode 100644 index 000000000000..d2c4e8f89720 --- /dev/null +++ b/net/mac802154/cfg.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* This program is free software; you can redistribute it and/or modify | ||
2 | * it under the terms of the GNU General Public License version 2 | ||
3 | * as published by the Free Software Foundation. | ||
4 | * | ||
5 | * This program is distributed in the hope that it will be useful, | ||
6 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
7 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
8 | * GNU General Public License for more details. | ||
9 | * | ||
10 | * Authors: | ||
11 | * Alexander Aring <aar@pengutronix.de> | ||
12 | * | ||
13 | * Based on: net/mac80211/cfg.c | ||
14 | */ | ||
15 | |||
16 | #include <net/rtnetlink.h> | ||
17 | #include <net/cfg802154.h> | ||
18 | |||
19 | #include "ieee802154_i.h" | ||
20 | #include "cfg.h" | ||
21 | |||
22 | static struct net_device * | ||
23 | ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, | ||
24 | const char *name, int type) | ||
25 | { | ||
26 | struct ieee802154_local *local = wpan_phy_priv(wpan_phy); | ||
27 | struct net_device *dev; | ||
28 | |||
29 | rtnl_lock(); | ||
30 | dev = ieee802154_if_add(local, name, NULL, type); | ||
31 | rtnl_unlock(); | ||
32 | |||
33 | return dev; | ||
34 | } | ||
35 | |||
36 | static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, | ||
37 | struct net_device *dev) | ||
38 | { | ||
39 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
40 | |||
41 | ieee802154_if_remove(sdata); | ||
42 | } | ||
43 | |||
44 | const struct cfg802154_ops mac802154_config_ops = { | ||
45 | .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated, | ||
46 | .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated, | ||
47 | }; | ||
diff --git a/net/mac802154/cfg.h b/net/mac802154/cfg.h new file mode 100644 index 000000000000..e2718f981e82 --- /dev/null +++ b/net/mac802154/cfg.h | |||
@@ -0,0 +1,9 @@ | |||
1 | /* mac802154 configuration hooks for cfg802154 | ||
2 | */ | ||
3 | |||
4 | #ifndef __CFG_H | ||
5 | #define __CFG_H | ||
6 | |||
7 | extern const struct cfg802154_ops mac802154_config_ops; | ||
8 | |||
9 | #endif /* __CFG_H */ | ||
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 1086a9d96f8f..4acacea0d371 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #define __IEEE802154_I_H | 20 | #define __IEEE802154_I_H |
21 | 21 | ||
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <net/cfg802154.h> | ||
23 | #include <net/mac802154.h> | 24 | #include <net/mac802154.h> |
24 | #include <net/ieee802154_netdev.h> | 25 | #include <net/ieee802154_netdev.h> |
25 | 26 | ||
@@ -73,18 +74,20 @@ enum ieee802154_sdata_state_bits { | |||
73 | struct ieee802154_sub_if_data { | 74 | struct ieee802154_sub_if_data { |
74 | struct list_head list; /* the ieee802154_priv->slaves list */ | 75 | struct list_head list; /* the ieee802154_priv->slaves list */ |
75 | 76 | ||
77 | struct wpan_dev wpan_dev; | ||
78 | |||
76 | struct ieee802154_local *local; | 79 | struct ieee802154_local *local; |
77 | struct net_device *dev; | 80 | struct net_device *dev; |
78 | 81 | ||
79 | int type; | ||
80 | unsigned long state; | 82 | unsigned long state; |
83 | char name[IFNAMSIZ]; | ||
81 | 84 | ||
82 | spinlock_t mib_lock; | 85 | spinlock_t mib_lock; |
83 | 86 | ||
84 | __le16 pan_id; | 87 | __le16 pan_id; |
85 | __le16 short_addr; | 88 | __le16 short_addr; |
86 | __le64 extended_addr; | 89 | __le64 extended_addr; |
87 | bool promisuous_mode; | 90 | bool promiscuous_mode; |
88 | 91 | ||
89 | struct ieee802154_mac_params mac_params; | 92 | struct ieee802154_mac_params mac_params; |
90 | 93 | ||
@@ -99,6 +102,8 @@ struct ieee802154_sub_if_data { | |||
99 | struct mutex sec_mtx; | 102 | struct mutex sec_mtx; |
100 | 103 | ||
101 | struct mac802154_llsec sec; | 104 | struct mac802154_llsec sec; |
105 | /* must be last, dynamically sized area in this! */ | ||
106 | struct ieee802154_vif vif; | ||
102 | }; | 107 | }; |
103 | 108 | ||
104 | #define MAC802154_CHAN_NONE 0xff /* No channel is assigned */ | 109 | #define MAC802154_CHAN_NONE 0xff /* No channel is assigned */ |
@@ -135,7 +140,6 @@ ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | |||
135 | /* MIB callbacks */ | 140 | /* MIB callbacks */ |
136 | void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val); | 141 | void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val); |
137 | __le16 mac802154_dev_get_short_addr(const struct net_device *dev); | 142 | __le16 mac802154_dev_get_short_addr(const struct net_device *dev); |
138 | void mac802154_dev_set_ieee_addr(struct net_device *dev); | ||
139 | __le16 mac802154_dev_get_pan_id(const struct net_device *dev); | 143 | __le16 mac802154_dev_get_pan_id(const struct net_device *dev); |
140 | void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val); | 144 | void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val); |
141 | void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); | 145 | void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); |
@@ -174,4 +178,11 @@ void mac802154_get_table(struct net_device *dev, | |||
174 | struct ieee802154_llsec_table **t); | 178 | struct ieee802154_llsec_table **t); |
175 | void mac802154_unlock_table(struct net_device *dev); | 179 | void mac802154_unlock_table(struct net_device *dev); |
176 | 180 | ||
181 | struct net_device * | ||
182 | mac802154_add_iface(struct wpan_phy *phy, const char *name, int type); | ||
183 | void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata); | ||
184 | struct net_device * | ||
185 | ieee802154_if_add(struct ieee802154_local *local, const char *name, | ||
186 | struct wpan_dev **new_wpan_dev, int type); | ||
187 | |||
177 | #endif /* __IEEE802154_I_H */ | 188 | #endif /* __IEEE802154_I_H */ |
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index f7a6f83301e2..384f4bb3c99b 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include <net/rtnetlink.h> | 25 | #include <net/rtnetlink.h> |
26 | #include <linux/nl802154.h> | 26 | #include <linux/nl802154.h> |
27 | #include <net/af_ieee802154.h> | ||
28 | #include <net/mac802154.h> | 27 | #include <net/mac802154.h> |
29 | #include <net/ieee802154_netdev.h> | 28 | #include <net/ieee802154_netdev.h> |
30 | #include <net/cfg802154.h> | 29 | #include <net/cfg802154.h> |
@@ -110,37 +109,21 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
110 | 109 | ||
111 | static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) | 110 | static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) |
112 | { | 111 | { |
112 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
113 | struct sockaddr *addr = p; | 113 | struct sockaddr *addr = p; |
114 | __le64 extended_addr; | ||
114 | 115 | ||
115 | if (netif_running(dev)) | 116 | if (netif_running(dev)) |
116 | return -EBUSY; | 117 | return -EBUSY; |
117 | 118 | ||
118 | /* FIXME: validate addr */ | 119 | ieee802154_be64_to_le64(&extended_addr, addr->sa_data); |
119 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | 120 | if (!ieee802154_is_valid_extended_addr(extended_addr)) |
120 | mac802154_dev_set_ieee_addr(dev); | 121 | return -EINVAL; |
121 | return mac802154_wpan_update_llsec(dev); | ||
122 | } | ||
123 | |||
124 | int mac802154_set_mac_params(struct net_device *dev, | ||
125 | const struct ieee802154_mac_params *params) | ||
126 | { | ||
127 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
128 | |||
129 | mutex_lock(&sdata->local->iflist_mtx); | ||
130 | sdata->mac_params = *params; | ||
131 | mutex_unlock(&sdata->local->iflist_mtx); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | 122 | ||
136 | void mac802154_get_mac_params(struct net_device *dev, | 123 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); |
137 | struct ieee802154_mac_params *params) | 124 | sdata->extended_addr = extended_addr; |
138 | { | ||
139 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
140 | 125 | ||
141 | mutex_lock(&sdata->local->iflist_mtx); | 126 | return mac802154_wpan_update_llsec(dev); |
142 | *params = sdata->mac_params; | ||
143 | mutex_unlock(&sdata->local->iflist_mtx); | ||
144 | } | 127 | } |
145 | 128 | ||
146 | static int mac802154_slave_open(struct net_device *dev) | 129 | static int mac802154_slave_open(struct net_device *dev) |
@@ -152,10 +135,11 @@ static int mac802154_slave_open(struct net_device *dev) | |||
152 | 135 | ||
153 | ASSERT_RTNL(); | 136 | ASSERT_RTNL(); |
154 | 137 | ||
155 | if (sdata->type == IEEE802154_DEV_WPAN) { | 138 | if (sdata->vif.type == IEEE802154_DEV_WPAN) { |
156 | mutex_lock(&sdata->local->iflist_mtx); | 139 | mutex_lock(&sdata->local->iflist_mtx); |
157 | list_for_each_entry(subif, &sdata->local->interfaces, list) { | 140 | list_for_each_entry(subif, &sdata->local->interfaces, list) { |
158 | if (subif != sdata && subif->type == sdata->type && | 141 | if (subif != sdata && |
142 | subif->vif.type == sdata->vif.type && | ||
159 | ieee802154_sdata_running(subif)) { | 143 | ieee802154_sdata_running(subif)) { |
160 | mutex_unlock(&sdata->local->iflist_mtx); | 144 | mutex_unlock(&sdata->local->iflist_mtx); |
161 | return -EBUSY; | 145 | return -EBUSY; |
@@ -197,32 +181,27 @@ static int mac802154_wpan_open(struct net_device *dev) | |||
197 | mutex_lock(&phy->pib_lock); | 181 | mutex_lock(&phy->pib_lock); |
198 | 182 | ||
199 | if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) { | 183 | if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) { |
200 | rc = drv_set_promiscuous_mode(local, sdata->promisuous_mode); | 184 | rc = drv_set_promiscuous_mode(local, sdata->promiscuous_mode); |
201 | if (rc < 0) | 185 | if (rc < 0) |
202 | goto out; | 186 | goto out; |
203 | } | 187 | } |
204 | 188 | ||
205 | if (local->hw.flags & IEEE802154_HW_TXPOWER) { | 189 | if (local->hw.flags & IEEE802154_HW_AFILT) { |
206 | rc = drv_set_tx_power(local, sdata->mac_params.transmit_power); | 190 | rc = drv_set_pan_id(local, sdata->pan_id); |
207 | if (rc < 0) | 191 | if (rc < 0) |
208 | goto out; | 192 | goto out; |
209 | } | ||
210 | 193 | ||
211 | if (local->hw.flags & IEEE802154_HW_LBT) { | 194 | rc = drv_set_extended_addr(local, sdata->extended_addr); |
212 | rc = drv_set_lbt_mode(local, sdata->mac_params.lbt); | ||
213 | if (rc < 0) | 195 | if (rc < 0) |
214 | goto out; | 196 | goto out; |
215 | } | ||
216 | 197 | ||
217 | if (local->hw.flags & IEEE802154_HW_CCA_MODE) { | 198 | rc = drv_set_short_addr(local, sdata->short_addr); |
218 | rc = drv_set_cca_mode(local, sdata->mac_params.cca_mode); | ||
219 | if (rc < 0) | 199 | if (rc < 0) |
220 | goto out; | 200 | goto out; |
221 | } | 201 | } |
222 | 202 | ||
223 | if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) { | 203 | if (local->hw.flags & IEEE802154_HW_LBT) { |
224 | rc = drv_set_cca_ed_level(local, | 204 | rc = drv_set_lbt_mode(local, sdata->mac_params.lbt); |
225 | sdata->mac_params.cca_ed_level); | ||
226 | if (rc < 0) | 205 | if (rc < 0) |
227 | goto out; | 206 | goto out; |
228 | } | 207 | } |
@@ -402,30 +381,23 @@ static void mac802154_wpan_free(struct net_device *dev) | |||
402 | free_netdev(dev); | 381 | free_netdev(dev); |
403 | } | 382 | } |
404 | 383 | ||
405 | void mac802154_wpan_setup(struct net_device *dev) | 384 | static void ieee802154_if_setup(struct net_device *dev) |
406 | { | 385 | { |
407 | struct ieee802154_sub_if_data *sdata; | 386 | dev->addr_len = IEEE802154_EXTENDED_ADDR_LEN; |
408 | 387 | memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_ADDR_LEN); | |
409 | dev->addr_len = IEEE802154_ADDR_LEN; | ||
410 | memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN); | ||
411 | 388 | ||
412 | dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; | 389 | dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; |
413 | dev->header_ops = &mac802154_header_ops; | ||
414 | dev->needed_tailroom = 2 + 16; /* FCS + MIC */ | 390 | dev->needed_tailroom = 2 + 16; /* FCS + MIC */ |
415 | dev->mtu = IEEE802154_MTU; | 391 | dev->mtu = IEEE802154_MTU; |
416 | dev->tx_queue_len = 300; | 392 | dev->tx_queue_len = 300; |
417 | dev->type = ARPHRD_IEEE802154; | ||
418 | dev->flags = IFF_NOARP | IFF_BROADCAST; | 393 | dev->flags = IFF_NOARP | IFF_BROADCAST; |
394 | } | ||
419 | 395 | ||
420 | dev->destructor = mac802154_wpan_free; | 396 | static int |
421 | dev->netdev_ops = &mac802154_wpan_ops; | 397 | ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type) |
422 | dev->ml_priv = &mac802154_mlme_wpan; | 398 | { |
423 | 399 | /* set some type-dependent values */ | |
424 | sdata = IEEE802154_DEV_TO_SUB_IF(dev); | 400 | sdata->vif.type = type; |
425 | sdata->type = IEEE802154_DEV_WPAN; | ||
426 | |||
427 | spin_lock_init(&sdata->mib_lock); | ||
428 | mutex_init(&sdata->sec_mtx); | ||
429 | 401 | ||
430 | get_random_bytes(&sdata->bsn, 1); | 402 | get_random_bytes(&sdata->bsn, 1); |
431 | get_random_bytes(&sdata->dsn, 1); | 403 | get_random_bytes(&sdata->dsn, 1); |
@@ -437,30 +409,113 @@ void mac802154_wpan_setup(struct net_device *dev) | |||
437 | /* for compatibility, actual default is 3 */ | 409 | /* for compatibility, actual default is 3 */ |
438 | sdata->mac_params.frame_retries = -1; | 410 | sdata->mac_params.frame_retries = -1; |
439 | 411 | ||
412 | ieee802154_be64_to_le64(&sdata->extended_addr, sdata->dev->dev_addr); | ||
440 | sdata->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); | 413 | sdata->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); |
441 | sdata->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); | 414 | sdata->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); |
442 | 415 | ||
443 | sdata->promisuous_mode = false; | 416 | switch (type) { |
417 | case IEEE802154_DEV_WPAN: | ||
418 | sdata->dev->header_ops = &mac802154_header_ops; | ||
419 | sdata->dev->destructor = mac802154_wpan_free; | ||
420 | sdata->dev->netdev_ops = &mac802154_wpan_ops; | ||
421 | sdata->dev->ml_priv = &mac802154_mlme_wpan; | ||
422 | sdata->promiscuous_mode = false; | ||
423 | |||
424 | spin_lock_init(&sdata->mib_lock); | ||
425 | mutex_init(&sdata->sec_mtx); | ||
426 | |||
427 | mac802154_llsec_init(&sdata->sec); | ||
428 | break; | ||
429 | case IEEE802154_DEV_MONITOR: | ||
430 | sdata->dev->destructor = free_netdev; | ||
431 | sdata->dev->netdev_ops = &mac802154_monitor_ops; | ||
432 | sdata->promiscuous_mode = true; | ||
433 | break; | ||
434 | default: | ||
435 | BUG(); | ||
436 | } | ||
444 | 437 | ||
445 | mac802154_llsec_init(&sdata->sec); | 438 | return 0; |
446 | } | 439 | } |
447 | 440 | ||
448 | void mac802154_monitor_setup(struct net_device *dev) | 441 | struct net_device * |
442 | ieee802154_if_add(struct ieee802154_local *local, const char *name, | ||
443 | struct wpan_dev **new_wpan_dev, int type) | ||
449 | { | 444 | { |
450 | struct ieee802154_sub_if_data *sdata; | 445 | struct net_device *ndev = NULL; |
446 | struct ieee802154_sub_if_data *sdata = NULL; | ||
447 | int ret = -ENOMEM; | ||
451 | 448 | ||
452 | dev->needed_tailroom = 2; /* room for FCS */ | 449 | ASSERT_RTNL(); |
453 | dev->mtu = IEEE802154_MTU; | 450 | |
454 | dev->tx_queue_len = 10; | 451 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name, |
455 | dev->type = ARPHRD_IEEE802154_MONITOR; | 452 | NET_NAME_UNKNOWN, ieee802154_if_setup); |
456 | dev->flags = IFF_NOARP | IFF_BROADCAST; | 453 | if (!ndev) |
454 | return ERR_PTR(-ENOMEM); | ||
455 | |||
456 | ndev->needed_headroom = local->hw.extra_tx_headroom; | ||
457 | |||
458 | ret = dev_alloc_name(ndev, ndev->name); | ||
459 | if (ret < 0) | ||
460 | goto err; | ||
461 | |||
462 | switch (type) { | ||
463 | case IEEE802154_DEV_WPAN: | ||
464 | ndev->type = ARPHRD_IEEE802154; | ||
465 | break; | ||
466 | case IEEE802154_DEV_MONITOR: | ||
467 | ndev->type = ARPHRD_IEEE802154_MONITOR; | ||
468 | break; | ||
469 | default: | ||
470 | ret = -EINVAL; | ||
471 | goto err; | ||
472 | } | ||
473 | |||
474 | ieee802154_le64_to_be64(ndev->perm_addr, | ||
475 | &local->hw.phy->perm_extended_addr); | ||
476 | memcpy(ndev->dev_addr, ndev->perm_addr, IEEE802154_EXTENDED_ADDR_LEN); | ||
477 | /* TODO check this */ | ||
478 | SET_NETDEV_DEV(ndev, &local->phy->dev); | ||
479 | sdata = netdev_priv(ndev); | ||
480 | ndev->ieee802154_ptr = &sdata->wpan_dev; | ||
481 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | ||
482 | sdata->dev = ndev; | ||
483 | sdata->wpan_dev.wpan_phy = local->hw.phy; | ||
484 | sdata->local = local; | ||
485 | |||
486 | /* setup type-dependent data */ | ||
487 | ret = ieee802154_setup_sdata(sdata, type); | ||
488 | if (ret) | ||
489 | goto err; | ||
490 | |||
491 | if (ndev) { | ||
492 | ret = register_netdevice(ndev); | ||
493 | if (ret < 0) | ||
494 | goto err; | ||
495 | } | ||
496 | |||
497 | mutex_lock(&local->iflist_mtx); | ||
498 | list_add_tail_rcu(&sdata->list, &local->interfaces); | ||
499 | mutex_unlock(&local->iflist_mtx); | ||
457 | 500 | ||
458 | dev->destructor = free_netdev; | 501 | if (new_wpan_dev) |
459 | dev->netdev_ops = &mac802154_monitor_ops; | 502 | *new_wpan_dev = &sdata->wpan_dev; |
460 | dev->ml_priv = &mac802154_mlme_reduced; | ||
461 | 503 | ||
462 | sdata = IEEE802154_DEV_TO_SUB_IF(dev); | 504 | return ndev; |
463 | sdata->type = IEEE802154_DEV_MONITOR; | 505 | |
506 | err: | ||
507 | free_netdev(ndev); | ||
508 | return ERR_PTR(ret); | ||
509 | } | ||
510 | |||
511 | void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata) | ||
512 | { | ||
513 | ASSERT_RTNL(); | ||
514 | |||
515 | mutex_lock(&sdata->local->iflist_mtx); | ||
516 | list_del_rcu(&sdata->list); | ||
517 | mutex_unlock(&sdata->local->iflist_mtx); | ||
464 | 518 | ||
465 | sdata->promisuous_mode = true; | 519 | synchronize_rcu(); |
520 | unregister_netdevice(sdata->dev); | ||
466 | } | 521 | } |
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c index fc261ab33347..00b2b214770e 100644 --- a/net/mac802154/mac_cmd.c +++ b/net/mac802154/mac_cmd.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include <net/ieee802154_netdev.h> | 25 | #include <net/ieee802154_netdev.h> |
26 | #include <net/cfg802154.h> | 26 | #include <net/cfg802154.h> |
27 | #include <net/mac802154.h> | 27 | #include <net/mac802154.h> |
28 | #include <net/nl802154.h> | ||
29 | 28 | ||
30 | #include "ieee802154_i.h" | 29 | #include "ieee802154_i.h" |
30 | #include "driver-ops.h" | ||
31 | 31 | ||
32 | static int mac802154_mlme_start_req(struct net_device *dev, | 32 | static int mac802154_mlme_start_req(struct net_device *dev, |
33 | struct ieee802154_addr *addr, | 33 | struct ieee802154_addr *addr, |
@@ -43,7 +43,6 @@ static int mac802154_mlme_start_req(struct net_device *dev, | |||
43 | 43 | ||
44 | mac802154_dev_set_pan_id(dev, addr->pan_id); | 44 | mac802154_dev_set_pan_id(dev, addr->pan_id); |
45 | mac802154_dev_set_short_addr(dev, addr->short_addr); | 45 | mac802154_dev_set_short_addr(dev, addr->short_addr); |
46 | mac802154_dev_set_ieee_addr(dev); | ||
47 | mac802154_dev_set_page_channel(dev, page, channel); | 46 | mac802154_dev_set_page_channel(dev, page, channel); |
48 | 47 | ||
49 | if (ops->llsec) { | 48 | if (ops->llsec) { |
@@ -65,32 +64,38 @@ static int mac802154_mlme_start_req(struct net_device *dev, | |||
65 | rc = ops->llsec->set_params(dev, ¶ms, changed); | 64 | rc = ops->llsec->set_params(dev, ¶ms, changed); |
66 | } | 65 | } |
67 | 66 | ||
68 | /* FIXME: add validation for unused parameters to be sane | ||
69 | * for SoftMAC | ||
70 | */ | ||
71 | ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS); | ||
72 | |||
73 | return rc; | 67 | return rc; |
74 | } | 68 | } |
75 | 69 | ||
76 | static struct wpan_phy *mac802154_get_phy(const struct net_device *dev) | ||
77 | { | ||
78 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
79 | |||
80 | BUG_ON(dev->type != ARPHRD_IEEE802154); | ||
81 | |||
82 | return to_phy(get_device(&sdata->local->phy->dev)); | ||
83 | } | ||
84 | |||
85 | static int mac802154_set_mac_params(struct net_device *dev, | 70 | static int mac802154_set_mac_params(struct net_device *dev, |
86 | const struct ieee802154_mac_params *params) | 71 | const struct ieee802154_mac_params *params) |
87 | { | 72 | { |
88 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | 73 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); |
74 | struct ieee802154_local *local = sdata->local; | ||
75 | int ret; | ||
89 | 76 | ||
90 | mutex_lock(&sdata->local->iflist_mtx); | 77 | mutex_lock(&sdata->local->iflist_mtx); |
91 | sdata->mac_params = *params; | 78 | sdata->mac_params = *params; |
92 | mutex_unlock(&sdata->local->iflist_mtx); | 79 | mutex_unlock(&sdata->local->iflist_mtx); |
93 | 80 | ||
81 | if (local->hw.flags & IEEE802154_HW_TXPOWER) { | ||
82 | ret = drv_set_tx_power(local, params->transmit_power); | ||
83 | if (ret < 0) | ||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | if (local->hw.flags & IEEE802154_HW_CCA_MODE) { | ||
88 | ret = drv_set_cca_mode(local, params->cca_mode); | ||
89 | if (ret < 0) | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) { | ||
94 | ret = drv_set_cca_ed_level(local, params->cca_ed_level); | ||
95 | if (ret < 0) | ||
96 | return ret; | ||
97 | } | ||
98 | |||
94 | return 0; | 99 | return 0; |
95 | } | 100 | } |
96 | 101 | ||
@@ -120,12 +125,7 @@ static struct ieee802154_llsec_ops mac802154_llsec_ops = { | |||
120 | .unlock_table = mac802154_unlock_table, | 125 | .unlock_table = mac802154_unlock_table, |
121 | }; | 126 | }; |
122 | 127 | ||
123 | struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced = { | ||
124 | .get_phy = mac802154_get_phy, | ||
125 | }; | ||
126 | |||
127 | struct ieee802154_mlme_ops mac802154_mlme_wpan = { | 128 | struct ieee802154_mlme_ops mac802154_mlme_wpan = { |
128 | .get_phy = mac802154_get_phy, | ||
129 | .start_req = mac802154_mlme_start_req, | 129 | .start_req = mac802154_mlme_start_req, |
130 | .get_pan_id = mac802154_dev_get_pan_id, | 130 | .get_pan_id = mac802154_dev_get_pan_id, |
131 | .get_short_addr = mac802154_dev_get_short_addr, | 131 | .get_short_addr = mac802154_dev_get_short_addr, |
diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 86e533ed3775..7d0ff7fd2cd4 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c | |||
@@ -28,90 +28,7 @@ | |||
28 | #include <net/cfg802154.h> | 28 | #include <net/cfg802154.h> |
29 | 29 | ||
30 | #include "ieee802154_i.h" | 30 | #include "ieee802154_i.h" |
31 | 31 | #include "cfg.h" | |
32 | static int | ||
33 | mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev) | ||
34 | { | ||
35 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
36 | struct ieee802154_local *local; | ||
37 | int err; | ||
38 | |||
39 | local = wpan_phy_priv(phy); | ||
40 | |||
41 | sdata->dev = dev; | ||
42 | sdata->local = local; | ||
43 | |||
44 | dev->needed_headroom = local->hw.extra_tx_headroom; | ||
45 | |||
46 | SET_NETDEV_DEV(dev, &local->phy->dev); | ||
47 | |||
48 | err = register_netdev(dev); | ||
49 | if (err < 0) | ||
50 | return err; | ||
51 | |||
52 | rtnl_lock(); | ||
53 | mutex_lock(&local->iflist_mtx); | ||
54 | list_add_tail_rcu(&sdata->list, &local->interfaces); | ||
55 | mutex_unlock(&local->iflist_mtx); | ||
56 | rtnl_unlock(); | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static void | ||
62 | mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) | ||
63 | { | ||
64 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
65 | |||
66 | ASSERT_RTNL(); | ||
67 | |||
68 | BUG_ON(sdata->local->phy != phy); | ||
69 | |||
70 | mutex_lock(&sdata->local->iflist_mtx); | ||
71 | list_del_rcu(&sdata->list); | ||
72 | mutex_unlock(&sdata->local->iflist_mtx); | ||
73 | |||
74 | synchronize_rcu(); | ||
75 | unregister_netdevice(sdata->dev); | ||
76 | } | ||
77 | |||
78 | static struct net_device * | ||
79 | mac802154_add_iface(struct wpan_phy *phy, const char *name, int type) | ||
80 | { | ||
81 | struct net_device *dev; | ||
82 | int err = -ENOMEM; | ||
83 | |||
84 | switch (type) { | ||
85 | case IEEE802154_DEV_MONITOR: | ||
86 | dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), | ||
87 | name, NET_NAME_UNKNOWN, | ||
88 | mac802154_monitor_setup); | ||
89 | break; | ||
90 | case IEEE802154_DEV_WPAN: | ||
91 | dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), | ||
92 | name, NET_NAME_UNKNOWN, | ||
93 | mac802154_wpan_setup); | ||
94 | break; | ||
95 | default: | ||
96 | dev = NULL; | ||
97 | err = -EINVAL; | ||
98 | break; | ||
99 | } | ||
100 | if (!dev) | ||
101 | goto err; | ||
102 | |||
103 | err = mac802154_netdev_register(phy, dev); | ||
104 | if (err) | ||
105 | goto err_free; | ||
106 | |||
107 | dev_hold(dev); /* we return an incremented device refcount */ | ||
108 | return dev; | ||
109 | |||
110 | err_free: | ||
111 | free_netdev(dev); | ||
112 | err: | ||
113 | return ERR_PTR(err); | ||
114 | } | ||
115 | 32 | ||
116 | static void ieee802154_tasklet_handler(unsigned long data) | 33 | static void ieee802154_tasklet_handler(unsigned long data) |
117 | { | 34 | { |
@@ -169,7 +86,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) | |||
169 | 86 | ||
170 | priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; | 87 | priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; |
171 | 88 | ||
172 | phy = wpan_phy_alloc(priv_size); | 89 | phy = wpan_phy_alloc(&mac802154_config_ops, priv_size); |
173 | if (!phy) { | 90 | if (!phy) { |
174 | pr_err("failure to allocate master IEEE802.15.4 device\n"); | 91 | pr_err("failure to allocate master IEEE802.15.4 device\n"); |
175 | return NULL; | 92 | return NULL; |
@@ -209,6 +126,7 @@ EXPORT_SYMBOL(ieee802154_free_hw); | |||
209 | int ieee802154_register_hw(struct ieee802154_hw *hw) | 126 | int ieee802154_register_hw(struct ieee802154_hw *hw) |
210 | { | 127 | { |
211 | struct ieee802154_local *local = hw_to_local(hw); | 128 | struct ieee802154_local *local = hw_to_local(hw); |
129 | struct net_device *dev; | ||
212 | int rc = -ENOSYS; | 130 | int rc = -ENOSYS; |
213 | 131 | ||
214 | local->workqueue = | 132 | local->workqueue = |
@@ -220,13 +138,21 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) | |||
220 | 138 | ||
221 | wpan_phy_set_dev(local->phy, local->hw.parent); | 139 | wpan_phy_set_dev(local->phy, local->hw.parent); |
222 | 140 | ||
223 | local->phy->add_iface = mac802154_add_iface; | ||
224 | local->phy->del_iface = mac802154_del_iface; | ||
225 | |||
226 | rc = wpan_phy_register(local->phy); | 141 | rc = wpan_phy_register(local->phy); |
227 | if (rc < 0) | 142 | if (rc < 0) |
228 | goto out_wq; | 143 | goto out_wq; |
229 | 144 | ||
145 | rtnl_lock(); | ||
146 | |||
147 | dev = ieee802154_if_add(local, "wpan%d", NULL, IEEE802154_DEV_WPAN); | ||
148 | if (IS_ERR(dev)) { | ||
149 | rtnl_unlock(); | ||
150 | rc = PTR_ERR(dev); | ||
151 | goto out_wq; | ||
152 | } | ||
153 | |||
154 | rtnl_unlock(); | ||
155 | |||
230 | return 0; | 156 | return 0; |
231 | 157 | ||
232 | out_wq: | 158 | out_wq: |
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c index 0184fced2f62..6fa749154baf 100644 --- a/net/mac802154/mib.c +++ b/net/mac802154/mib.c | |||
@@ -26,51 +26,6 @@ | |||
26 | #include "ieee802154_i.h" | 26 | #include "ieee802154_i.h" |
27 | #include "driver-ops.h" | 27 | #include "driver-ops.h" |
28 | 28 | ||
29 | struct hw_addr_filt_notify_work { | ||
30 | struct work_struct work; | ||
31 | struct net_device *dev; | ||
32 | unsigned long changed; | ||
33 | }; | ||
34 | |||
35 | static struct ieee802154_local *mac802154_slave_get_priv(struct net_device *dev) | ||
36 | { | ||
37 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
38 | |||
39 | BUG_ON(dev->type != ARPHRD_IEEE802154); | ||
40 | |||
41 | return sdata->local; | ||
42 | } | ||
43 | |||
44 | static void hw_addr_notify(struct work_struct *work) | ||
45 | { | ||
46 | struct hw_addr_filt_notify_work *nw = container_of(work, | ||
47 | struct hw_addr_filt_notify_work, work); | ||
48 | struct ieee802154_local *local = mac802154_slave_get_priv(nw->dev); | ||
49 | int res; | ||
50 | |||
51 | res = local->ops->set_hw_addr_filt(&local->hw, &local->hw.hw_filt, | ||
52 | nw->changed); | ||
53 | if (res) | ||
54 | pr_debug("failed changed mask %lx\n", nw->changed); | ||
55 | |||
56 | kfree(nw); | ||
57 | } | ||
58 | |||
59 | static void set_hw_addr_filt(struct net_device *dev, unsigned long changed) | ||
60 | { | ||
61 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
62 | struct hw_addr_filt_notify_work *work; | ||
63 | |||
64 | work = kzalloc(sizeof(*work), GFP_ATOMIC); | ||
65 | if (!work) | ||
66 | return; | ||
67 | |||
68 | INIT_WORK(&work->work, hw_addr_notify); | ||
69 | work->dev = dev; | ||
70 | work->changed = changed; | ||
71 | queue_work(sdata->local->workqueue, &work->work); | ||
72 | } | ||
73 | |||
74 | void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) | 29 | void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) |
75 | { | 30 | { |
76 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | 31 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); |
@@ -80,12 +35,6 @@ void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) | |||
80 | spin_lock_bh(&sdata->mib_lock); | 35 | spin_lock_bh(&sdata->mib_lock); |
81 | sdata->short_addr = val; | 36 | sdata->short_addr = val; |
82 | spin_unlock_bh(&sdata->mib_lock); | 37 | spin_unlock_bh(&sdata->mib_lock); |
83 | |||
84 | if ((sdata->local->ops->set_hw_addr_filt) && | ||
85 | (sdata->local->hw.hw_filt.short_addr != sdata->short_addr)) { | ||
86 | sdata->local->hw.hw_filt.short_addr = sdata->short_addr; | ||
87 | set_hw_addr_filt(dev, IEEE802154_AFILT_SADDR_CHANGED); | ||
88 | } | ||
89 | } | 38 | } |
90 | 39 | ||
91 | __le16 mac802154_dev_get_short_addr(const struct net_device *dev) | 40 | __le16 mac802154_dev_get_short_addr(const struct net_device *dev) |
@@ -102,20 +51,6 @@ __le16 mac802154_dev_get_short_addr(const struct net_device *dev) | |||
102 | return ret; | 51 | return ret; |
103 | } | 52 | } |
104 | 53 | ||
105 | void mac802154_dev_set_ieee_addr(struct net_device *dev) | ||
106 | { | ||
107 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | ||
108 | struct ieee802154_local *local = sdata->local; | ||
109 | |||
110 | sdata->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr); | ||
111 | |||
112 | if (local->ops->set_hw_addr_filt && | ||
113 | local->hw.hw_filt.ieee_addr != sdata->extended_addr) { | ||
114 | local->hw.hw_filt.ieee_addr = sdata->extended_addr; | ||
115 | set_hw_addr_filt(dev, IEEE802154_AFILT_IEEEADDR_CHANGED); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | __le16 mac802154_dev_get_pan_id(const struct net_device *dev) | 54 | __le16 mac802154_dev_get_pan_id(const struct net_device *dev) |
120 | { | 55 | { |
121 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); | 56 | struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); |
@@ -139,12 +74,6 @@ void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val) | |||
139 | spin_lock_bh(&sdata->mib_lock); | 74 | spin_lock_bh(&sdata->mib_lock); |
140 | sdata->pan_id = val; | 75 | sdata->pan_id = val; |
141 | spin_unlock_bh(&sdata->mib_lock); | 76 | spin_unlock_bh(&sdata->mib_lock); |
142 | |||
143 | if ((sdata->local->ops->set_hw_addr_filt) && | ||
144 | (sdata->local->hw.hw_filt.pan_id != sdata->pan_id)) { | ||
145 | sdata->local->hw.hw_filt.pan_id = sdata->pan_id; | ||
146 | set_hw_addr_filt(dev, IEEE802154_AFILT_PANID_CHANGED); | ||
147 | } | ||
148 | } | 77 | } |
149 | 78 | ||
150 | u8 mac802154_dev_get_dsn(const struct net_device *dev) | 79 | u8 mac802154_dev_get_dsn(const struct net_device *dev) |
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c index 95961cccc253..4b54cf33e562 100644 --- a/net/mac802154/rx.c +++ b/net/mac802154/rx.c | |||
@@ -208,7 +208,7 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local, | |||
208 | } | 208 | } |
209 | 209 | ||
210 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 210 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
211 | if (sdata->type != IEEE802154_DEV_WPAN || | 211 | if (sdata->vif.type != IEEE802154_DEV_WPAN || |
212 | !netif_running(sdata->dev)) | 212 | !netif_running(sdata->dev)) |
213 | continue; | 213 | continue; |
214 | 214 | ||
@@ -233,7 +233,7 @@ ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb) | |||
233 | skb->protocol = htons(ETH_P_IEEE802154); | 233 | skb->protocol = htons(ETH_P_IEEE802154); |
234 | 234 | ||
235 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 235 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
236 | if (sdata->type != IEEE802154_DEV_MONITOR) | 236 | if (sdata->vif.type != IEEE802154_DEV_MONITOR) |
237 | continue; | 237 | continue; |
238 | 238 | ||
239 | if (!ieee802154_sdata_running(sdata)) | 239 | if (!ieee802154_sdata_running(sdata)) |