diff options
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_mac.c')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 241 |
1 files changed, 146 insertions, 95 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 76ef2d83919d..69c45ca99051 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -34,76 +34,61 @@ | |||
34 | 34 | ||
35 | /* This table contains the hardware specific values for the modulation rates. */ | 35 | /* This table contains the hardware specific values for the modulation rates. */ |
36 | static const struct ieee80211_rate zd_rates[] = { | 36 | static const struct ieee80211_rate zd_rates[] = { |
37 | { .rate = 10, | 37 | { .bitrate = 10, |
38 | .val = ZD_CCK_RATE_1M, | 38 | .hw_value = ZD_CCK_RATE_1M, }, |
39 | .flags = IEEE80211_RATE_CCK }, | 39 | { .bitrate = 20, |
40 | { .rate = 20, | 40 | .hw_value = ZD_CCK_RATE_2M, |
41 | .val = ZD_CCK_RATE_2M, | 41 | .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT, |
42 | .val2 = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT, | 42 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, |
43 | .flags = IEEE80211_RATE_CCK_2 }, | 43 | { .bitrate = 55, |
44 | { .rate = 55, | 44 | .hw_value = ZD_CCK_RATE_5_5M, |
45 | .val = ZD_CCK_RATE_5_5M, | 45 | .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT, |
46 | .val2 = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT, | 46 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, |
47 | .flags = IEEE80211_RATE_CCK_2 }, | 47 | { .bitrate = 110, |
48 | { .rate = 110, | 48 | .hw_value = ZD_CCK_RATE_11M, |
49 | .val = ZD_CCK_RATE_11M, | 49 | .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT, |
50 | .val2 = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT, | 50 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, |
51 | .flags = IEEE80211_RATE_CCK_2 }, | 51 | { .bitrate = 60, |
52 | { .rate = 60, | 52 | .hw_value = ZD_OFDM_RATE_6M, |
53 | .val = ZD_OFDM_RATE_6M, | 53 | .flags = 0 }, |
54 | .flags = IEEE80211_RATE_OFDM }, | 54 | { .bitrate = 90, |
55 | { .rate = 90, | 55 | .hw_value = ZD_OFDM_RATE_9M, |
56 | .val = ZD_OFDM_RATE_9M, | 56 | .flags = 0 }, |
57 | .flags = IEEE80211_RATE_OFDM }, | 57 | { .bitrate = 120, |
58 | { .rate = 120, | 58 | .hw_value = ZD_OFDM_RATE_12M, |
59 | .val = ZD_OFDM_RATE_12M, | 59 | .flags = 0 }, |
60 | .flags = IEEE80211_RATE_OFDM }, | 60 | { .bitrate = 180, |
61 | { .rate = 180, | 61 | .hw_value = ZD_OFDM_RATE_18M, |
62 | .val = ZD_OFDM_RATE_18M, | 62 | .flags = 0 }, |
63 | .flags = IEEE80211_RATE_OFDM }, | 63 | { .bitrate = 240, |
64 | { .rate = 240, | 64 | .hw_value = ZD_OFDM_RATE_24M, |
65 | .val = ZD_OFDM_RATE_24M, | 65 | .flags = 0 }, |
66 | .flags = IEEE80211_RATE_OFDM }, | 66 | { .bitrate = 360, |
67 | { .rate = 360, | 67 | .hw_value = ZD_OFDM_RATE_36M, |
68 | .val = ZD_OFDM_RATE_36M, | 68 | .flags = 0 }, |
69 | .flags = IEEE80211_RATE_OFDM }, | 69 | { .bitrate = 480, |
70 | { .rate = 480, | 70 | .hw_value = ZD_OFDM_RATE_48M, |
71 | .val = ZD_OFDM_RATE_48M, | 71 | .flags = 0 }, |
72 | .flags = IEEE80211_RATE_OFDM }, | 72 | { .bitrate = 540, |
73 | { .rate = 540, | 73 | .hw_value = ZD_OFDM_RATE_54M, |
74 | .val = ZD_OFDM_RATE_54M, | 74 | .flags = 0 }, |
75 | .flags = IEEE80211_RATE_OFDM }, | ||
76 | }; | 75 | }; |
77 | 76 | ||
78 | static const struct ieee80211_channel zd_channels[] = { | 77 | static const struct ieee80211_channel zd_channels[] = { |
79 | { .chan = 1, | 78 | { .center_freq = 2412, .hw_value = 1 }, |
80 | .freq = 2412}, | 79 | { .center_freq = 2417, .hw_value = 2 }, |
81 | { .chan = 2, | 80 | { .center_freq = 2422, .hw_value = 3 }, |
82 | .freq = 2417}, | 81 | { .center_freq = 2427, .hw_value = 4 }, |
83 | { .chan = 3, | 82 | { .center_freq = 2432, .hw_value = 5 }, |
84 | .freq = 2422}, | 83 | { .center_freq = 2437, .hw_value = 6 }, |
85 | { .chan = 4, | 84 | { .center_freq = 2442, .hw_value = 7 }, |
86 | .freq = 2427}, | 85 | { .center_freq = 2447, .hw_value = 8 }, |
87 | { .chan = 5, | 86 | { .center_freq = 2452, .hw_value = 9 }, |
88 | .freq = 2432}, | 87 | { .center_freq = 2457, .hw_value = 10 }, |
89 | { .chan = 6, | 88 | { .center_freq = 2462, .hw_value = 11 }, |
90 | .freq = 2437}, | 89 | { .center_freq = 2467, .hw_value = 12 }, |
91 | { .chan = 7, | 90 | { .center_freq = 2472, .hw_value = 13 }, |
92 | .freq = 2442}, | 91 | { .center_freq = 2484, .hw_value = 14 }, |
93 | { .chan = 8, | ||
94 | .freq = 2447}, | ||
95 | { .chan = 9, | ||
96 | .freq = 2452}, | ||
97 | { .chan = 10, | ||
98 | .freq = 2457}, | ||
99 | { .chan = 11, | ||
100 | .freq = 2462}, | ||
101 | { .chan = 12, | ||
102 | .freq = 2467}, | ||
103 | { .chan = 13, | ||
104 | .freq = 2472}, | ||
105 | { .chan = 14, | ||
106 | .freq = 2484} | ||
107 | }; | 92 | }; |
108 | 93 | ||
109 | static void housekeeping_init(struct zd_mac *mac); | 94 | static void housekeeping_init(struct zd_mac *mac); |
@@ -490,6 +475,46 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
490 | /* FIXME: Management frame? */ | 475 | /* FIXME: Management frame? */ |
491 | } | 476 | } |
492 | 477 | ||
478 | void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) | ||
479 | { | ||
480 | struct zd_mac *mac = zd_hw_mac(hw); | ||
481 | u32 tmp, j = 0; | ||
482 | /* 4 more bytes for tail CRC */ | ||
483 | u32 full_len = beacon->len + 4; | ||
484 | zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); | ||
485 | zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | ||
486 | while (tmp & 0x2) { | ||
487 | zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | ||
488 | if ((++j % 100) == 0) { | ||
489 | printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n"); | ||
490 | if (j >= 500) { | ||
491 | printk(KERN_ERR "Giving up beacon config.\n"); | ||
492 | return; | ||
493 | } | ||
494 | } | ||
495 | msleep(1); | ||
496 | } | ||
497 | |||
498 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); | ||
499 | if (zd_chip_is_zd1211b(&mac->chip)) | ||
500 | zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); | ||
501 | |||
502 | for (j = 0 ; j < beacon->len; j++) | ||
503 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, | ||
504 | *((u8 *)(beacon->data + j))); | ||
505 | |||
506 | for (j = 0; j < 4; j++) | ||
507 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); | ||
508 | |||
509 | zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); | ||
510 | /* 802.11b/g 2.4G CCK 1Mb | ||
511 | * 802.11a, not yet implemented, uses different values (see GPL vendor | ||
512 | * driver) | ||
513 | */ | ||
514 | zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | | ||
515 | (full_len << 19)); | ||
516 | } | ||
517 | |||
493 | static int fill_ctrlset(struct zd_mac *mac, | 518 | static int fill_ctrlset(struct zd_mac *mac, |
494 | struct sk_buff *skb, | 519 | struct sk_buff *skb, |
495 | struct ieee80211_tx_control *control) | 520 | struct ieee80211_tx_control *control) |
@@ -503,7 +528,9 @@ static int fill_ctrlset(struct zd_mac *mac, | |||
503 | 528 | ||
504 | ZD_ASSERT(frag_len <= 0xffff); | 529 | ZD_ASSERT(frag_len <= 0xffff); |
505 | 530 | ||
506 | cs->modulation = control->tx_rate; | 531 | cs->modulation = control->tx_rate->hw_value; |
532 | if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) | ||
533 | cs->modulation = control->tx_rate->hw_value_short; | ||
507 | 534 | ||
508 | cs->tx_length = cpu_to_le16(frag_len); | 535 | cs->tx_length = cpu_to_le16(frag_len); |
509 | 536 | ||
@@ -631,6 +658,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
631 | int bad_frame = 0; | 658 | int bad_frame = 0; |
632 | u16 fc; | 659 | u16 fc; |
633 | bool is_qos, is_4addr, need_padding; | 660 | bool is_qos, is_4addr, need_padding; |
661 | int i; | ||
662 | u8 rate; | ||
634 | 663 | ||
635 | if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ + | 664 | if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ + |
636 | FCS_LEN + sizeof(struct rx_status)) | 665 | FCS_LEN + sizeof(struct rx_status)) |
@@ -660,14 +689,19 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
660 | } | 689 | } |
661 | } | 690 | } |
662 | 691 | ||
663 | stats.channel = _zd_chip_get_channel(&mac->chip); | 692 | stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; |
664 | stats.freq = zd_channels[stats.channel - 1].freq; | 693 | stats.band = IEEE80211_BAND_2GHZ; |
665 | stats.phymode = MODE_IEEE80211G; | ||
666 | stats.ssi = status->signal_strength; | 694 | stats.ssi = status->signal_strength; |
667 | stats.signal = zd_rx_qual_percent(buffer, | 695 | stats.signal = zd_rx_qual_percent(buffer, |
668 | length - sizeof(struct rx_status), | 696 | length - sizeof(struct rx_status), |
669 | status); | 697 | status); |
670 | stats.rate = zd_rx_rate(buffer, status); | 698 | |
699 | rate = zd_rx_rate(buffer, status); | ||
700 | |||
701 | /* todo: return index in the big switches in zd_rx_rate instead */ | ||
702 | for (i = 0; i < mac->band.n_bitrates; i++) | ||
703 | if (rate == mac->band.bitrates[i].hw_value) | ||
704 | stats.rate_idx = i; | ||
671 | 705 | ||
672 | length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status); | 706 | length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status); |
673 | buffer += ZD_PLCP_HEADER_SIZE; | 707 | buffer += ZD_PLCP_HEADER_SIZE; |
@@ -715,6 +749,7 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, | |||
715 | 749 | ||
716 | switch (conf->type) { | 750 | switch (conf->type) { |
717 | case IEEE80211_IF_TYPE_MNTR: | 751 | case IEEE80211_IF_TYPE_MNTR: |
752 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
718 | case IEEE80211_IF_TYPE_STA: | 753 | case IEEE80211_IF_TYPE_STA: |
719 | mac->type = conf->type; | 754 | mac->type = conf->type; |
720 | break; | 755 | break; |
@@ -736,7 +771,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw, | |||
736 | static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | 771 | static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) |
737 | { | 772 | { |
738 | struct zd_mac *mac = zd_hw_mac(hw); | 773 | struct zd_mac *mac = zd_hw_mac(hw); |
739 | return zd_chip_set_channel(&mac->chip, conf->channel); | 774 | return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); |
740 | } | 775 | } |
741 | 776 | ||
742 | static int zd_op_config_interface(struct ieee80211_hw *hw, | 777 | static int zd_op_config_interface(struct ieee80211_hw *hw, |
@@ -744,15 +779,43 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, | |||
744 | struct ieee80211_if_conf *conf) | 779 | struct ieee80211_if_conf *conf) |
745 | { | 780 | { |
746 | struct zd_mac *mac = zd_hw_mac(hw); | 781 | struct zd_mac *mac = zd_hw_mac(hw); |
782 | int associated; | ||
783 | |||
784 | if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) { | ||
785 | associated = true; | ||
786 | if (conf->beacon) { | ||
787 | zd_mac_config_beacon(hw, conf->beacon); | ||
788 | kfree_skb(conf->beacon); | ||
789 | zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | | ||
790 | hw->conf.beacon_int); | ||
791 | } | ||
792 | } else | ||
793 | associated = is_valid_ether_addr(conf->bssid); | ||
747 | 794 | ||
748 | spin_lock_irq(&mac->lock); | 795 | spin_lock_irq(&mac->lock); |
749 | mac->associated = is_valid_ether_addr(conf->bssid); | 796 | mac->associated = associated; |
750 | spin_unlock_irq(&mac->lock); | 797 | spin_unlock_irq(&mac->lock); |
751 | 798 | ||
752 | /* TODO: do hardware bssid filtering */ | 799 | /* TODO: do hardware bssid filtering */ |
753 | return 0; | 800 | return 0; |
754 | } | 801 | } |
755 | 802 | ||
803 | void zd_process_intr(struct work_struct *work) | ||
804 | { | ||
805 | u16 int_status; | ||
806 | struct zd_mac *mac = container_of(work, struct zd_mac, process_intr); | ||
807 | |||
808 | int_status = le16_to_cpu(*(u16 *)(mac->intr_buffer+4)); | ||
809 | if (int_status & INT_CFG_NEXT_BCN) { | ||
810 | if (net_ratelimit()) | ||
811 | dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n"); | ||
812 | } else | ||
813 | dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n"); | ||
814 | |||
815 | zd_chip_enable_hwint(&mac->chip); | ||
816 | } | ||
817 | |||
818 | |||
756 | static void set_multicast_hash_handler(struct work_struct *work) | 819 | static void set_multicast_hash_handler(struct work_struct *work) |
757 | { | 820 | { |
758 | struct zd_mac *mac = | 821 | struct zd_mac *mac = |
@@ -780,7 +843,7 @@ static void set_rx_filter_handler(struct work_struct *work) | |||
780 | 843 | ||
781 | #define SUPPORTED_FIF_FLAGS \ | 844 | #define SUPPORTED_FIF_FLAGS \ |
782 | (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ | 845 | (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ |
783 | FIF_OTHER_BSS) | 846 | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) |
784 | static void zd_op_configure_filter(struct ieee80211_hw *hw, | 847 | static void zd_op_configure_filter(struct ieee80211_hw *hw, |
785 | unsigned int changed_flags, | 848 | unsigned int changed_flags, |
786 | unsigned int *new_flags, | 849 | unsigned int *new_flags, |
@@ -894,7 +957,6 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
894 | { | 957 | { |
895 | struct zd_mac *mac; | 958 | struct zd_mac *mac; |
896 | struct ieee80211_hw *hw; | 959 | struct ieee80211_hw *hw; |
897 | int i; | ||
898 | 960 | ||
899 | hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops); | 961 | hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops); |
900 | if (!hw) { | 962 | if (!hw) { |
@@ -912,19 +974,15 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
912 | 974 | ||
913 | memcpy(mac->channels, zd_channels, sizeof(zd_channels)); | 975 | memcpy(mac->channels, zd_channels, sizeof(zd_channels)); |
914 | memcpy(mac->rates, zd_rates, sizeof(zd_rates)); | 976 | memcpy(mac->rates, zd_rates, sizeof(zd_rates)); |
915 | mac->modes[0].mode = MODE_IEEE80211G; | 977 | mac->band.n_bitrates = ARRAY_SIZE(zd_rates); |
916 | mac->modes[0].num_rates = ARRAY_SIZE(zd_rates); | 978 | mac->band.bitrates = mac->rates; |
917 | mac->modes[0].rates = mac->rates; | 979 | mac->band.n_channels = ARRAY_SIZE(zd_channels); |
918 | mac->modes[0].num_channels = ARRAY_SIZE(zd_channels); | 980 | mac->band.channels = mac->channels; |
919 | mac->modes[0].channels = mac->channels; | 981 | |
920 | mac->modes[1].mode = MODE_IEEE80211B; | 982 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; |
921 | mac->modes[1].num_rates = 4; | ||
922 | mac->modes[1].rates = mac->rates; | ||
923 | mac->modes[1].num_channels = ARRAY_SIZE(zd_channels); | ||
924 | mac->modes[1].channels = mac->channels; | ||
925 | 983 | ||
926 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 984 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
927 | IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED; | 985 | IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; |
928 | hw->max_rssi = 100; | 986 | hw->max_rssi = 100; |
929 | hw->max_signal = 100; | 987 | hw->max_signal = 100; |
930 | 988 | ||
@@ -933,19 +991,12 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
933 | 991 | ||
934 | skb_queue_head_init(&mac->ack_wait_queue); | 992 | skb_queue_head_init(&mac->ack_wait_queue); |
935 | 993 | ||
936 | for (i = 0; i < 2; i++) { | ||
937 | if (ieee80211_register_hwmode(hw, &mac->modes[i])) { | ||
938 | dev_dbg_f(&intf->dev, "cannot register hwmode\n"); | ||
939 | ieee80211_free_hw(hw); | ||
940 | return NULL; | ||
941 | } | ||
942 | } | ||
943 | |||
944 | zd_chip_init(&mac->chip, hw, intf); | 994 | zd_chip_init(&mac->chip, hw, intf); |
945 | housekeeping_init(mac); | 995 | housekeeping_init(mac); |
946 | INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); | 996 | INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); |
947 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); | 997 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); |
948 | INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler); | 998 | INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler); |
999 | INIT_WORK(&mac->process_intr, zd_process_intr); | ||
949 | 1000 | ||
950 | SET_IEEE80211_DEV(hw, &intf->dev); | 1001 | SET_IEEE80211_DEV(hw, &intf->dev); |
951 | return hw; | 1002 | return hw; |