aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-12-20 04:52:42 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 15:58:34 -0500
commit7d7f19ccb777946df0a8fb7c83189ba2ae08b02e (patch)
tree38fcea85510a4945283cf23bc029261b3941fc74
parent3ebbbb56a162b8f9b9a77bc7810b9d4e0868e039 (diff)
rt2x00: Implement Powersaving
Listen to IEEE80211_CONF_PS to determine if the device should drop into powersaving mode. This feature depends on the dynamic power save functionality in mac80211. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c53
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.h4
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c40
6 files changed, 174 insertions, 7 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 6a977679124d..1afba42cc128 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -524,6 +524,32 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
524 rt2x00pci_register_write(rt2x00dev, CSR12, reg); 524 rt2x00pci_register_write(rt2x00dev, CSR12, reg);
525} 525}
526 526
527static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
528 struct rt2x00lib_conf *libconf)
529{
530 enum dev_state state =
531 (libconf->conf->flags & IEEE80211_CONF_PS) ?
532 STATE_SLEEP : STATE_AWAKE;
533 u32 reg;
534
535 if (state == STATE_SLEEP) {
536 rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
537 rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
538 (libconf->conf->beacon_int - 20) * 16);
539 rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
540 libconf->conf->listen_interval - 1);
541
542 /* We must first disable autowake before it can be enabled */
543 rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
544 rt2x00pci_register_write(rt2x00dev, CSR20, reg);
545
546 rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
547 rt2x00pci_register_write(rt2x00dev, CSR20, reg);
548 }
549
550 rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
551}
552
527static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, 553static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
528 struct rt2x00lib_conf *libconf, 554 struct rt2x00lib_conf *libconf,
529 const unsigned int flags) 555 const unsigned int flags)
@@ -537,6 +563,8 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
537 rt2400pci_config_retry_limit(rt2x00dev, libconf); 563 rt2400pci_config_retry_limit(rt2x00dev, libconf);
538 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) 564 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
539 rt2400pci_config_duration(rt2x00dev, libconf); 565 rt2400pci_config_duration(rt2x00dev, libconf);
566 if (flags & IEEE80211_CONF_CHANGE_PS)
567 rt2400pci_config_ps(rt2x00dev, libconf);
540} 568}
541 569
542static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, 570static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index d3bc218ec85c..bf5e81162f25 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -573,6 +573,32 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
573 rt2x00pci_register_write(rt2x00dev, CSR12, reg); 573 rt2x00pci_register_write(rt2x00dev, CSR12, reg);
574} 574}
575 575
576static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
577 struct rt2x00lib_conf *libconf)
578{
579 enum dev_state state =
580 (libconf->conf->flags & IEEE80211_CONF_PS) ?
581 STATE_SLEEP : STATE_AWAKE;
582 u32 reg;
583
584 if (state == STATE_SLEEP) {
585 rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
586 rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
587 (libconf->conf->beacon_int - 20) * 16);
588 rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
589 libconf->conf->listen_interval - 1);
590
591 /* We must first disable autowake before it can be enabled */
592 rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
593 rt2x00pci_register_write(rt2x00dev, CSR20, reg);
594
595 rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
596 rt2x00pci_register_write(rt2x00dev, CSR20, reg);
597 }
598
599 rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
600}
601
576static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, 602static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
577 struct rt2x00lib_conf *libconf, 603 struct rt2x00lib_conf *libconf,
578 const unsigned int flags) 604 const unsigned int flags)
@@ -588,6 +614,8 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
588 rt2500pci_config_retry_limit(rt2x00dev, libconf); 614 rt2500pci_config_retry_limit(rt2x00dev, libconf);
589 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) 615 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
590 rt2500pci_config_duration(rt2x00dev, libconf); 616 rt2500pci_config_duration(rt2x00dev, libconf);
617 if (flags & IEEE80211_CONF_CHANGE_PS)
618 rt2500pci_config_ps(rt2x00dev, libconf);
591} 619}
592 620
593/* 621/*
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index af6b5847be5c..23cf585f03a4 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -634,6 +634,32 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
634 rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); 634 rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
635} 635}
636 636
637static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
638 struct rt2x00lib_conf *libconf)
639{
640 enum dev_state state =
641 (libconf->conf->flags & IEEE80211_CONF_PS) ?
642 STATE_SLEEP : STATE_AWAKE;
643 u16 reg;
644
645 if (state == STATE_SLEEP) {
646 rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
647 rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
648 libconf->conf->beacon_int - 20);
649 rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
650 libconf->conf->listen_interval - 1);
651
652 /* We must first disable autowake before it can be enabled */
653 rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
654 rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
655
656 rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 1);
657 rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
658 }
659
660 rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
661}
662
637static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, 663static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
638 struct rt2x00lib_conf *libconf, 664 struct rt2x00lib_conf *libconf,
639 const unsigned int flags) 665 const unsigned int flags)
@@ -647,6 +673,8 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
647 libconf->conf->power_level); 673 libconf->conf->power_level);
648 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) 674 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
649 rt2500usb_config_duration(rt2x00dev, libconf); 675 rt2500usb_config_duration(rt2x00dev, libconf);
676 if (flags & IEEE80211_CONF_CHANGE_PS)
677 rt2500usb_config_ps(rt2x00dev, libconf);
650} 678}
651 679
652/* 680/*
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 987e89009f74..c7ab744f0052 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -146,12 +146,6 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
146 mutex_unlock(&rt2x00dev->csr_mutex); 146 mutex_unlock(&rt2x00dev->csr_mutex);
147} 147}
148 148
149#ifdef CONFIG_RT2X00_LIB_LEDS
150/*
151 * This function is only called from rt61pci_led_brightness()
152 * make gcc happy by placing this function inside the
153 * same ifdef statement as the caller.
154 */
155static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, 149static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
156 const u8 command, const u8 token, 150 const u8 command, const u8 token,
157 const u8 arg0, const u8 arg1) 151 const u8 arg0, const u8 arg1)
@@ -180,7 +174,6 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
180 mutex_unlock(&rt2x00dev->csr_mutex); 174 mutex_unlock(&rt2x00dev->csr_mutex);
181 175
182} 176}
183#endif /* CONFIG_RT2X00_LIB_LEDS */
184 177
185static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom) 178static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
186{ 179{
@@ -967,6 +960,50 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
967 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); 960 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
968} 961}
969 962
963static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
964 struct rt2x00lib_conf *libconf)
965{
966 enum dev_state state =
967 (libconf->conf->flags & IEEE80211_CONF_PS) ?
968 STATE_SLEEP : STATE_AWAKE;
969 u32 reg;
970
971 if (state == STATE_SLEEP) {
972 rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
973 rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
974 libconf->conf->beacon_int - 10);
975 rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
976 libconf->conf->listen_interval - 1);
977 rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
978
979 /* We must first disable autowake before it can be enabled */
980 rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
981 rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
982
983 rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
984 rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
985
986 rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005);
987 rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c);
988 rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);
989
990 rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);
991 } else {
992 rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
993 rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
994 rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
995 rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
996 rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
997 rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
998
999 rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
1000 rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018);
1001 rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);
1002
1003 rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
1004 }
1005}
1006
970static void rt61pci_config(struct rt2x00_dev *rt2x00dev, 1007static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
971 struct rt2x00lib_conf *libconf, 1008 struct rt2x00lib_conf *libconf,
972 const unsigned int flags) 1009 const unsigned int flags)
@@ -984,6 +1021,8 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
984 rt61pci_config_retry_limit(rt2x00dev, libconf); 1021 rt61pci_config_retry_limit(rt2x00dev, libconf);
985 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) 1022 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
986 rt61pci_config_duration(rt2x00dev, libconf); 1023 rt61pci_config_duration(rt2x00dev, libconf);
1024 if (flags & IEEE80211_CONF_CHANGE_PS)
1025 rt61pci_config_ps(rt2x00dev, libconf);
987} 1026}
988 1027
989/* 1028/*
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
index 65fe3332364a..86590c6de0ef 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/rt2x00/rt61pci.h
@@ -88,8 +88,10 @@
88 88
89/* 89/*
90 * SOFT_RESET_CSR 90 * SOFT_RESET_CSR
91 * FORCE_CLOCK_ON: Host force MAC clock ON
91 */ 92 */
92#define SOFT_RESET_CSR 0x0010 93#define SOFT_RESET_CSR 0x0010
94#define SOFT_RESET_CSR_FORCE_CLOCK_ON FIELD32(0x00000002)
93 95
94/* 96/*
95 * MCU_INT_SOURCE_CSR: MCU interrupt source/mask register. 97 * MCU_INT_SOURCE_CSR: MCU interrupt source/mask register.
@@ -1054,8 +1056,10 @@ struct hw_pairwise_ta_entry {
1054 1056
1055/* 1057/*
1056 * IO_CNTL_CSR 1058 * IO_CNTL_CSR
1059 * RF_PS: Set RF interface value to power save
1057 */ 1060 */
1058#define IO_CNTL_CSR 0x3498 1061#define IO_CNTL_CSR 0x3498
1062#define IO_CNTL_CSR_RF_PS FIELD32(0x00000004)
1059 1063
1060/* 1064/*
1061 * UART_INT_SOURCE_CSR 1065 * UART_INT_SOURCE_CSR
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 96a8d69f8790..ae3b31d0d511 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -844,6 +844,44 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
844 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); 844 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
845} 845}
846 846
847static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
848 struct rt2x00lib_conf *libconf)
849{
850 enum dev_state state =
851 (libconf->conf->flags & IEEE80211_CONF_PS) ?
852 STATE_SLEEP : STATE_AWAKE;
853 u32 reg;
854
855 if (state == STATE_SLEEP) {
856 rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
857 rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
858 libconf->conf->beacon_int - 10);
859 rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
860 libconf->conf->listen_interval - 1);
861 rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
862
863 /* We must first disable autowake before it can be enabled */
864 rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
865 rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
866
867 rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
868 rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
869
870 rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
871 USB_MODE_SLEEP, REGISTER_TIMEOUT);
872 } else {
873 rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
874 USB_MODE_WAKEUP, REGISTER_TIMEOUT);
875
876 rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
877 rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
878 rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
879 rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
880 rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
881 rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
882 }
883}
884
847static void rt73usb_config(struct rt2x00_dev *rt2x00dev, 885static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
848 struct rt2x00lib_conf *libconf, 886 struct rt2x00lib_conf *libconf,
849 const unsigned int flags) 887 const unsigned int flags)
@@ -861,6 +899,8 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
861 rt73usb_config_retry_limit(rt2x00dev, libconf); 899 rt73usb_config_retry_limit(rt2x00dev, libconf);
862 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) 900 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
863 rt73usb_config_duration(rt2x00dev, libconf); 901 rt73usb_config_duration(rt2x00dev, libconf);
902 if (flags & IEEE80211_CONF_CHANGE_PS)
903 rt73usb_config_ps(rt2x00dev, libconf);
864} 904}
865 905
866/* 906/*