diff options
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 216 |
1 files changed, 131 insertions, 85 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 02e4fb639428..b7ab3590b586 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/if_arp.h> | 11 | #include <linux/if_arp.h> |
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include <linux/kfifo.h> | 13 | #include <linux/kfifo.h> |
14 | #include <linux/stddef.h> | ||
14 | 15 | ||
15 | #include <net/iw_handler.h> | 16 | #include <net/iw_handler.h> |
16 | #include <net/ieee80211.h> | 17 | #include <net/ieee80211.h> |
@@ -343,14 +344,15 @@ static ssize_t lbs_mesh_set(struct device *dev, | |||
343 | { | 344 | { |
344 | struct lbs_private *priv = to_net_dev(dev)->priv; | 345 | struct lbs_private *priv = to_net_dev(dev)->priv; |
345 | int enable; | 346 | int enable; |
346 | int ret; | 347 | int ret, action = CMD_ACT_MESH_CONFIG_STOP; |
347 | 348 | ||
348 | sscanf(buf, "%x", &enable); | 349 | sscanf(buf, "%x", &enable); |
349 | enable = !!enable; | 350 | enable = !!enable; |
350 | if (enable == !!priv->mesh_dev) | 351 | if (enable == !!priv->mesh_dev) |
351 | return count; | 352 | return count; |
352 | 353 | if (enable) | |
353 | ret = lbs_mesh_config(priv, enable, priv->curbssparams.channel); | 354 | action = CMD_ACT_MESH_CONFIG_START; |
355 | ret = lbs_mesh_config(priv, action, priv->curbssparams.channel); | ||
354 | if (ret) | 356 | if (ret) |
355 | return ret; | 357 | return ret; |
356 | 358 | ||
@@ -446,6 +448,8 @@ static int lbs_mesh_stop(struct net_device *dev) | |||
446 | 448 | ||
447 | spin_unlock_irq(&priv->driver_lock); | 449 | spin_unlock_irq(&priv->driver_lock); |
448 | 450 | ||
451 | schedule_work(&priv->mcast_work); | ||
452 | |||
449 | lbs_deb_leave(LBS_DEB_MESH); | 453 | lbs_deb_leave(LBS_DEB_MESH); |
450 | return 0; | 454 | return 0; |
451 | } | 455 | } |
@@ -467,6 +471,8 @@ static int lbs_eth_stop(struct net_device *dev) | |||
467 | netif_stop_queue(dev); | 471 | netif_stop_queue(dev); |
468 | spin_unlock_irq(&priv->driver_lock); | 472 | spin_unlock_irq(&priv->driver_lock); |
469 | 473 | ||
474 | schedule_work(&priv->mcast_work); | ||
475 | |||
470 | lbs_deb_leave(LBS_DEB_NET); | 476 | lbs_deb_leave(LBS_DEB_NET); |
471 | return 0; | 477 | return 0; |
472 | } | 478 | } |
@@ -563,89 +569,116 @@ done: | |||
563 | return ret; | 569 | return ret; |
564 | } | 570 | } |
565 | 571 | ||
566 | static int lbs_copy_multicast_address(struct lbs_private *priv, | 572 | |
567 | struct net_device *dev) | 573 | static inline int mac_in_list(unsigned char *list, int list_len, |
574 | unsigned char *mac) | ||
568 | { | 575 | { |
569 | int i = 0; | 576 | while (list_len) { |
570 | struct dev_mc_list *mcptr = dev->mc_list; | 577 | if (!memcmp(list, mac, ETH_ALEN)) |
578 | return 1; | ||
579 | list += ETH_ALEN; | ||
580 | list_len--; | ||
581 | } | ||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | |||
586 | static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, | ||
587 | struct net_device *dev, int nr_addrs) | ||
588 | { | ||
589 | int i = nr_addrs; | ||
590 | struct dev_mc_list *mc_list; | ||
591 | DECLARE_MAC_BUF(mac); | ||
592 | |||
593 | if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) | ||
594 | return nr_addrs; | ||
595 | |||
596 | netif_tx_lock_bh(dev); | ||
597 | for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) { | ||
598 | if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { | ||
599 | lbs_deb_net("mcast address %s:%s skipped\n", dev->name, | ||
600 | print_mac(mac, mc_list->dmi_addr)); | ||
601 | continue; | ||
602 | } | ||
571 | 603 | ||
572 | for (i = 0; i < dev->mc_count; i++) { | 604 | if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE) |
573 | memcpy(&priv->multicastlist[i], mcptr->dmi_addr, ETH_ALEN); | 605 | break; |
574 | mcptr = mcptr->next; | 606 | memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN); |
607 | lbs_deb_net("mcast address %s:%s added to filter\n", dev->name, | ||
608 | print_mac(mac, mc_list->dmi_addr)); | ||
609 | i++; | ||
575 | } | 610 | } |
611 | netif_tx_unlock_bh(dev); | ||
612 | if (mc_list) | ||
613 | return -EOVERFLOW; | ||
614 | |||
576 | return i; | 615 | return i; |
577 | } | 616 | } |
578 | 617 | ||
579 | static void lbs_set_multicast_list(struct net_device *dev) | 618 | static void lbs_set_mcast_worker(struct work_struct *work) |
580 | { | 619 | { |
581 | struct lbs_private *priv = dev->priv; | 620 | struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work); |
582 | int old_mac_control; | 621 | struct cmd_ds_mac_multicast_adr mcast_cmd; |
583 | DECLARE_MAC_BUF(mac); | 622 | int dev_flags; |
623 | int nr_addrs; | ||
624 | int old_mac_control = priv->mac_control; | ||
584 | 625 | ||
585 | lbs_deb_enter(LBS_DEB_NET); | 626 | lbs_deb_enter(LBS_DEB_NET); |
586 | 627 | ||
587 | old_mac_control = priv->mac_control; | 628 | dev_flags = priv->dev->flags; |
588 | 629 | if (priv->mesh_dev) | |
589 | if (dev->flags & IFF_PROMISC) { | 630 | dev_flags |= priv->mesh_dev->flags; |
590 | lbs_deb_net("enable promiscuous mode\n"); | 631 | |
591 | priv->mac_control |= | 632 | if (dev_flags & IFF_PROMISC) { |
592 | CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 633 | priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; |
593 | priv->mac_control &= | 634 | priv->mac_control &= ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | |
594 | ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | | 635 | CMD_ACT_MAC_MULTICAST_ENABLE); |
595 | CMD_ACT_MAC_MULTICAST_ENABLE); | 636 | goto out_set_mac_control; |
596 | } else { | 637 | } else if (dev_flags & IFF_ALLMULTI) { |
597 | /* Multicast */ | 638 | do_allmulti: |
598 | priv->mac_control &= | 639 | priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
599 | ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 640 | priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | |
600 | 641 | CMD_ACT_MAC_MULTICAST_ENABLE); | |
601 | if (dev->flags & IFF_ALLMULTI || dev->mc_count > | 642 | goto out_set_mac_control; |
602 | MRVDRV_MAX_MULTICAST_LIST_SIZE) { | ||
603 | lbs_deb_net( "enabling all multicast\n"); | ||
604 | priv->mac_control |= | ||
605 | CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | ||
606 | priv->mac_control &= | ||
607 | ~CMD_ACT_MAC_MULTICAST_ENABLE; | ||
608 | } else { | ||
609 | priv->mac_control &= | ||
610 | ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | ||
611 | |||
612 | if (!dev->mc_count) { | ||
613 | lbs_deb_net("no multicast addresses, " | ||
614 | "disabling multicast\n"); | ||
615 | priv->mac_control &= | ||
616 | ~CMD_ACT_MAC_MULTICAST_ENABLE; | ||
617 | } else { | ||
618 | int i; | ||
619 | |||
620 | priv->mac_control |= | ||
621 | CMD_ACT_MAC_MULTICAST_ENABLE; | ||
622 | |||
623 | priv->nr_of_multicastmacaddr = | ||
624 | lbs_copy_multicast_address(priv, dev); | ||
625 | |||
626 | lbs_deb_net("multicast addresses: %d\n", | ||
627 | dev->mc_count); | ||
628 | |||
629 | for (i = 0; i < dev->mc_count; i++) { | ||
630 | lbs_deb_net("Multicast address %d: %s\n", | ||
631 | i, print_mac(mac, | ||
632 | priv->multicastlist[i])); | ||
633 | } | ||
634 | /* send multicast addresses to firmware */ | ||
635 | lbs_prepare_and_send_command(priv, | ||
636 | CMD_MAC_MULTICAST_ADR, | ||
637 | CMD_ACT_SET, 0, 0, | ||
638 | NULL); | ||
639 | } | ||
640 | } | ||
641 | } | 643 | } |
642 | 644 | ||
645 | /* Once for priv->dev, again for priv->mesh_dev if it exists */ | ||
646 | nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->dev, 0); | ||
647 | if (nr_addrs >= 0 && priv->mesh_dev) | ||
648 | nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->mesh_dev, nr_addrs); | ||
649 | if (nr_addrs < 0) | ||
650 | goto do_allmulti; | ||
651 | |||
652 | if (nr_addrs) { | ||
653 | int size = offsetof(struct cmd_ds_mac_multicast_adr, | ||
654 | maclist[6*nr_addrs]); | ||
655 | |||
656 | mcast_cmd.action = cpu_to_le16(CMD_ACT_SET); | ||
657 | mcast_cmd.hdr.size = cpu_to_le16(size); | ||
658 | mcast_cmd.nr_of_adrs = cpu_to_le16(nr_addrs); | ||
659 | |||
660 | lbs_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &mcast_cmd.hdr, size); | ||
661 | |||
662 | priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; | ||
663 | } else | ||
664 | priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; | ||
665 | |||
666 | priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | | ||
667 | CMD_ACT_MAC_ALL_MULTICAST_ENABLE); | ||
668 | out_set_mac_control: | ||
643 | if (priv->mac_control != old_mac_control) | 669 | if (priv->mac_control != old_mac_control) |
644 | lbs_set_mac_control(priv); | 670 | lbs_set_mac_control(priv); |
645 | 671 | ||
646 | lbs_deb_leave(LBS_DEB_NET); | 672 | lbs_deb_leave(LBS_DEB_NET); |
647 | } | 673 | } |
648 | 674 | ||
675 | static void lbs_set_multicast_list(struct net_device *dev) | ||
676 | { | ||
677 | struct lbs_private *priv = dev->priv; | ||
678 | |||
679 | schedule_work(&priv->mcast_work); | ||
680 | } | ||
681 | |||
649 | /** | 682 | /** |
650 | * @brief This function handles the major jobs in the LBS driver. | 683 | * @brief This function handles the major jobs in the LBS driver. |
651 | * It handles all events generated by firmware, RX data received | 684 | * It handles all events generated by firmware, RX data received |
@@ -689,14 +722,14 @@ static int lbs_thread(void *data) | |||
689 | shouldsleep = 1; /* Something is en route to the device already */ | 722 | shouldsleep = 1; /* Something is en route to the device already */ |
690 | else if (priv->tx_pending_len > 0) | 723 | else if (priv->tx_pending_len > 0) |
691 | shouldsleep = 0; /* We've a packet to send */ | 724 | shouldsleep = 0; /* We've a packet to send */ |
725 | else if (priv->resp_len[priv->resp_idx]) | ||
726 | shouldsleep = 0; /* We have a command response */ | ||
692 | else if (priv->cur_cmd) | 727 | else if (priv->cur_cmd) |
693 | shouldsleep = 1; /* Can't send a command; one already running */ | 728 | shouldsleep = 1; /* Can't send a command; one already running */ |
694 | else if (!list_empty(&priv->cmdpendingq)) | 729 | else if (!list_empty(&priv->cmdpendingq)) |
695 | shouldsleep = 0; /* We have a command to send */ | 730 | shouldsleep = 0; /* We have a command to send */ |
696 | else if (__kfifo_len(priv->event_fifo)) | 731 | else if (__kfifo_len(priv->event_fifo)) |
697 | shouldsleep = 0; /* We have an event to process */ | 732 | shouldsleep = 0; /* We have an event to process */ |
698 | else if (priv->resp_len[priv->resp_idx]) | ||
699 | shouldsleep = 0; /* We have a command response */ | ||
700 | else | 733 | else |
701 | shouldsleep = 1; /* No command */ | 734 | shouldsleep = 1; /* No command */ |
702 | 735 | ||
@@ -749,16 +782,21 @@ static int lbs_thread(void *data) | |||
749 | if (priv->cmd_timed_out && priv->cur_cmd) { | 782 | if (priv->cmd_timed_out && priv->cur_cmd) { |
750 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | 783 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; |
751 | 784 | ||
752 | if (++priv->nr_retries > 10) { | 785 | if (++priv->nr_retries > 3) { |
753 | lbs_pr_info("Excessive timeouts submitting command %x\n", | 786 | lbs_pr_info("Excessive timeouts submitting " |
754 | le16_to_cpu(cmdnode->cmdbuf->command)); | 787 | "command 0x%04x\n", |
788 | le16_to_cpu(cmdnode->cmdbuf->command)); | ||
755 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); | 789 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); |
756 | priv->nr_retries = 0; | 790 | priv->nr_retries = 0; |
791 | if (priv->reset_card) | ||
792 | priv->reset_card(priv); | ||
757 | } else { | 793 | } else { |
758 | priv->cur_cmd = NULL; | 794 | priv->cur_cmd = NULL; |
759 | priv->dnld_sent = DNLD_RES_RECEIVED; | 795 | priv->dnld_sent = DNLD_RES_RECEIVED; |
760 | lbs_pr_info("requeueing command %x due to timeout (#%d)\n", | 796 | lbs_pr_info("requeueing command 0x%04x due " |
761 | le16_to_cpu(cmdnode->cmdbuf->command), priv->nr_retries); | 797 | "to timeout (#%d)\n", |
798 | le16_to_cpu(cmdnode->cmdbuf->command), | ||
799 | priv->nr_retries); | ||
762 | 800 | ||
763 | /* Stick it back at the _top_ of the pending queue | 801 | /* Stick it back at the _top_ of the pending queue |
764 | for immediate resubmission */ | 802 | for immediate resubmission */ |
@@ -949,12 +987,11 @@ static void command_timer_fn(unsigned long data) | |||
949 | lbs_deb_enter(LBS_DEB_CMD); | 987 | lbs_deb_enter(LBS_DEB_CMD); |
950 | spin_lock_irqsave(&priv->driver_lock, flags); | 988 | spin_lock_irqsave(&priv->driver_lock, flags); |
951 | 989 | ||
952 | if (!priv->cur_cmd) { | 990 | if (!priv->cur_cmd) |
953 | lbs_pr_info("Command timer expired; no pending command\n"); | ||
954 | goto out; | 991 | goto out; |
955 | } | ||
956 | 992 | ||
957 | lbs_pr_info("Command %x timed out\n", le16_to_cpu(priv->cur_cmd->cmdbuf->command)); | 993 | lbs_pr_info("command 0x%04x timed out\n", |
994 | le16_to_cpu(priv->cur_cmd->cmdbuf->command)); | ||
958 | 995 | ||
959 | priv->cmd_timed_out = 1; | 996 | priv->cmd_timed_out = 1; |
960 | wake_up_interruptible(&priv->waitq); | 997 | wake_up_interruptible(&priv->waitq); |
@@ -1008,7 +1045,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1008 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; | 1045 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; |
1009 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 1046 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
1010 | priv->radioon = RADIO_ON; | 1047 | priv->radioon = RADIO_ON; |
1011 | priv->auto_rate = 1; | 1048 | priv->enablehwauto = 1; |
1012 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | 1049 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; |
1013 | priv->psmode = LBS802_11POWERMODECAM; | 1050 | priv->psmode = LBS802_11POWERMODECAM; |
1014 | priv->psstate = PS_STATE_FULL_POWER; | 1051 | priv->psstate = PS_STATE_FULL_POWER; |
@@ -1123,6 +1160,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1123 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); | 1160 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); |
1124 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | 1161 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); |
1125 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 1162 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
1163 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); | ||
1126 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); | 1164 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); |
1127 | 1165 | ||
1128 | sprintf(priv->mesh_ssid, "mesh"); | 1166 | sprintf(priv->mesh_ssid, "mesh"); |
@@ -1159,6 +1197,7 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1159 | 1197 | ||
1160 | cancel_delayed_work_sync(&priv->scan_work); | 1198 | cancel_delayed_work_sync(&priv->scan_work); |
1161 | cancel_delayed_work_sync(&priv->assoc_work); | 1199 | cancel_delayed_work_sync(&priv->assoc_work); |
1200 | cancel_work_sync(&priv->mcast_work); | ||
1162 | destroy_workqueue(priv->work_thread); | 1201 | destroy_workqueue(priv->work_thread); |
1163 | 1202 | ||
1164 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { | 1203 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { |
@@ -1224,9 +1263,11 @@ int lbs_start_card(struct lbs_private *priv) | |||
1224 | useful */ | 1263 | useful */ |
1225 | 1264 | ||
1226 | priv->mesh_tlv = 0x100 + 291; | 1265 | priv->mesh_tlv = 0x100 + 291; |
1227 | if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) { | 1266 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1267 | priv->curbssparams.channel)) { | ||
1228 | priv->mesh_tlv = 0x100 + 37; | 1268 | priv->mesh_tlv = 0x100 + 37; |
1229 | if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) | 1269 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1270 | priv->curbssparams.channel)) | ||
1230 | priv->mesh_tlv = 0; | 1271 | priv->mesh_tlv = 0; |
1231 | } | 1272 | } |
1232 | if (priv->mesh_tlv) { | 1273 | if (priv->mesh_tlv) { |
@@ -1266,8 +1307,9 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1266 | 1307 | ||
1267 | lbs_debugfs_remove_one(priv); | 1308 | lbs_debugfs_remove_one(priv); |
1268 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); | 1309 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); |
1269 | if (priv->mesh_tlv) | 1310 | if (priv->mesh_tlv) { |
1270 | device_remove_file(&dev->dev, &dev_attr_lbs_mesh); | 1311 | device_remove_file(&dev->dev, &dev_attr_lbs_mesh); |
1312 | } | ||
1271 | 1313 | ||
1272 | /* Flush pending command nodes */ | 1314 | /* Flush pending command nodes */ |
1273 | del_timer_sync(&priv->command_timer); | 1315 | del_timer_sync(&priv->command_timer); |
@@ -1323,6 +1365,8 @@ static int lbs_add_mesh(struct lbs_private *priv) | |||
1323 | #ifdef WIRELESS_EXT | 1365 | #ifdef WIRELESS_EXT |
1324 | mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; | 1366 | mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; |
1325 | #endif | 1367 | #endif |
1368 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | ||
1369 | mesh_dev->set_multicast_list = lbs_set_multicast_list; | ||
1326 | /* Register virtual mesh interface */ | 1370 | /* Register virtual mesh interface */ |
1327 | ret = register_netdev(mesh_dev); | 1371 | ret = register_netdev(mesh_dev); |
1328 | if (ret) { | 1372 | if (ret) { |
@@ -1334,6 +1378,8 @@ static int lbs_add_mesh(struct lbs_private *priv) | |||
1334 | if (ret) | 1378 | if (ret) |
1335 | goto err_unregister; | 1379 | goto err_unregister; |
1336 | 1380 | ||
1381 | lbs_persist_config_init(mesh_dev); | ||
1382 | |||
1337 | /* Everything successful */ | 1383 | /* Everything successful */ |
1338 | ret = 0; | 1384 | ret = 0; |
1339 | goto done; | 1385 | goto done; |
@@ -1360,8 +1406,9 @@ static void lbs_remove_mesh(struct lbs_private *priv) | |||
1360 | 1406 | ||
1361 | lbs_deb_enter(LBS_DEB_MESH); | 1407 | lbs_deb_enter(LBS_DEB_MESH); |
1362 | netif_stop_queue(mesh_dev); | 1408 | netif_stop_queue(mesh_dev); |
1363 | netif_carrier_off(priv->mesh_dev); | 1409 | netif_carrier_off(mesh_dev); |
1364 | sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); | 1410 | sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); |
1411 | lbs_persist_config_remove(mesh_dev); | ||
1365 | unregister_netdev(mesh_dev); | 1412 | unregister_netdev(mesh_dev); |
1366 | priv->mesh_dev = NULL; | 1413 | priv->mesh_dev = NULL; |
1367 | free_netdev(mesh_dev); | 1414 | free_netdev(mesh_dev); |
@@ -1555,7 +1602,6 @@ static int lbs_add_rtap(struct lbs_private *priv) | |||
1555 | rtap_dev->stop = lbs_rtap_stop; | 1602 | rtap_dev->stop = lbs_rtap_stop; |
1556 | rtap_dev->get_stats = lbs_rtap_get_stats; | 1603 | rtap_dev->get_stats = lbs_rtap_get_stats; |
1557 | rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit; | 1604 | rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit; |
1558 | rtap_dev->set_multicast_list = lbs_set_multicast_list; | ||
1559 | rtap_dev->priv = priv; | 1605 | rtap_dev->priv = priv; |
1560 | SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent); | 1606 | SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent); |
1561 | 1607 | ||