diff options
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; |
