diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 29 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmdresp.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/hostcmd.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 167 |
5 files changed, 105 insertions, 96 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index bed68e9add02..b494aba869c5 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -746,28 +746,6 @@ out: | |||
746 | return ret; | 746 | return ret; |
747 | } | 747 | } |
748 | 748 | ||
749 | static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv, | ||
750 | struct cmd_ds_command *cmd, | ||
751 | u16 cmd_action) | ||
752 | { | ||
753 | struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr; | ||
754 | |||
755 | lbs_deb_enter(LBS_DEB_CMD); | ||
756 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) + | ||
757 | S_DS_GEN); | ||
758 | cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR); | ||
759 | |||
760 | lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs); | ||
761 | pMCastAdr->action = cpu_to_le16(cmd_action); | ||
762 | pMCastAdr->nr_of_adrs = | ||
763 | cpu_to_le16((u16) priv->nr_of_multicastmacaddr); | ||
764 | memcpy(pMCastAdr->maclist, priv->multicastlist, | ||
765 | priv->nr_of_multicastmacaddr * ETH_ALEN); | ||
766 | |||
767 | lbs_deb_leave(LBS_DEB_CMD); | ||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | /** | 749 | /** |
772 | * @brief Get the radio channel | 750 | * @brief Get the radio channel |
773 | * | 751 | * |
@@ -1247,8 +1225,7 @@ void lbs_set_mac_control(struct lbs_private *priv) | |||
1247 | cmd.action = cpu_to_le16(priv->mac_control); | 1225 | cmd.action = cpu_to_le16(priv->mac_control); |
1248 | cmd.reserved = 0; | 1226 | cmd.reserved = 0; |
1249 | 1227 | ||
1250 | lbs_cmd_async(priv, CMD_MAC_CONTROL, | 1228 | lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd)); |
1251 | &cmd.hdr, sizeof(cmd)); | ||
1252 | 1229 | ||
1253 | lbs_deb_leave(LBS_DEB_CMD); | 1230 | lbs_deb_leave(LBS_DEB_CMD); |
1254 | } | 1231 | } |
@@ -1360,10 +1337,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1360 | cmdptr, cmd_action); | 1337 | cmdptr, cmd_action); |
1361 | break; | 1338 | break; |
1362 | 1339 | ||
1363 | case CMD_MAC_MULTICAST_ADR: | ||
1364 | ret = lbs_cmd_mac_multicast_adr(priv, cmdptr, cmd_action); | ||
1365 | break; | ||
1366 | |||
1367 | case CMD_802_11_MONITOR_MODE: | 1340 | case CMD_802_11_MONITOR_MODE: |
1368 | ret = lbs_cmd_802_11_monitor_mode(cmdptr, | 1341 | ret = lbs_cmd_802_11_monitor_mode(cmdptr, |
1369 | cmd_action, pdata_buf); | 1342 | cmd_action, pdata_buf); |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 9e50fdd94810..4c3c5ec16f98 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -316,7 +316,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
316 | 316 | ||
317 | break; | 317 | break; |
318 | 318 | ||
319 | case CMD_RET(CMD_MAC_MULTICAST_ADR): | ||
320 | case CMD_RET(CMD_802_11_RESET): | 319 | case CMD_RET(CMD_802_11_RESET): |
321 | case CMD_RET(CMD_802_11_AUTHENTICATE): | 320 | case CMD_RET(CMD_802_11_AUTHENTICATE): |
322 | case CMD_RET(CMD_802_11_BEACON_STOP): | 321 | case CMD_RET(CMD_802_11_BEACON_STOP): |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 0d9edb9b11f5..e12ce6506729 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -140,6 +140,8 @@ struct lbs_private { | |||
140 | wait_queue_head_t waitq; | 140 | wait_queue_head_t waitq; |
141 | struct workqueue_struct *work_thread; | 141 | struct workqueue_struct *work_thread; |
142 | 142 | ||
143 | struct work_struct mcast_work; | ||
144 | |||
143 | /** Scanning */ | 145 | /** Scanning */ |
144 | struct delayed_work scan_work; | 146 | struct delayed_work scan_work; |
145 | struct delayed_work assoc_work; | 147 | struct delayed_work assoc_work; |
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index f29bc5bbda3e..c36ab3162238 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h | |||
@@ -219,6 +219,7 @@ struct cmd_ds_mac_control { | |||
219 | }; | 219 | }; |
220 | 220 | ||
221 | struct cmd_ds_mac_multicast_adr { | 221 | struct cmd_ds_mac_multicast_adr { |
222 | struct cmd_header hdr; | ||
222 | __le16 action; | 223 | __le16 action; |
223 | __le16 nr_of_adrs; | 224 | __le16 nr_of_adrs; |
224 | u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; | 225 | u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; |
@@ -703,7 +704,6 @@ struct cmd_ds_command { | |||
703 | struct cmd_ds_802_11_rf_antenna rant; | 704 | struct cmd_ds_802_11_rf_antenna rant; |
704 | struct cmd_ds_802_11_monitor_mode monitor; | 705 | struct cmd_ds_802_11_monitor_mode monitor; |
705 | struct cmd_ds_802_11_rate_adapt_rateset rateset; | 706 | struct cmd_ds_802_11_rate_adapt_rateset rateset; |
706 | struct cmd_ds_mac_multicast_adr madr; | ||
707 | struct cmd_ds_802_11_ad_hoc_join adj; | 707 | struct cmd_ds_802_11_ad_hoc_join adj; |
708 | struct cmd_ds_802_11_rssi rssi; | 708 | struct cmd_ds_802_11_rssi rssi; |
709 | struct cmd_ds_802_11_rssi_rsp rssirsp; | 709 | struct cmd_ds_802_11_rssi_rsp rssirsp; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index e333f14dce23..a87febad8c29 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> |
@@ -446,6 +447,8 @@ static int lbs_mesh_stop(struct net_device *dev) | |||
446 | 447 | ||
447 | spin_unlock_irq(&priv->driver_lock); | 448 | spin_unlock_irq(&priv->driver_lock); |
448 | 449 | ||
450 | schedule_work(&priv->mcast_work); | ||
451 | |||
449 | lbs_deb_leave(LBS_DEB_MESH); | 452 | lbs_deb_leave(LBS_DEB_MESH); |
450 | return 0; | 453 | return 0; |
451 | } | 454 | } |
@@ -467,6 +470,8 @@ static int lbs_eth_stop(struct net_device *dev) | |||
467 | netif_stop_queue(dev); | 470 | netif_stop_queue(dev); |
468 | spin_unlock_irq(&priv->driver_lock); | 471 | spin_unlock_irq(&priv->driver_lock); |
469 | 472 | ||
473 | schedule_work(&priv->mcast_work); | ||
474 | |||
470 | lbs_deb_leave(LBS_DEB_NET); | 475 | lbs_deb_leave(LBS_DEB_NET); |
471 | return 0; | 476 | return 0; |
472 | } | 477 | } |
@@ -563,89 +568,116 @@ done: | |||
563 | return ret; | 568 | return ret; |
564 | } | 569 | } |
565 | 570 | ||
566 | static int lbs_copy_multicast_address(struct lbs_private *priv, | 571 | |
567 | struct net_device *dev) | 572 | static inline int mac_in_list(unsigned char *list, int list_len, |
573 | unsigned char *mac) | ||
568 | { | 574 | { |
569 | int i = 0; | 575 | while (list_len) { |
570 | struct dev_mc_list *mcptr = dev->mc_list; | 576 | if (!memcmp(list, mac, ETH_ALEN)) |
577 | return 1; | ||
578 | list += ETH_ALEN; | ||
579 | list_len--; | ||
580 | } | ||
581 | return 0; | ||
582 | } | ||
583 | |||
571 | 584 | ||
572 | for (i = 0; i < dev->mc_count; i++) { | 585 | static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, |
573 | memcpy(&priv->multicastlist[i], mcptr->dmi_addr, ETH_ALEN); | 586 | struct net_device *dev, int nr_addrs) |
574 | mcptr = mcptr->next; | 587 | { |
588 | int i = nr_addrs; | ||
589 | struct dev_mc_list *mc_list; | ||
590 | DECLARE_MAC_BUF(mac); | ||
591 | |||
592 | if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) | ||
593 | return nr_addrs; | ||
594 | |||
595 | netif_tx_lock_bh(dev); | ||
596 | for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) { | ||
597 | if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { | ||
598 | lbs_deb_net("mcast address %s:%s skipped\n", dev->name, | ||
599 | print_mac(mac, mc_list->dmi_addr)); | ||
600 | continue; | ||
601 | } | ||
602 | |||
603 | if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE) | ||
604 | break; | ||
605 | memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN); | ||
606 | lbs_deb_net("mcast address %s:%s added to filter\n", dev->name, | ||
607 | print_mac(mac, mc_list->dmi_addr)); | ||
608 | i++; | ||
575 | } | 609 | } |
610 | netif_tx_unlock_bh(dev); | ||
611 | if (mc_list) | ||
612 | return -EOVERFLOW; | ||
613 | |||
576 | return i; | 614 | return i; |
577 | } | 615 | } |
578 | 616 | ||
579 | static void lbs_set_multicast_list(struct net_device *dev) | 617 | static void lbs_set_mcast_worker(struct work_struct *work) |
580 | { | 618 | { |
581 | struct lbs_private *priv = dev->priv; | 619 | struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work); |
582 | int old_mac_control; | 620 | struct cmd_ds_mac_multicast_adr mcast_cmd; |
583 | DECLARE_MAC_BUF(mac); | 621 | int dev_flags; |
622 | int nr_addrs; | ||
623 | int old_mac_control = priv->mac_control; | ||
584 | 624 | ||
585 | lbs_deb_enter(LBS_DEB_NET); | 625 | lbs_deb_enter(LBS_DEB_NET); |
586 | 626 | ||
587 | old_mac_control = priv->mac_control; | 627 | dev_flags = priv->dev->flags; |
588 | 628 | if (priv->mesh_dev) | |
589 | if (dev->flags & IFF_PROMISC) { | 629 | dev_flags |= priv->mesh_dev->flags; |
590 | lbs_deb_net("enable promiscuous mode\n"); | 630 | |
591 | priv->mac_control |= | 631 | if (dev_flags & IFF_PROMISC) { |
592 | CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 632 | priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; |
593 | priv->mac_control &= | 633 | priv->mac_control &= ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | |
594 | ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | | 634 | CMD_ACT_MAC_MULTICAST_ENABLE); |
595 | CMD_ACT_MAC_MULTICAST_ENABLE); | 635 | goto out_set_mac_control; |
596 | } else { | 636 | } else if (dev_flags & IFF_ALLMULTI) { |
597 | /* Multicast */ | 637 | do_allmulti: |
598 | priv->mac_control &= | 638 | priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
599 | ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 639 | priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | |
600 | 640 | CMD_ACT_MAC_MULTICAST_ENABLE); | |
601 | if (dev->flags & IFF_ALLMULTI || dev->mc_count > | 641 | 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 | } | 642 | } |
642 | 643 | ||
644 | /* Once for priv->dev, again for priv->mesh_dev if it exists */ | ||
645 | nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->dev, 0); | ||
646 | if (nr_addrs >= 0 && priv->mesh_dev) | ||
647 | nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->mesh_dev, nr_addrs); | ||
648 | if (nr_addrs < 0) | ||
649 | goto do_allmulti; | ||
650 | |||
651 | if (nr_addrs) { | ||
652 | int size = offsetof(struct cmd_ds_mac_multicast_adr, | ||
653 | maclist[6*nr_addrs]); | ||
654 | |||
655 | mcast_cmd.action = cpu_to_le16(CMD_ACT_SET); | ||
656 | mcast_cmd.hdr.size = cpu_to_le16(size); | ||
657 | mcast_cmd.nr_of_adrs = cpu_to_le16(nr_addrs); | ||
658 | |||
659 | lbs_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &mcast_cmd.hdr, size); | ||
660 | |||
661 | priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; | ||
662 | } else | ||
663 | priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; | ||
664 | |||
665 | priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | | ||
666 | CMD_ACT_MAC_ALL_MULTICAST_ENABLE); | ||
667 | out_set_mac_control: | ||
643 | if (priv->mac_control != old_mac_control) | 668 | if (priv->mac_control != old_mac_control) |
644 | lbs_set_mac_control(priv); | 669 | lbs_set_mac_control(priv); |
645 | 670 | ||
646 | lbs_deb_leave(LBS_DEB_NET); | 671 | lbs_deb_leave(LBS_DEB_NET); |
647 | } | 672 | } |
648 | 673 | ||
674 | static void lbs_set_multicast_list(struct net_device *dev) | ||
675 | { | ||
676 | struct lbs_private *priv = dev->priv; | ||
677 | |||
678 | schedule_work(&priv->mcast_work); | ||
679 | } | ||
680 | |||
649 | /** | 681 | /** |
650 | * @brief This function handles the major jobs in the LBS driver. | 682 | * @brief This function handles the major jobs in the LBS driver. |
651 | * It handles all events generated by firmware, RX data received | 683 | * It handles all events generated by firmware, RX data received |
@@ -1122,6 +1154,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1122 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); | 1154 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); |
1123 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | 1155 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); |
1124 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 1156 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
1157 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); | ||
1125 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); | 1158 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); |
1126 | 1159 | ||
1127 | sprintf(priv->mesh_ssid, "mesh"); | 1160 | sprintf(priv->mesh_ssid, "mesh"); |
@@ -1158,6 +1191,7 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1158 | 1191 | ||
1159 | cancel_delayed_work_sync(&priv->scan_work); | 1192 | cancel_delayed_work_sync(&priv->scan_work); |
1160 | cancel_delayed_work_sync(&priv->assoc_work); | 1193 | cancel_delayed_work_sync(&priv->assoc_work); |
1194 | cancel_work_sync(&priv->mcast_work); | ||
1161 | destroy_workqueue(priv->work_thread); | 1195 | destroy_workqueue(priv->work_thread); |
1162 | 1196 | ||
1163 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { | 1197 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { |
@@ -1322,6 +1356,8 @@ static int lbs_add_mesh(struct lbs_private *priv) | |||
1322 | #ifdef WIRELESS_EXT | 1356 | #ifdef WIRELESS_EXT |
1323 | mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; | 1357 | mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; |
1324 | #endif | 1358 | #endif |
1359 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | ||
1360 | mesh_dev->set_multicast_list = lbs_set_multicast_list; | ||
1325 | /* Register virtual mesh interface */ | 1361 | /* Register virtual mesh interface */ |
1326 | ret = register_netdev(mesh_dev); | 1362 | ret = register_netdev(mesh_dev); |
1327 | if (ret) { | 1363 | if (ret) { |
@@ -1554,7 +1590,6 @@ static int lbs_add_rtap(struct lbs_private *priv) | |||
1554 | rtap_dev->stop = lbs_rtap_stop; | 1590 | rtap_dev->stop = lbs_rtap_stop; |
1555 | rtap_dev->get_stats = lbs_rtap_get_stats; | 1591 | rtap_dev->get_stats = lbs_rtap_get_stats; |
1556 | rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit; | 1592 | rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit; |
1557 | rtap_dev->set_multicast_list = lbs_set_multicast_list; | ||
1558 | rtap_dev->priv = priv; | 1593 | rtap_dev->priv = priv; |
1559 | 1594 | ||
1560 | ret = register_netdev(rtap_dev); | 1595 | ret = register_netdev(rtap_dev); |