diff options
author | Luis Carlos Cobo <luisca@cozybit.com> | 2008-03-03 15:32:15 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-06 17:19:47 -0500 |
commit | 72e77a8a7921d952bdef2468d9315616eca6b464 (patch) | |
tree | 752dfd038edb0a76257eda3b7e04db74ecfe1a7e /drivers/net/wireless/zd1211rw/zd_mac.c | |
parent | f137e05468f2a648aba11377dc824d788683dff4 (diff) |
zd1211rw: support for mesh interface and beaconing
The previously unused CR_CAM_MODE register is set to MODE_AP_WDS. This makes the
driver ack mesh (WDS) frames. It does not affect Infra functionality of the
driver.
Previously missing beaconing support has been added. This might also help
implement a currently missing ah-hoc mode.
Support for interrupts from the device have been added, but we are not handling
most of them.
Mesh interfaces are considered associated as long as the interface is up.
Signed-off-by: Luis Carlos Cobo <luisca@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_mac.c')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index f90f03f676de..69c45ca99051 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -475,6 +475,46 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
475 | /* FIXME: Management frame? */ | 475 | /* FIXME: Management frame? */ |
476 | } | 476 | } |
477 | 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 | |||
478 | static int fill_ctrlset(struct zd_mac *mac, | 518 | static int fill_ctrlset(struct zd_mac *mac, |
479 | struct sk_buff *skb, | 519 | struct sk_buff *skb, |
480 | struct ieee80211_tx_control *control) | 520 | struct ieee80211_tx_control *control) |
@@ -709,6 +749,7 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, | |||
709 | 749 | ||
710 | switch (conf->type) { | 750 | switch (conf->type) { |
711 | case IEEE80211_IF_TYPE_MNTR: | 751 | case IEEE80211_IF_TYPE_MNTR: |
752 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
712 | case IEEE80211_IF_TYPE_STA: | 753 | case IEEE80211_IF_TYPE_STA: |
713 | mac->type = conf->type; | 754 | mac->type = conf->type; |
714 | break; | 755 | break; |
@@ -738,15 +779,43 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, | |||
738 | struct ieee80211_if_conf *conf) | 779 | struct ieee80211_if_conf *conf) |
739 | { | 780 | { |
740 | 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); | ||
741 | 794 | ||
742 | spin_lock_irq(&mac->lock); | 795 | spin_lock_irq(&mac->lock); |
743 | mac->associated = is_valid_ether_addr(conf->bssid); | 796 | mac->associated = associated; |
744 | spin_unlock_irq(&mac->lock); | 797 | spin_unlock_irq(&mac->lock); |
745 | 798 | ||
746 | /* TODO: do hardware bssid filtering */ | 799 | /* TODO: do hardware bssid filtering */ |
747 | return 0; | 800 | return 0; |
748 | } | 801 | } |
749 | 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 | |||
750 | static void set_multicast_hash_handler(struct work_struct *work) | 819 | static void set_multicast_hash_handler(struct work_struct *work) |
751 | { | 820 | { |
752 | struct zd_mac *mac = | 821 | struct zd_mac *mac = |
@@ -912,7 +981,8 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
912 | 981 | ||
913 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; | 982 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; |
914 | 983 | ||
915 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS; | 984 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
985 | IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; | ||
916 | hw->max_rssi = 100; | 986 | hw->max_rssi = 100; |
917 | hw->max_signal = 100; | 987 | hw->max_signal = 100; |
918 | 988 | ||
@@ -926,6 +996,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
926 | INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); | 996 | INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); |
927 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); | 997 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); |
928 | 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); | ||
929 | 1000 | ||
930 | SET_IEEE80211_DEV(hw, &intf->dev); | 1001 | SET_IEEE80211_DEV(hw, &intf->dev); |
931 | return hw; | 1002 | return hw; |