diff options
Diffstat (limited to 'drivers/net/wireless/zd1211rw')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_chip.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_chip.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 75 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_usb.c | 11 |
5 files changed, 94 insertions, 4 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index db96adf90ae2..0acb5c345734 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -809,6 +809,7 @@ static int hw_init_hmac(struct zd_chip *chip) | |||
809 | { CR_AFTER_PNP, 0x1 }, | 809 | { CR_AFTER_PNP, 0x1 }, |
810 | { CR_WEP_PROTECT, 0x114 }, | 810 | { CR_WEP_PROTECT, 0x114 }, |
811 | { CR_IFS_VALUE, IFS_VALUE_DEFAULT }, | 811 | { CR_IFS_VALUE, IFS_VALUE_DEFAULT }, |
812 | { CR_CAM_MODE, MODE_AP_WDS}, | ||
812 | }; | 813 | }; |
813 | 814 | ||
814 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | 815 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 5b6e3a3751ba..f8c061a9b6ec 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -489,6 +489,7 @@ enum { | |||
489 | 489 | ||
490 | #define CR_RX_OFFSET CTL_REG(0x065c) | 490 | #define CR_RX_OFFSET CTL_REG(0x065c) |
491 | 491 | ||
492 | #define CR_BCN_LENGTH CTL_REG(0x0664) | ||
492 | #define CR_PHY_DELAY CTL_REG(0x066C) | 493 | #define CR_PHY_DELAY CTL_REG(0x066C) |
493 | #define CR_BCN_FIFO CTL_REG(0x0670) | 494 | #define CR_BCN_FIFO CTL_REG(0x0670) |
494 | #define CR_SNIFFER_ON CTL_REG(0x0674) | 495 | #define CR_SNIFFER_ON CTL_REG(0x0674) |
@@ -545,6 +546,8 @@ enum { | |||
545 | #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \ | 546 | #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \ |
546 | RX_FILTER_CFEND | RX_FILTER_CFACK) | 547 | RX_FILTER_CFEND | RX_FILTER_CFACK) |
547 | 548 | ||
549 | #define BCN_MODE_IBSS 0x2000000 | ||
550 | |||
548 | /* Monitor mode sets filter to 0xfffff */ | 551 | /* Monitor mode sets filter to 0xfffff */ |
549 | 552 | ||
550 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) | 553 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) |
@@ -578,6 +581,11 @@ enum { | |||
578 | 581 | ||
579 | /* CAM: Continuous Access Mode (power management) */ | 582 | /* CAM: Continuous Access Mode (power management) */ |
580 | #define CR_CAM_MODE CTL_REG(0x0700) | 583 | #define CR_CAM_MODE CTL_REG(0x0700) |
584 | #define MODE_IBSS 0x0 | ||
585 | #define MODE_AP 0x1 | ||
586 | #define MODE_STA 0x2 | ||
587 | #define MODE_AP_WDS 0x3 | ||
588 | |||
581 | #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) | 589 | #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) |
582 | #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) | 590 | #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) |
583 | #define CR_CAM_ADDRESS CTL_REG(0x070C) | 591 | #define CR_CAM_ADDRESS CTL_REG(0x070C) |
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; |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 67dea9739c8f..71170244d2c9 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -172,12 +172,15 @@ struct zd_tx_skb_control_block { | |||
172 | struct zd_mac { | 172 | struct zd_mac { |
173 | struct zd_chip chip; | 173 | struct zd_chip chip; |
174 | spinlock_t lock; | 174 | spinlock_t lock; |
175 | spinlock_t intr_lock; | ||
175 | struct ieee80211_hw *hw; | 176 | struct ieee80211_hw *hw; |
176 | struct housekeeping housekeeping; | 177 | struct housekeeping housekeeping; |
177 | struct work_struct set_multicast_hash_work; | 178 | struct work_struct set_multicast_hash_work; |
178 | struct work_struct set_rts_cts_work; | 179 | struct work_struct set_rts_cts_work; |
179 | struct work_struct set_rx_filter_work; | 180 | struct work_struct set_rx_filter_work; |
181 | struct work_struct process_intr; | ||
180 | struct zd_mc_hash multicast_hash; | 182 | struct zd_mc_hash multicast_hash; |
183 | u8 intr_buffer[USB_MAX_EP_INT_BUFFER]; | ||
181 | u8 regdomain; | 184 | u8 regdomain; |
182 | u8 default_regdomain; | 185 | u8 default_regdomain; |
183 | int type; | 186 | int type; |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 7942b15acfe7..e34675c2f8fc 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -97,6 +97,7 @@ MODULE_DEVICE_TABLE(usb, usb_ids); | |||
97 | #define FW_ZD1211B_PREFIX "zd1211/zd1211b_" | 97 | #define FW_ZD1211B_PREFIX "zd1211/zd1211b_" |
98 | 98 | ||
99 | /* USB device initialization */ | 99 | /* USB device initialization */ |
100 | static void int_urb_complete(struct urb *urb); | ||
100 | 101 | ||
101 | static int request_fw_file( | 102 | static int request_fw_file( |
102 | const struct firmware **fw, const char *name, struct device *device) | 103 | const struct firmware **fw, const char *name, struct device *device) |
@@ -336,11 +337,18 @@ static inline void handle_regs_int(struct urb *urb) | |||
336 | struct zd_usb *usb = urb->context; | 337 | struct zd_usb *usb = urb->context; |
337 | struct zd_usb_interrupt *intr = &usb->intr; | 338 | struct zd_usb_interrupt *intr = &usb->intr; |
338 | int len; | 339 | int len; |
340 | u16 int_num; | ||
339 | 341 | ||
340 | ZD_ASSERT(in_interrupt()); | 342 | ZD_ASSERT(in_interrupt()); |
341 | spin_lock(&intr->lock); | 343 | spin_lock(&intr->lock); |
342 | 344 | ||
343 | if (intr->read_regs_enabled) { | 345 | int_num = le16_to_cpu(*(u16 *)(urb->transfer_buffer+2)); |
346 | if (int_num == CR_INTERRUPT) { | ||
347 | struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context)); | ||
348 | memcpy(&mac->intr_buffer, urb->transfer_buffer, | ||
349 | USB_MAX_EP_INT_BUFFER); | ||
350 | schedule_work(&mac->process_intr); | ||
351 | } else if (intr->read_regs_enabled) { | ||
344 | intr->read_regs.length = len = urb->actual_length; | 352 | intr->read_regs.length = len = urb->actual_length; |
345 | 353 | ||
346 | if (len > sizeof(intr->read_regs.buffer)) | 354 | if (len > sizeof(intr->read_regs.buffer)) |
@@ -351,7 +359,6 @@ static inline void handle_regs_int(struct urb *urb) | |||
351 | goto out; | 359 | goto out; |
352 | } | 360 | } |
353 | 361 | ||
354 | dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n"); | ||
355 | out: | 362 | out: |
356 | spin_unlock(&intr->lock); | 363 | spin_unlock(&intr->lock); |
357 | } | 364 | } |