aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-05-05 13:32:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-05 13:32:35 -0400
commita70171dce9cd44cb06c7d299eba9fa87a8933045 (patch)
tree5425df5f33fadc617c7dec99578d06f0d933578e /drivers/net/wireless/rt2x00
parent5a412ad7f4c95bb5b756aa12b52646e857e7c75d (diff)
parenteaef6a93bd52a2cc47b9fce201310010707afdb4 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/libertas/if_cs.c drivers/net/wireless/rtlwifi/pci.c net/bluetooth/l2cap_sock.c
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c31
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h18
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c31
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c88
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h4
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
10 files changed, 175 insertions, 28 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index b21f81231a09..15237c275486 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1797,6 +1797,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
1797 __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags); 1797 __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);
1798 } 1798 }
1799 __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); 1799 __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
1800 __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
1800 1801
1801 /* 1802 /*
1802 * Set the rssi offset. 1803 * Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 5cd096e2ae36..790afd3ed946 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1640,7 +1640,6 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
1640 struct channel_info *info) 1640 struct channel_info *info)
1641{ 1641{
1642 u8 rfcsr; 1642 u8 rfcsr;
1643 u16 eeprom;
1644 1643
1645 rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); 1644 rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
1646 rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); 1645 rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
@@ -1670,11 +1669,10 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
1670 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); 1669 rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
1671 rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); 1670 rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
1672 1671
1673 rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
1674 if (rf->channel <= 14) { 1672 if (rf->channel <= 14) {
1675 int idx = rf->channel-1; 1673 int idx = rf->channel-1;
1676 1674
1677 if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) { 1675 if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
1678 if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { 1676 if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
1679 /* r55/r59 value array of channel 1~14 */ 1677 /* r55/r59 value array of channel 1~14 */
1680 static const char r55_bt_rev[] = {0x83, 0x83, 1678 static const char r55_bt_rev[] = {0x83, 0x83,
@@ -2917,8 +2915,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
2917 ant = (div_mode == 3) ? 1 : 0; 2915 ant = (div_mode == 3) ? 1 : 0;
2918 2916
2919 /* check if this is a Bluetooth combo card */ 2917 /* check if this is a Bluetooth combo card */
2920 rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); 2918 if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
2921 if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) {
2922 u32 reg; 2919 u32 reg;
2923 2920
2924 rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg); 2921 rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
@@ -3727,16 +3724,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
3727 } 3724 }
3728 3725
3729 /* 3726 /*
3730 * Read frequency offset and RF programming sequence. 3727 * Determine external LNA informations.
3731 */
3732 rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
3733 rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
3734
3735 /*
3736 * Read external LNA informations.
3737 */ 3728 */
3738 rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
3739
3740 if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) 3729 if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))
3741 __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); 3730 __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
3742 if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) 3731 if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))
@@ -3749,6 +3738,18 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
3749 __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); 3738 __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
3750 3739
3751 /* 3740 /*
3741 * Detect if this device has Bluetooth co-existence.
3742 */
3743 if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST))
3744 __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);
3745
3746 /*
3747 * Read frequency offset and RF programming sequence.
3748 */
3749 rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
3750 rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
3751
3752 /*
3752 * Store led settings, for correct led behaviour. 3753 * Store led settings, for correct led behaviour.
3753 */ 3754 */
3754#ifdef CONFIG_RT2X00_LIB_LEDS 3755#ifdef CONFIG_RT2X00_LIB_LEDS
@@ -3756,7 +3757,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
3756 rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); 3757 rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
3757 rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); 3758 rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
3758 3759
3759 rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); 3760 rt2x00dev->led_mcu_reg = eeprom;
3760#endif /* CONFIG_RT2X00_LIB_LEDS */ 3761#endif /* CONFIG_RT2X00_LIB_LEDS */
3761 3762
3762 /* 3763 /*
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 08d3947fcb26..cc4a54f571b8 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -302,8 +302,8 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
302 /* 302 /*
303 * Write firmware to device. 303 * Write firmware to device.
304 */ 304 */
305 rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, 305 rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
306 data, len); 306 data, len);
307 307
308 rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); 308 rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
309 rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); 309 rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 0d4e8fa3e1f8..0eb44cf2f44a 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -114,12 +114,12 @@ static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
114 return false; 114 return false;
115} 115}
116 116
117static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, 117static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
118 int urb_status, u32 tx_status) 118 int urb_status, u32 tx_status)
119{ 119{
120 if (urb_status) { 120 if (urb_status) {
121 WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status); 121 WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status);
122 return; 122 return false;
123 } 123 }
124 124
125 /* try to read all TX_STA_FIFO entries before scheduling txdone_work */ 125 /* try to read all TX_STA_FIFO entries before scheduling txdone_work */
@@ -129,13 +129,14 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
129 "drop tx status report.\n"); 129 "drop tx status report.\n");
130 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); 130 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
131 } else 131 } else
132 rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, 132 return true;
133 rt2800usb_tx_sta_fifo_read_completed);
134 } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { 133 } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
135 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); 134 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
136 } else if (rt2800usb_txstatus_pending(rt2x00dev)) { 135 } else if (rt2800usb_txstatus_pending(rt2x00dev)) {
137 mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); 136 mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2));
138 } 137 }
138
139 return false;
139} 140}
140 141
141static void rt2800usb_tx_dma_done(struct queue_entry *entry) 142static void rt2800usb_tx_dma_done(struct queue_entry *entry)
@@ -493,7 +494,7 @@ static void rt2800usb_work_txdone(struct work_struct *work)
493 * also delayed -> use a timer to retrieve it. 494 * also delayed -> use a timer to retrieve it.
494 */ 495 */
495 if (rt2800usb_txstatus_pending(rt2x00dev)) 496 if (rt2800usb_txstatus_pending(rt2x00dev))
496 mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); 497 mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2));
497} 498}
498 499
499/* 500/*
@@ -633,6 +634,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
633 __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); 634 __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
634 __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); 635 __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
635 __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); 636 __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
637 __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
636 638
637 setup_timer(&rt2x00dev->txstatus_timer, 639 setup_timer(&rt2x00dev->txstatus_timer,
638 rt2800usb_tx_sta_fifo_timeout, 640 rt2800usb_tx_sta_fifo_timeout,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 9d1a158e2c33..c446db69bd3c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -662,6 +662,7 @@ enum rt2x00_state_flags {
662 * Driver configuration 662 * Driver configuration
663 */ 663 */
664 CONFIG_CHANNEL_HT40, 664 CONFIG_CHANNEL_HT40,
665 CONFIG_POWERSAVING,
665}; 666};
666 667
667/* 668/*
@@ -681,6 +682,7 @@ enum rt2x00_capability_flags {
681 REQUIRE_TASKLET_CONTEXT, 682 REQUIRE_TASKLET_CONTEXT,
682 REQUIRE_SW_SEQNO, 683 REQUIRE_SW_SEQNO,
683 REQUIRE_HT_TX_DESC, 684 REQUIRE_HT_TX_DESC,
685 REQUIRE_PS_AUTOWAKE,
684 686
685 /* 687 /*
686 * Capabilities 688 * Capabilities
@@ -697,6 +699,7 @@ enum rt2x00_capability_flags {
697 CAPABILITY_EXTERNAL_LNA_A, 699 CAPABILITY_EXTERNAL_LNA_A,
698 CAPABILITY_EXTERNAL_LNA_BG, 700 CAPABILITY_EXTERNAL_LNA_BG,
699 CAPABILITY_DOUBLE_ANTENNA, 701 CAPABILITY_DOUBLE_ANTENNA,
702 CAPABILITY_BT_COEXIST,
700}; 703};
701 704
702/* 705/*
@@ -874,10 +877,20 @@ struct rt2x00_dev {
874 u8 calibration[2]; 877 u8 calibration[2];
875 878
876 /* 879 /*
880 * Association id.
881 */
882 u16 aid;
883
884 /*
877 * Beacon interval. 885 * Beacon interval.
878 */ 886 */
879 u16 beacon_int; 887 u16 beacon_int;
880 888
889 /**
890 * Timestamp of last received beacon
891 */
892 unsigned long last_beacon;
893
881 /* 894 /*
882 * Low level statistics which will have 895 * Low level statistics which will have
883 * to be kept up to date while device is running. 896 * to be kept up to date while device is running.
@@ -906,6 +919,11 @@ struct rt2x00_dev {
906 struct work_struct txdone_work; 919 struct work_struct txdone_work;
907 920
908 /* 921 /*
922 * Powersaving work
923 */
924 struct delayed_work autowakeup_work;
925
926 /*
909 * Data queue arrays for RX, TX, Beacon and ATIM. 927 * Data queue arrays for RX, TX, Beacon and ATIM.
910 */ 928 */
911 unsigned int data_queues; 929 unsigned int data_queues;
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index f78726404592..555180d8f4aa 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -100,6 +100,10 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
100 erp.basic_rates = bss_conf->basic_rates; 100 erp.basic_rates = bss_conf->basic_rates;
101 erp.beacon_int = bss_conf->beacon_int; 101 erp.beacon_int = bss_conf->beacon_int;
102 102
103 /* Update the AID, this is needed for dynamic PS support */
104 rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
105 rt2x00dev->last_beacon = bss_conf->timestamp;
106
103 /* Update global beacon interval time, this is needed for PS support */ 107 /* Update global beacon interval time, this is needed for PS support */
104 rt2x00dev->beacon_int = bss_conf->beacon_int; 108 rt2x00dev->beacon_int = bss_conf->beacon_int;
105 109
@@ -204,6 +208,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
204{ 208{
205 struct rt2x00lib_conf libconf; 209 struct rt2x00lib_conf libconf;
206 u16 hw_value; 210 u16 hw_value;
211 u16 autowake_timeout;
212 u16 beacon_int;
213 u16 beacon_diff;
207 214
208 memset(&libconf, 0, sizeof(libconf)); 215 memset(&libconf, 0, sizeof(libconf));
209 216
@@ -227,6 +234,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
227 sizeof(libconf.channel)); 234 sizeof(libconf.channel));
228 } 235 }
229 236
237 if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
238 (ieee80211_flags & IEEE80211_CONF_CHANGE_PS))
239 cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
240
230 /* 241 /*
231 * Start configuration. 242 * Start configuration.
232 */ 243 */
@@ -239,6 +250,26 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
239 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) 250 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
240 rt2x00link_reset_tuner(rt2x00dev, false); 251 rt2x00link_reset_tuner(rt2x00dev, false);
241 252
253 if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
254 (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) &&
255 (conf->flags & IEEE80211_CONF_PS)) {
256 beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon;
257 beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int);
258
259 if (beacon_diff > beacon_int)
260 beacon_diff = 0;
261
262 autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff;
263 queue_delayed_work(rt2x00dev->workqueue,
264 &rt2x00dev->autowakeup_work,
265 autowake_timeout - 15);
266 }
267
268 if (conf->flags & IEEE80211_CONF_PS)
269 set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
270 else
271 clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
272
242 rt2x00dev->curr_band = conf->channel->band; 273 rt2x00dev->curr_band = conf->channel->band;
243 rt2x00dev->curr_freq = conf->channel->center_freq; 274 rt2x00dev->curr_freq = conf->channel->center_freq;
244 rt2x00dev->tx_power = conf->power_level; 275 rt2x00dev->tx_power = conf->power_level;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 7776d9f1f297..2eb5196977fd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -141,6 +141,16 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
141 rt2x00dev); 141 rt2x00dev);
142} 142}
143 143
144static void rt2x00lib_autowakeup(struct work_struct *work)
145{
146 struct rt2x00_dev *rt2x00dev =
147 container_of(work, struct rt2x00_dev, autowakeup_work.work);
148
149 if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
150 ERROR(rt2x00dev, "Device failed to wakeup.\n");
151 clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
152}
153
144/* 154/*
145 * Interrupt context handlers. 155 * Interrupt context handlers.
146 */ 156 */
@@ -416,6 +426,77 @@ void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status)
416} 426}
417EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo); 427EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo);
418 428
429static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
430{
431 struct ieee80211_mgmt *mgmt = (void *)data;
432 u8 *pos, *end;
433
434 pos = (u8 *)mgmt->u.beacon.variable;
435 end = data + len;
436 while (pos < end) {
437 if (pos + 2 + pos[1] > end)
438 return NULL;
439
440 if (pos[0] == ie)
441 return pos;
442
443 pos += 2 + pos[1];
444 }
445
446 return NULL;
447}
448
449static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
450 struct sk_buff *skb,
451 struct rxdone_entry_desc *rxdesc)
452{
453 struct ieee80211_hdr *hdr = (void *) skb->data;
454 struct ieee80211_tim_ie *tim_ie;
455 u8 *tim;
456 u8 tim_len;
457 bool cam;
458
459 /* If this is not a beacon, or if mac80211 has no powersaving
460 * configured, or if the device is already in powersaving mode
461 * we can exit now. */
462 if (likely(!ieee80211_is_beacon(hdr->frame_control) ||
463 !(rt2x00dev->hw->conf.flags & IEEE80211_CONF_PS)))
464 return;
465
466 /* min. beacon length + FCS_LEN */
467 if (skb->len <= 40 + FCS_LEN)
468 return;
469
470 /* and only beacons from the associated BSSID, please */
471 if (!(rxdesc->dev_flags & RXDONE_MY_BSS) ||
472 !rt2x00dev->aid)
473 return;
474
475 rt2x00dev->last_beacon = jiffies;
476
477 tim = rt2x00lib_find_ie(skb->data, skb->len - FCS_LEN, WLAN_EID_TIM);
478 if (!tim)
479 return;
480
481 if (tim[1] < sizeof(*tim_ie))
482 return;
483
484 tim_len = tim[1];
485 tim_ie = (struct ieee80211_tim_ie *) &tim[2];
486
487 /* Check whenever the PHY can be turned off again. */
488
489 /* 1. What about buffered unicast traffic for our AID? */
490 cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid);
491
492 /* 2. Maybe the AP wants to send multicast/broadcast data? */
493 cam |= (tim_ie->bitmap_ctrl & 0x01);
494
495 if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
496 rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
497 IEEE80211_CONF_CHANGE_PS);
498}
499
419static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, 500static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
420 struct rxdone_entry_desc *rxdesc) 501 struct rxdone_entry_desc *rxdesc)
421{ 502{
@@ -531,6 +612,12 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
531 rxdesc.flags |= RX_FLAG_HT; 612 rxdesc.flags |= RX_FLAG_HT;
532 613
533 /* 614 /*
615 * Check if this is a beacon, and more frames have been
616 * buffered while we were in powersaving mode.
617 */
618 rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc);
619
620 /*
534 * Update extra components 621 * Update extra components
535 */ 622 */
536 rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); 623 rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
@@ -1017,6 +1104,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
1017 } 1104 }
1018 1105
1019 INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); 1106 INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
1107 INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
1020 1108
1021 /* 1109 /*
1022 * Let the driver probe the device to detect the capabilities. 1110 * Let the driver probe the device to detect the capabilities.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index cb208d589ff8..39e1052123e3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -170,19 +170,22 @@ struct rt2x00_async_read_data {
170 __le32 reg; 170 __le32 reg;
171 struct usb_ctrlrequest cr; 171 struct usb_ctrlrequest cr;
172 struct rt2x00_dev *rt2x00dev; 172 struct rt2x00_dev *rt2x00dev;
173 void (*callback)(struct rt2x00_dev *,int,u32); 173 bool (*callback)(struct rt2x00_dev *, int, u32);
174}; 174};
175 175
176static void rt2x00usb_register_read_async_cb(struct urb *urb) 176static void rt2x00usb_register_read_async_cb(struct urb *urb)
177{ 177{
178 struct rt2x00_async_read_data *rd = urb->context; 178 struct rt2x00_async_read_data *rd = urb->context;
179 rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg)); 179 if (rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg))) {
180 kfree(urb->context); 180 if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
181 kfree(rd);
182 } else
183 kfree(rd);
181} 184}
182 185
183void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, 186void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
184 const unsigned int offset, 187 const unsigned int offset,
185 void (*callback)(struct rt2x00_dev*,int,u32)) 188 bool (*callback)(struct rt2x00_dev*, int, u32))
186{ 189{
187 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); 190 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
188 struct urb *urb; 191 struct urb *urb;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 64be34f612f6..323ca7b2b095 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -349,10 +349,12 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
349 * be called from atomic context. The callback will be called 349 * be called from atomic context. The callback will be called
350 * when the URB completes. Otherwise the function is similar 350 * when the URB completes. Otherwise the function is similar
351 * to rt2x00usb_register_read(). 351 * to rt2x00usb_register_read().
352 * When the callback function returns false, the memory will be cleaned up,
353 * when it returns true, the urb will be fired again.
352 */ 354 */
353void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, 355void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
354 const unsigned int offset, 356 const unsigned int offset,
355 void (*callback)(struct rt2x00_dev*,int,u32)); 357 bool (*callback)(struct rt2x00_dev*, int, u32));
356 358
357/* 359/*
358 * Radio handlers 360 * Radio handlers
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index a6ce7d6cbdfa..ad20953cbf05 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2209,6 +2209,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
2209 if (!modparam_nohwcrypt) 2209 if (!modparam_nohwcrypt)
2210 __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); 2210 __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
2211 __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); 2211 __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
2212 __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
2212 2213
2213 /* 2214 /*
2214 * Set the rssi offset. 2215 * Set the rssi offset.