diff options
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 289 |
1 files changed, 169 insertions, 120 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 4d4e2f3b66ac..406f54d40956 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
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 | 14 | ||
14 | #include <net/iw_handler.h> | 15 | #include <net/iw_handler.h> |
15 | #include <net/ieee80211.h> | 16 | #include <net/ieee80211.h> |
@@ -19,8 +20,8 @@ | |||
19 | #include "dev.h" | 20 | #include "dev.h" |
20 | #include "wext.h" | 21 | #include "wext.h" |
21 | #include "debugfs.h" | 22 | #include "debugfs.h" |
23 | #include "scan.h" | ||
22 | #include "assoc.h" | 24 | #include "assoc.h" |
23 | #include "join.h" | ||
24 | #include "cmd.h" | 25 | #include "cmd.h" |
25 | 26 | ||
26 | #define DRIVER_RELEASE_VERSION "323.p0" | 27 | #define DRIVER_RELEASE_VERSION "323.p0" |
@@ -37,6 +38,11 @@ EXPORT_SYMBOL_GPL(lbs_debug); | |||
37 | module_param_named(libertas_debug, lbs_debug, int, 0644); | 38 | module_param_named(libertas_debug, lbs_debug, int, 0644); |
38 | 39 | ||
39 | 40 | ||
41 | /* This global structure is used to send the confirm_sleep command as | ||
42 | * fast as possible down to the firmware. */ | ||
43 | struct cmd_confirm_sleep confirm_sleep; | ||
44 | |||
45 | |||
40 | #define LBS_TX_PWR_DEFAULT 20 /*100mW */ | 46 | #define LBS_TX_PWR_DEFAULT 20 /*100mW */ |
41 | #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ | 47 | #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ |
42 | #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ | 48 | #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ |
@@ -277,10 +283,10 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
277 | struct lbs_private *priv = to_net_dev(dev)->priv; | 283 | struct lbs_private *priv = to_net_dev(dev)->priv; |
278 | 284 | ||
279 | sscanf(buf, "%x", &monitor_mode); | 285 | sscanf(buf, "%x", &monitor_mode); |
280 | if (monitor_mode != LBS_MONITOR_OFF) { | 286 | if (monitor_mode) { |
281 | if(priv->monitormode == monitor_mode) | 287 | if (priv->monitormode == monitor_mode) |
282 | return strlen(buf); | 288 | return strlen(buf); |
283 | if (priv->monitormode == LBS_MONITOR_OFF) { | 289 | if (!priv->monitormode) { |
284 | if (priv->infra_open || priv->mesh_open) | 290 | if (priv->infra_open || priv->mesh_open) |
285 | return -EBUSY; | 291 | return -EBUSY; |
286 | if (priv->mode == IW_MODE_INFRA) | 292 | if (priv->mode == IW_MODE_INFRA) |
@@ -293,9 +299,9 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
293 | } | 299 | } |
294 | 300 | ||
295 | else { | 301 | else { |
296 | if (priv->monitormode == LBS_MONITOR_OFF) | 302 | if (!priv->monitormode) |
297 | return strlen(buf); | 303 | return strlen(buf); |
298 | priv->monitormode = LBS_MONITOR_OFF; | 304 | priv->monitormode = 0; |
299 | lbs_remove_rtap(priv); | 305 | lbs_remove_rtap(priv); |
300 | 306 | ||
301 | if (priv->currenttxskb) { | 307 | if (priv->currenttxskb) { |
@@ -392,7 +398,7 @@ static int lbs_dev_open(struct net_device *dev) | |||
392 | 398 | ||
393 | spin_lock_irq(&priv->driver_lock); | 399 | spin_lock_irq(&priv->driver_lock); |
394 | 400 | ||
395 | if (priv->monitormode != LBS_MONITOR_OFF) { | 401 | if (priv->monitormode) { |
396 | ret = -EBUSY; | 402 | ret = -EBUSY; |
397 | goto out; | 403 | goto out; |
398 | } | 404 | } |
@@ -475,10 +481,9 @@ static void lbs_tx_timeout(struct net_device *dev) | |||
475 | 481 | ||
476 | dev->trans_start = jiffies; | 482 | dev->trans_start = jiffies; |
477 | 483 | ||
478 | if (priv->currenttxskb) { | 484 | if (priv->currenttxskb) |
479 | priv->eventcause = 0x01000000; | 485 | lbs_send_tx_feedback(priv, 0); |
480 | lbs_send_tx_feedback(priv); | 486 | |
481 | } | ||
482 | /* XX: Shouldn't we also call into the hw-specific driver | 487 | /* XX: Shouldn't we also call into the hw-specific driver |
483 | to kick it somehow? */ | 488 | to kick it somehow? */ |
484 | lbs_host_to_card_done(priv); | 489 | lbs_host_to_card_done(priv); |
@@ -531,34 +536,27 @@ static int lbs_set_mac_address(struct net_device *dev, void *addr) | |||
531 | int ret = 0; | 536 | int ret = 0; |
532 | struct lbs_private *priv = (struct lbs_private *) dev->priv; | 537 | struct lbs_private *priv = (struct lbs_private *) dev->priv; |
533 | struct sockaddr *phwaddr = addr; | 538 | struct sockaddr *phwaddr = addr; |
539 | struct cmd_ds_802_11_mac_address cmd; | ||
534 | 540 | ||
535 | lbs_deb_enter(LBS_DEB_NET); | 541 | lbs_deb_enter(LBS_DEB_NET); |
536 | 542 | ||
537 | /* In case it was called from the mesh device */ | 543 | /* In case it was called from the mesh device */ |
538 | dev = priv->dev ; | 544 | dev = priv->dev; |
539 | |||
540 | memset(priv->current_addr, 0, ETH_ALEN); | ||
541 | |||
542 | /* dev->dev_addr is 8 bytes */ | ||
543 | lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN); | ||
544 | |||
545 | lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN); | ||
546 | memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN); | ||
547 | 545 | ||
548 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS, | 546 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
549 | CMD_ACT_SET, | 547 | cmd.action = cpu_to_le16(CMD_ACT_SET); |
550 | CMD_OPTION_WAITFORRSP, 0, NULL); | 548 | memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN); |
551 | 549 | ||
550 | ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd); | ||
552 | if (ret) { | 551 | if (ret) { |
553 | lbs_deb_net("set MAC address failed\n"); | 552 | lbs_deb_net("set MAC address failed\n"); |
554 | ret = -1; | ||
555 | goto done; | 553 | goto done; |
556 | } | 554 | } |
557 | 555 | ||
558 | lbs_deb_hex(LBS_DEB_NET, "priv->macaddr", priv->current_addr, ETH_ALEN); | 556 | memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN); |
559 | memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN); | 557 | memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN); |
560 | if (priv->mesh_dev) | 558 | if (priv->mesh_dev) |
561 | memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); | 559 | memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN); |
562 | 560 | ||
563 | done: | 561 | done: |
564 | lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); | 562 | lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); |
@@ -581,45 +579,45 @@ static int lbs_copy_multicast_address(struct lbs_private *priv, | |||
581 | static void lbs_set_multicast_list(struct net_device *dev) | 579 | static void lbs_set_multicast_list(struct net_device *dev) |
582 | { | 580 | { |
583 | struct lbs_private *priv = dev->priv; | 581 | struct lbs_private *priv = dev->priv; |
584 | int oldpacketfilter; | 582 | int old_mac_control; |
585 | DECLARE_MAC_BUF(mac); | 583 | DECLARE_MAC_BUF(mac); |
586 | 584 | ||
587 | lbs_deb_enter(LBS_DEB_NET); | 585 | lbs_deb_enter(LBS_DEB_NET); |
588 | 586 | ||
589 | oldpacketfilter = priv->currentpacketfilter; | 587 | old_mac_control = priv->mac_control; |
590 | 588 | ||
591 | if (dev->flags & IFF_PROMISC) { | 589 | if (dev->flags & IFF_PROMISC) { |
592 | lbs_deb_net("enable promiscuous mode\n"); | 590 | lbs_deb_net("enable promiscuous mode\n"); |
593 | priv->currentpacketfilter |= | 591 | priv->mac_control |= |
594 | CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 592 | CMD_ACT_MAC_PROMISCUOUS_ENABLE; |
595 | priv->currentpacketfilter &= | 593 | priv->mac_control &= |
596 | ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | | 594 | ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | |
597 | CMD_ACT_MAC_MULTICAST_ENABLE); | 595 | CMD_ACT_MAC_MULTICAST_ENABLE); |
598 | } else { | 596 | } else { |
599 | /* Multicast */ | 597 | /* Multicast */ |
600 | priv->currentpacketfilter &= | 598 | priv->mac_control &= |
601 | ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 599 | ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; |
602 | 600 | ||
603 | if (dev->flags & IFF_ALLMULTI || dev->mc_count > | 601 | if (dev->flags & IFF_ALLMULTI || dev->mc_count > |
604 | MRVDRV_MAX_MULTICAST_LIST_SIZE) { | 602 | MRVDRV_MAX_MULTICAST_LIST_SIZE) { |
605 | lbs_deb_net( "enabling all multicast\n"); | 603 | lbs_deb_net( "enabling all multicast\n"); |
606 | priv->currentpacketfilter |= | 604 | priv->mac_control |= |
607 | CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | 605 | CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
608 | priv->currentpacketfilter &= | 606 | priv->mac_control &= |
609 | ~CMD_ACT_MAC_MULTICAST_ENABLE; | 607 | ~CMD_ACT_MAC_MULTICAST_ENABLE; |
610 | } else { | 608 | } else { |
611 | priv->currentpacketfilter &= | 609 | priv->mac_control &= |
612 | ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | 610 | ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
613 | 611 | ||
614 | if (!dev->mc_count) { | 612 | if (!dev->mc_count) { |
615 | lbs_deb_net("no multicast addresses, " | 613 | lbs_deb_net("no multicast addresses, " |
616 | "disabling multicast\n"); | 614 | "disabling multicast\n"); |
617 | priv->currentpacketfilter &= | 615 | priv->mac_control &= |
618 | ~CMD_ACT_MAC_MULTICAST_ENABLE; | 616 | ~CMD_ACT_MAC_MULTICAST_ENABLE; |
619 | } else { | 617 | } else { |
620 | int i; | 618 | int i; |
621 | 619 | ||
622 | priv->currentpacketfilter |= | 620 | priv->mac_control |= |
623 | CMD_ACT_MAC_MULTICAST_ENABLE; | 621 | CMD_ACT_MAC_MULTICAST_ENABLE; |
624 | 622 | ||
625 | priv->nr_of_multicastmacaddr = | 623 | priv->nr_of_multicastmacaddr = |
@@ -642,9 +640,8 @@ static void lbs_set_multicast_list(struct net_device *dev) | |||
642 | } | 640 | } |
643 | } | 641 | } |
644 | 642 | ||
645 | if (priv->currentpacketfilter != oldpacketfilter) { | 643 | if (priv->mac_control != old_mac_control) |
646 | lbs_set_mac_packet_filter(priv); | 644 | lbs_set_mac_control(priv); |
647 | } | ||
648 | 645 | ||
649 | lbs_deb_leave(LBS_DEB_NET); | 646 | lbs_deb_leave(LBS_DEB_NET); |
650 | } | 647 | } |
@@ -662,7 +659,6 @@ static int lbs_thread(void *data) | |||
662 | struct net_device *dev = data; | 659 | struct net_device *dev = data; |
663 | struct lbs_private *priv = dev->priv; | 660 | struct lbs_private *priv = dev->priv; |
664 | wait_queue_t wait; | 661 | wait_queue_t wait; |
665 | u8 ireg = 0; | ||
666 | 662 | ||
667 | lbs_deb_enter(LBS_DEB_THREAD); | 663 | lbs_deb_enter(LBS_DEB_THREAD); |
668 | 664 | ||
@@ -670,9 +666,10 @@ static int lbs_thread(void *data) | |||
670 | 666 | ||
671 | for (;;) { | 667 | for (;;) { |
672 | int shouldsleep; | 668 | int shouldsleep; |
669 | u8 resp_idx; | ||
673 | 670 | ||
674 | lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 671 | lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n", |
675 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 672 | priv->currenttxskb, priv->dnld_sent); |
676 | 673 | ||
677 | add_wait_queue(&priv->waitq, &wait); | 674 | add_wait_queue(&priv->waitq, &wait); |
678 | set_current_state(TASK_INTERRUPTIBLE); | 675 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -684,8 +681,6 @@ static int lbs_thread(void *data) | |||
684 | shouldsleep = 1; /* We need to wait until we're _told_ to die */ | 681 | shouldsleep = 1; /* We need to wait until we're _told_ to die */ |
685 | else if (priv->psstate == PS_STATE_SLEEP) | 682 | else if (priv->psstate == PS_STATE_SLEEP) |
686 | shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ | 683 | shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ |
687 | else if (priv->intcounter) | ||
688 | shouldsleep = 0; /* Interrupt pending. Deal with it now */ | ||
689 | else if (priv->cmd_timed_out) | 684 | else if (priv->cmd_timed_out) |
690 | shouldsleep = 0; /* Command timed out. Recover */ | 685 | shouldsleep = 0; /* Command timed out. Recover */ |
691 | else if (!priv->fw_ready) | 686 | else if (!priv->fw_ready) |
@@ -698,29 +693,34 @@ static int lbs_thread(void *data) | |||
698 | shouldsleep = 1; /* Can't send a command; one already running */ | 693 | shouldsleep = 1; /* Can't send a command; one already running */ |
699 | else if (!list_empty(&priv->cmdpendingq)) | 694 | else if (!list_empty(&priv->cmdpendingq)) |
700 | shouldsleep = 0; /* We have a command to send */ | 695 | shouldsleep = 0; /* We have a command to send */ |
696 | else if (__kfifo_len(priv->event_fifo)) | ||
697 | 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 */ | ||
701 | else | 700 | else |
702 | shouldsleep = 1; /* No command */ | 701 | shouldsleep = 1; /* No command */ |
703 | 702 | ||
704 | if (shouldsleep) { | 703 | if (shouldsleep) { |
705 | lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n", | 704 | lbs_deb_thread("sleeping, connect_status %d, " |
706 | priv->connect_status, priv->intcounter, | 705 | "ps_mode %d, ps_state %d\n", |
707 | priv->psmode, priv->psstate); | 706 | priv->connect_status, |
707 | priv->psmode, priv->psstate); | ||
708 | spin_unlock_irq(&priv->driver_lock); | 708 | spin_unlock_irq(&priv->driver_lock); |
709 | schedule(); | 709 | schedule(); |
710 | } else | 710 | } else |
711 | spin_unlock_irq(&priv->driver_lock); | 711 | spin_unlock_irq(&priv->driver_lock); |
712 | 712 | ||
713 | lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 713 | lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n", |
714 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 714 | priv->currenttxskb, priv->dnld_sent); |
715 | 715 | ||
716 | set_current_state(TASK_RUNNING); | 716 | set_current_state(TASK_RUNNING); |
717 | remove_wait_queue(&priv->waitq, &wait); | 717 | remove_wait_queue(&priv->waitq, &wait); |
718 | 718 | ||
719 | lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 719 | lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n", |
720 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 720 | priv->currenttxskb, priv->dnld_sent); |
721 | 721 | ||
722 | if (kthread_should_stop()) { | 722 | if (kthread_should_stop()) { |
723 | lbs_deb_thread("main-thread: break from main thread\n"); | 723 | lbs_deb_thread("break from main thread\n"); |
724 | break; | 724 | break; |
725 | } | 725 | } |
726 | 726 | ||
@@ -729,35 +729,23 @@ static int lbs_thread(void *data) | |||
729 | continue; | 729 | continue; |
730 | } | 730 | } |
731 | 731 | ||
732 | spin_lock_irq(&priv->driver_lock); | 732 | lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", |
733 | 733 | priv->currenttxskb, priv->dnld_sent); | |
734 | if (priv->intcounter) { | ||
735 | u8 int_status; | ||
736 | |||
737 | priv->intcounter = 0; | ||
738 | int_status = priv->hw_get_int_status(priv, &ireg); | ||
739 | |||
740 | if (int_status) { | ||
741 | lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n"); | ||
742 | spin_unlock_irq(&priv->driver_lock); | ||
743 | continue; | ||
744 | } | ||
745 | priv->hisregcpy |= ireg; | ||
746 | } | ||
747 | |||
748 | lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | ||
749 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | ||
750 | 734 | ||
751 | /* command response? */ | 735 | spin_lock_irq(&priv->driver_lock); |
752 | if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) { | 736 | /* Process any pending command response */ |
753 | lbs_deb_thread("main-thread: cmd response ready\n"); | 737 | resp_idx = priv->resp_idx; |
754 | 738 | if (priv->resp_len[resp_idx]) { | |
755 | priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY; | ||
756 | spin_unlock_irq(&priv->driver_lock); | 739 | spin_unlock_irq(&priv->driver_lock); |
757 | lbs_process_rx_command(priv); | 740 | lbs_process_command_response(priv, |
741 | priv->resp_buf[resp_idx], | ||
742 | priv->resp_len[resp_idx]); | ||
758 | spin_lock_irq(&priv->driver_lock); | 743 | spin_lock_irq(&priv->driver_lock); |
744 | priv->resp_len[resp_idx] = 0; | ||
759 | } | 745 | } |
746 | spin_unlock_irq(&priv->driver_lock); | ||
760 | 747 | ||
748 | /* command timeout stuff */ | ||
761 | if (priv->cmd_timed_out && priv->cur_cmd) { | 749 | if (priv->cmd_timed_out && priv->cur_cmd) { |
762 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | 750 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; |
763 | 751 | ||
@@ -778,21 +766,18 @@ static int lbs_thread(void *data) | |||
778 | } | 766 | } |
779 | priv->cmd_timed_out = 0; | 767 | priv->cmd_timed_out = 0; |
780 | 768 | ||
781 | /* Any Card Event */ | 769 | /* Process hardware events, e.g. card removed, link lost */ |
782 | if (priv->hisregcpy & MRVDRV_CARDEVENT) { | 770 | spin_lock_irq(&priv->driver_lock); |
783 | lbs_deb_thread("main-thread: Card Event Activity\n"); | 771 | while (__kfifo_len(priv->event_fifo)) { |
784 | 772 | u32 event; | |
785 | priv->hisregcpy &= ~MRVDRV_CARDEVENT; | ||
786 | 773 | ||
787 | if (priv->hw_read_event_cause(priv)) { | 774 | __kfifo_get(priv->event_fifo, (unsigned char *) &event, |
788 | lbs_pr_alert("main-thread: hw_read_event_cause failed\n"); | 775 | sizeof(event)); |
789 | spin_unlock_irq(&priv->driver_lock); | ||
790 | continue; | ||
791 | } | ||
792 | spin_unlock_irq(&priv->driver_lock); | ||
793 | lbs_process_event(priv); | ||
794 | } else | ||
795 | spin_unlock_irq(&priv->driver_lock); | 776 | spin_unlock_irq(&priv->driver_lock); |
777 | lbs_process_event(priv, event); | ||
778 | spin_lock_irq(&priv->driver_lock); | ||
779 | } | ||
780 | spin_unlock_irq(&priv->driver_lock); | ||
796 | 781 | ||
797 | if (!priv->fw_ready) | 782 | if (!priv->fw_ready) |
798 | continue; | 783 | continue; |
@@ -801,10 +786,12 @@ static int lbs_thread(void *data) | |||
801 | if (priv->psstate == PS_STATE_PRE_SLEEP && | 786 | if (priv->psstate == PS_STATE_PRE_SLEEP && |
802 | !priv->dnld_sent && !priv->cur_cmd) { | 787 | !priv->dnld_sent && !priv->cur_cmd) { |
803 | if (priv->connect_status == LBS_CONNECTED) { | 788 | if (priv->connect_status == LBS_CONNECTED) { |
804 | lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n", | 789 | lbs_deb_thread("pre-sleep, currenttxskb %p, " |
805 | priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd); | 790 | "dnld_sent %d, cur_cmd %p\n", |
791 | priv->currenttxskb, priv->dnld_sent, | ||
792 | priv->cur_cmd); | ||
806 | 793 | ||
807 | lbs_ps_confirm_sleep(priv, (u16) priv->psmode); | 794 | lbs_ps_confirm_sleep(priv); |
808 | } else { | 795 | } else { |
809 | /* workaround for firmware sending | 796 | /* workaround for firmware sending |
810 | * deauth/linkloss event immediately | 797 | * deauth/linkloss event immediately |
@@ -812,7 +799,8 @@ static int lbs_thread(void *data) | |||
812 | * after firmware fixes it | 799 | * after firmware fixes it |
813 | */ | 800 | */ |
814 | priv->psstate = PS_STATE_AWAKE; | 801 | priv->psstate = PS_STATE_AWAKE; |
815 | lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n"); | 802 | lbs_pr_alert("ignore PS_SleepConfirm in " |
803 | "non-connected state\n"); | ||
816 | } | 804 | } |
817 | } | 805 | } |
818 | 806 | ||
@@ -945,7 +933,7 @@ static int lbs_setup_firmware(struct lbs_private *priv) | |||
945 | goto done; | 933 | goto done; |
946 | } | 934 | } |
947 | 935 | ||
948 | lbs_set_mac_packet_filter(priv); | 936 | lbs_set_mac_control(priv); |
949 | 937 | ||
950 | ret = lbs_get_data_rate(priv); | 938 | ret = lbs_get_data_rate(priv); |
951 | if (ret < 0) { | 939 | if (ret < 0) { |
@@ -985,6 +973,18 @@ out: | |||
985 | lbs_deb_leave(LBS_DEB_CMD); | 973 | lbs_deb_leave(LBS_DEB_CMD); |
986 | } | 974 | } |
987 | 975 | ||
976 | static void lbs_sync_channel_worker(struct work_struct *work) | ||
977 | { | ||
978 | struct lbs_private *priv = container_of(work, struct lbs_private, | ||
979 | sync_channel); | ||
980 | |||
981 | lbs_deb_enter(LBS_DEB_MAIN); | ||
982 | if (lbs_update_channel(priv)) | ||
983 | lbs_pr_info("Channel synchronization failed."); | ||
984 | lbs_deb_leave(LBS_DEB_MAIN); | ||
985 | } | ||
986 | |||
987 | |||
988 | static int lbs_init_adapter(struct lbs_private *priv) | 988 | static int lbs_init_adapter(struct lbs_private *priv) |
989 | { | 989 | { |
990 | size_t bufsize; | 990 | size_t bufsize; |
@@ -1009,14 +1009,6 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1009 | &priv->network_free_list); | 1009 | &priv->network_free_list); |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | priv->lbs_ps_confirm_sleep.seqnum = cpu_to_le16(++priv->seqnum); | ||
1013 | priv->lbs_ps_confirm_sleep.command = | ||
1014 | cpu_to_le16(CMD_802_11_PS_MODE); | ||
1015 | priv->lbs_ps_confirm_sleep.size = | ||
1016 | cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep)); | ||
1017 | priv->lbs_ps_confirm_sleep.action = | ||
1018 | cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); | ||
1019 | |||
1020 | memset(priv->current_addr, 0xff, ETH_ALEN); | 1012 | memset(priv->current_addr, 0xff, ETH_ALEN); |
1021 | 1013 | ||
1022 | priv->connect_status = LBS_DISCONNECTED; | 1014 | priv->connect_status = LBS_DISCONNECTED; |
@@ -1024,7 +1016,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1024 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 1016 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
1025 | priv->mode = IW_MODE_INFRA; | 1017 | priv->mode = IW_MODE_INFRA; |
1026 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; | 1018 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; |
1027 | priv->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 1019 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
1028 | priv->radioon = RADIO_ON; | 1020 | priv->radioon = RADIO_ON; |
1029 | priv->auto_rate = 1; | 1021 | priv->auto_rate = 1; |
1030 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | 1022 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; |
@@ -1045,7 +1037,18 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1045 | /* Allocate the command buffers */ | 1037 | /* Allocate the command buffers */ |
1046 | if (lbs_allocate_cmd_buffer(priv)) { | 1038 | if (lbs_allocate_cmd_buffer(priv)) { |
1047 | lbs_pr_err("Out of memory allocating command buffers\n"); | 1039 | lbs_pr_err("Out of memory allocating command buffers\n"); |
1048 | ret = -1; | 1040 | ret = -ENOMEM; |
1041 | goto out; | ||
1042 | } | ||
1043 | priv->resp_idx = 0; | ||
1044 | priv->resp_len[0] = priv->resp_len[1] = 0; | ||
1045 | |||
1046 | /* Create the event FIFO */ | ||
1047 | priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); | ||
1048 | if (IS_ERR(priv->event_fifo)) { | ||
1049 | lbs_pr_err("Out of memory allocating event FIFO buffer\n"); | ||
1050 | ret = -ENOMEM; | ||
1051 | goto out; | ||
1049 | } | 1052 | } |
1050 | 1053 | ||
1051 | out: | 1054 | out: |
@@ -1059,6 +1062,8 @@ static void lbs_free_adapter(struct lbs_private *priv) | |||
1059 | lbs_deb_enter(LBS_DEB_MAIN); | 1062 | lbs_deb_enter(LBS_DEB_MAIN); |
1060 | 1063 | ||
1061 | lbs_free_cmd_buffer(priv); | 1064 | lbs_free_cmd_buffer(priv); |
1065 | if (priv->event_fifo) | ||
1066 | kfifo_free(priv->event_fifo); | ||
1062 | del_timer(&priv->command_timer); | 1067 | del_timer(&priv->command_timer); |
1063 | kfree(priv->networks); | 1068 | kfree(priv->networks); |
1064 | priv->networks = NULL; | 1069 | priv->networks = NULL; |
@@ -1128,7 +1133,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1128 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); | 1133 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); |
1129 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | 1134 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); |
1130 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 1135 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
1131 | INIT_WORK(&priv->sync_channel, lbs_sync_channel); | 1136 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); |
1132 | 1137 | ||
1133 | sprintf(priv->mesh_ssid, "mesh"); | 1138 | sprintf(priv->mesh_ssid, "mesh"); |
1134 | priv->mesh_ssid_len = 4; | 1139 | priv->mesh_ssid_len = 4; |
@@ -1380,7 +1385,7 @@ static void lbs_remove_mesh(struct lbs_private *priv) | |||
1380 | * @param cfp_no A pointer to CFP number | 1385 | * @param cfp_no A pointer to CFP number |
1381 | * @return A pointer to CFP | 1386 | * @return A pointer to CFP |
1382 | */ | 1387 | */ |
1383 | struct chan_freq_power *lbs_get_region_cfp_table(u8 region, u8 band, int *cfp_no) | 1388 | struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no) |
1384 | { | 1389 | { |
1385 | int i, end; | 1390 | int i, end; |
1386 | 1391 | ||
@@ -1414,7 +1419,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) | |||
1414 | 1419 | ||
1415 | memset(priv->region_channel, 0, sizeof(priv->region_channel)); | 1420 | memset(priv->region_channel, 0, sizeof(priv->region_channel)); |
1416 | 1421 | ||
1417 | cfp = lbs_get_region_cfp_table(region, band, &cfp_no); | 1422 | cfp = lbs_get_region_cfp_table(region, &cfp_no); |
1418 | if (cfp != NULL) { | 1423 | if (cfp != NULL) { |
1419 | priv->region_channel[i].nrcfp = cfp_no; | 1424 | priv->region_channel[i].nrcfp = cfp_no; |
1420 | priv->region_channel[i].CFP = cfp; | 1425 | priv->region_channel[i].CFP = cfp; |
@@ -1433,31 +1438,49 @@ out: | |||
1433 | return ret; | 1438 | return ret; |
1434 | } | 1439 | } |
1435 | 1440 | ||
1436 | /** | 1441 | void lbs_queue_event(struct lbs_private *priv, u32 event) |
1437 | * @brief This function handles the interrupt. it will change PS | 1442 | { |
1438 | * state if applicable. it will wake up main_thread to handle | 1443 | unsigned long flags; |
1439 | * the interrupt event as well. | 1444 | |
1440 | * | 1445 | lbs_deb_enter(LBS_DEB_THREAD); |
1441 | * @param dev A pointer to net_device structure | 1446 | spin_lock_irqsave(&priv->driver_lock, flags); |
1442 | * @return n/a | 1447 | |
1443 | */ | 1448 | if (priv->psstate == PS_STATE_SLEEP) |
1444 | void lbs_interrupt(struct lbs_private *priv) | 1449 | priv->psstate = PS_STATE_AWAKE; |
1450 | |||
1451 | __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); | ||
1452 | |||
1453 | wake_up_interruptible(&priv->waitq); | ||
1454 | |||
1455 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
1456 | lbs_deb_leave(LBS_DEB_THREAD); | ||
1457 | } | ||
1458 | EXPORT_SYMBOL_GPL(lbs_queue_event); | ||
1459 | |||
1460 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) | ||
1445 | { | 1461 | { |
1446 | lbs_deb_enter(LBS_DEB_THREAD); | 1462 | lbs_deb_enter(LBS_DEB_THREAD); |
1447 | 1463 | ||
1448 | lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter); | ||
1449 | priv->intcounter++; | ||
1450 | if (priv->psstate == PS_STATE_SLEEP) | 1464 | if (priv->psstate == PS_STATE_SLEEP) |
1451 | priv->psstate = PS_STATE_AWAKE; | 1465 | priv->psstate = PS_STATE_AWAKE; |
1466 | |||
1467 | /* Swap buffers by flipping the response index */ | ||
1468 | BUG_ON(resp_idx > 1); | ||
1469 | priv->resp_idx = resp_idx; | ||
1470 | |||
1452 | wake_up_interruptible(&priv->waitq); | 1471 | wake_up_interruptible(&priv->waitq); |
1453 | 1472 | ||
1454 | lbs_deb_leave(LBS_DEB_THREAD); | 1473 | lbs_deb_leave(LBS_DEB_THREAD); |
1455 | } | 1474 | } |
1456 | EXPORT_SYMBOL_GPL(lbs_interrupt); | 1475 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); |
1457 | 1476 | ||
1458 | static int __init lbs_init_module(void) | 1477 | static int __init lbs_init_module(void) |
1459 | { | 1478 | { |
1460 | lbs_deb_enter(LBS_DEB_MAIN); | 1479 | lbs_deb_enter(LBS_DEB_MAIN); |
1480 | memset(&confirm_sleep, 0, sizeof(confirm_sleep)); | ||
1481 | confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE); | ||
1482 | confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep)); | ||
1483 | confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); | ||
1461 | lbs_debugfs_init(); | 1484 | lbs_debugfs_init(); |
1462 | lbs_deb_leave(LBS_DEB_MAIN); | 1485 | lbs_deb_leave(LBS_DEB_MAIN); |
1463 | return 0; | 1486 | return 0; |
@@ -1554,6 +1577,32 @@ out: | |||
1554 | return ret; | 1577 | return ret; |
1555 | } | 1578 | } |
1556 | 1579 | ||
1580 | #ifndef CONFIG_IEEE80211 | ||
1581 | const char *escape_essid(const char *essid, u8 essid_len) | ||
1582 | { | ||
1583 | static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; | ||
1584 | const char *s = essid; | ||
1585 | char *d = escaped; | ||
1586 | |||
1587 | if (ieee80211_is_empty_essid(essid, essid_len)) { | ||
1588 | memcpy(escaped, "<hidden>", sizeof("<hidden>")); | ||
1589 | return escaped; | ||
1590 | } | ||
1591 | |||
1592 | essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE); | ||
1593 | while (essid_len--) { | ||
1594 | if (*s == '\0') { | ||
1595 | *d++ = '\\'; | ||
1596 | *d++ = '0'; | ||
1597 | s++; | ||
1598 | } else { | ||
1599 | *d++ = *s++; | ||
1600 | } | ||
1601 | } | ||
1602 | *d = '\0'; | ||
1603 | return escaped; | ||
1604 | } | ||
1605 | #endif | ||
1557 | 1606 | ||
1558 | module_init(lbs_init_module); | 1607 | module_init(lbs_init_module); |
1559 | module_exit(lbs_exit_module); | 1608 | module_exit(lbs_exit_module); |