aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r--drivers/net/wireless/libertas/main.c216
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
566static int lbs_copy_multicast_address(struct lbs_private *priv, 572
567 struct net_device *dev) 573static 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
586static 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
579static void lbs_set_multicast_list(struct net_device *dev) 618static 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
675static 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