diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800pci.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 229 |
1 files changed, 99 insertions, 130 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 6f11760117da..39b3846fa340 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -31,7 +31,6 @@ | |||
31 | Supported chipsets: RT2800E & RT2800ED. | 31 | Supported chipsets: RT2800E & RT2800ED. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/crc-ccitt.h> | ||
35 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
36 | #include <linux/etherdevice.h> | 35 | #include <linux/etherdevice.h> |
37 | #include <linux/init.h> | 36 | #include <linux/init.h> |
@@ -192,82 +191,14 @@ static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) | |||
192 | return FIRMWARE_RT2860; | 191 | return FIRMWARE_RT2860; |
193 | } | 192 | } |
194 | 193 | ||
195 | static int rt2800pci_check_firmware(struct rt2x00_dev *rt2x00dev, | 194 | static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, |
196 | const u8 *data, const size_t len) | 195 | const u8 *data, const size_t len) |
197 | { | 196 | { |
198 | u16 fw_crc; | ||
199 | u16 crc; | ||
200 | |||
201 | /* | ||
202 | * Only support 8kb firmware files. | ||
203 | */ | ||
204 | if (len != 8192) | ||
205 | return FW_BAD_LENGTH; | ||
206 | |||
207 | /* | ||
208 | * The last 2 bytes in the firmware array are the crc checksum itself, | ||
209 | * this means that we should never pass those 2 bytes to the crc | ||
210 | * algorithm. | ||
211 | */ | ||
212 | fw_crc = (data[len - 2] << 8 | data[len - 1]); | ||
213 | |||
214 | /* | ||
215 | * Use the crc ccitt algorithm. | ||
216 | * This will return the same value as the legacy driver which | ||
217 | * used bit ordering reversion on the both the firmware bytes | ||
218 | * before input input as well as on the final output. | ||
219 | * Obviously using crc ccitt directly is much more efficient. | ||
220 | */ | ||
221 | crc = crc_ccitt(~0, data, len - 2); | ||
222 | |||
223 | /* | ||
224 | * There is a small difference between the crc-itu-t + bitrev and | ||
225 | * the crc-ccitt crc calculation. In the latter method the 2 bytes | ||
226 | * will be swapped, use swab16 to convert the crc to the correct | ||
227 | * value. | ||
228 | */ | ||
229 | crc = swab16(crc); | ||
230 | |||
231 | return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; | ||
232 | } | ||
233 | |||
234 | static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
235 | const u8 *data, const size_t len) | ||
236 | { | ||
237 | unsigned int i; | ||
238 | u32 reg; | 197 | u32 reg; |
239 | 198 | ||
240 | /* | ||
241 | * Wait for stable hardware. | ||
242 | */ | ||
243 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
244 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
245 | if (reg && reg != ~0) | ||
246 | break; | ||
247 | msleep(1); | ||
248 | } | ||
249 | |||
250 | if (i == REGISTER_BUSY_COUNT) { | ||
251 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
252 | return -EBUSY; | ||
253 | } | ||
254 | |||
255 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); | ||
256 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); | 199 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); |
257 | 200 | ||
258 | /* | 201 | /* |
259 | * Disable DMA, will be reenabled later when enabling | ||
260 | * the radio. | ||
261 | */ | ||
262 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
263 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
264 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
265 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
266 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
267 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
268 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
269 | |||
270 | /* | ||
271 | * enable Host program ram write selection | 202 | * enable Host program ram write selection |
272 | */ | 203 | */ |
273 | reg = 0; | 204 | reg = 0; |
@@ -278,34 +209,11 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
278 | * Write firmware to device. | 209 | * Write firmware to device. |
279 | */ | 210 | */ |
280 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, | 211 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, |
281 | data, len); | 212 | data, len); |
282 | 213 | ||
283 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); | 214 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); |
284 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); | 215 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); |
285 | 216 | ||
286 | /* | ||
287 | * Wait for device to stabilize. | ||
288 | */ | ||
289 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
290 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
291 | if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) | ||
292 | break; | ||
293 | msleep(1); | ||
294 | } | ||
295 | |||
296 | if (i == REGISTER_BUSY_COUNT) { | ||
297 | ERROR(rt2x00dev, "PBF system register not ready.\n"); | ||
298 | return -EBUSY; | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * Disable interrupts | ||
303 | */ | ||
304 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF); | ||
305 | |||
306 | /* | ||
307 | * Initialize BBP R/W access agent | ||
308 | */ | ||
309 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | 217 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); |
310 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | 218 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); |
311 | 219 | ||
@@ -422,7 +330,8 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev, | |||
422 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 330 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
423 | enum dev_state state) | 331 | enum dev_state state) |
424 | { | 332 | { |
425 | int mask = (state == STATE_RADIO_IRQ_ON); | 333 | int mask = (state == STATE_RADIO_IRQ_ON) || |
334 | (state == STATE_RADIO_IRQ_ON_ISR); | ||
426 | u32 reg; | 335 | u32 reg; |
427 | 336 | ||
428 | /* | 337 | /* |
@@ -631,7 +540,9 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
631 | rt2800pci_toggle_rx(rt2x00dev, state); | 540 | rt2800pci_toggle_rx(rt2x00dev, state); |
632 | break; | 541 | break; |
633 | case STATE_RADIO_IRQ_ON: | 542 | case STATE_RADIO_IRQ_ON: |
543 | case STATE_RADIO_IRQ_ON_ISR: | ||
634 | case STATE_RADIO_IRQ_OFF: | 544 | case STATE_RADIO_IRQ_OFF: |
545 | case STATE_RADIO_IRQ_OFF_ISR: | ||
635 | rt2800pci_toggle_irq(rt2x00dev, state); | 546 | rt2800pci_toggle_irq(rt2x00dev, state); |
636 | break; | 547 | break; |
637 | case STATE_DEEP_SLEEP: | 548 | case STATE_DEEP_SLEEP: |
@@ -805,7 +716,7 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
805 | /* | 716 | /* |
806 | * Process the RXWI structure that is at the start of the buffer. | 717 | * Process the RXWI structure that is at the start of the buffer. |
807 | */ | 718 | */ |
808 | rt2800_process_rxwi(entry->skb, rxdesc); | 719 | rt2800_process_rxwi(entry, rxdesc); |
809 | 720 | ||
810 | /* | 721 | /* |
811 | * Set RX IDX in register to inform hardware that we have handled | 722 | * Set RX IDX in register to inform hardware that we have handled |
@@ -929,42 +840,74 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | |||
929 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | 840 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); |
930 | } | 841 | } |
931 | 842 | ||
932 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | 843 | static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) |
933 | { | 844 | { |
934 | struct rt2x00_dev *rt2x00dev = dev_instance; | 845 | struct rt2x00_dev *rt2x00dev = dev_instance; |
935 | u32 reg; | 846 | u32 reg = rt2x00dev->irqvalue[0]; |
936 | |||
937 | /* Read status and ACK all interrupts */ | ||
938 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
939 | rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
940 | 847 | ||
941 | if (!reg) | 848 | /* |
942 | return IRQ_NONE; | 849 | * 1 - Pre TBTT interrupt. |
850 | */ | ||
851 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) | ||
852 | rt2x00lib_pretbtt(rt2x00dev); | ||
943 | 853 | ||
944 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 854 | /* |
945 | return IRQ_HANDLED; | 855 | * 2 - Beacondone interrupt. |
856 | */ | ||
857 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) | ||
858 | rt2x00lib_beacondone(rt2x00dev); | ||
946 | 859 | ||
947 | /* | 860 | /* |
948 | * 1 - Rx ring done interrupt. | 861 | * 3 - Rx ring done interrupt. |
949 | */ | 862 | */ |
950 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) | 863 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) |
951 | rt2x00pci_rxdone(rt2x00dev); | 864 | rt2x00pci_rxdone(rt2x00dev); |
952 | 865 | ||
866 | /* | ||
867 | * 4 - Tx done interrupt. | ||
868 | */ | ||
953 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | 869 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) |
954 | rt2800pci_txdone(rt2x00dev); | 870 | rt2800pci_txdone(rt2x00dev); |
955 | 871 | ||
956 | /* | 872 | /* |
957 | * Current beacon was sent out, fetch the next one | 873 | * 5 - Auto wakeup interrupt. |
958 | */ | 874 | */ |
959 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) | ||
960 | rt2x00lib_beacondone(rt2x00dev); | ||
961 | |||
962 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | 875 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) |
963 | rt2800pci_wakeup(rt2x00dev); | 876 | rt2800pci_wakeup(rt2x00dev); |
964 | 877 | ||
878 | /* Enable interrupts again. */ | ||
879 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
880 | STATE_RADIO_IRQ_ON_ISR); | ||
881 | |||
965 | return IRQ_HANDLED; | 882 | return IRQ_HANDLED; |
966 | } | 883 | } |
967 | 884 | ||
885 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | ||
886 | { | ||
887 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
888 | u32 reg; | ||
889 | |||
890 | /* Read status and ACK all interrupts */ | ||
891 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
892 | rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
893 | |||
894 | if (!reg) | ||
895 | return IRQ_NONE; | ||
896 | |||
897 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
898 | return IRQ_HANDLED; | ||
899 | |||
900 | /* Store irqvalue for use in the interrupt thread. */ | ||
901 | rt2x00dev->irqvalue[0] = reg; | ||
902 | |||
903 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | ||
904 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
905 | STATE_RADIO_IRQ_OFF_ISR); | ||
906 | |||
907 | |||
908 | return IRQ_WAKE_THREAD; | ||
909 | } | ||
910 | |||
968 | /* | 911 | /* |
969 | * Device probe functions. | 912 | * Device probe functions. |
970 | */ | 913 | */ |
@@ -983,26 +926,10 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
983 | return rt2800_validate_eeprom(rt2x00dev); | 926 | return rt2800_validate_eeprom(rt2x00dev); |
984 | } | 927 | } |
985 | 928 | ||
986 | static const struct rt2800_ops rt2800pci_rt2800_ops = { | ||
987 | .register_read = rt2x00pci_register_read, | ||
988 | .register_read_lock = rt2x00pci_register_read, /* same for PCI */ | ||
989 | .register_write = rt2x00pci_register_write, | ||
990 | .register_write_lock = rt2x00pci_register_write, /* same for PCI */ | ||
991 | |||
992 | .register_multiread = rt2x00pci_register_multiread, | ||
993 | .register_multiwrite = rt2x00pci_register_multiwrite, | ||
994 | |||
995 | .regbusy_read = rt2x00pci_regbusy_read, | ||
996 | |||
997 | .drv_init_registers = rt2800pci_init_registers, | ||
998 | }; | ||
999 | |||
1000 | static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | 929 | static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) |
1001 | { | 930 | { |
1002 | int retval; | 931 | int retval; |
1003 | 932 | ||
1004 | rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops; | ||
1005 | |||
1006 | /* | 933 | /* |
1007 | * Allocate eeprom data. | 934 | * Allocate eeprom data. |
1008 | */ | 935 | */ |
@@ -1029,6 +956,12 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1029 | __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); | 956 | __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); |
1030 | 957 | ||
1031 | /* | 958 | /* |
959 | * This device has a pre tbtt interrupt and thus fetches | ||
960 | * a new beacon directly prior to transmission. | ||
961 | */ | ||
962 | __set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags); | ||
963 | |||
964 | /* | ||
1032 | * This device requires firmware. | 965 | * This device requires firmware. |
1033 | */ | 966 | */ |
1034 | if (!rt2x00_is_soc(rt2x00dev)) | 967 | if (!rt2x00_is_soc(rt2x00dev)) |
@@ -1037,6 +970,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1037 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | 970 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); |
1038 | if (!modparam_nohwcrypt) | 971 | if (!modparam_nohwcrypt) |
1039 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 972 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
973 | __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); | ||
1040 | 974 | ||
1041 | /* | 975 | /* |
1042 | * Set the rssi offset. | 976 | * Set the rssi offset. |
@@ -1046,12 +980,46 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1046 | return 0; | 980 | return 0; |
1047 | } | 981 | } |
1048 | 982 | ||
983 | static const struct ieee80211_ops rt2800pci_mac80211_ops = { | ||
984 | .tx = rt2x00mac_tx, | ||
985 | .start = rt2x00mac_start, | ||
986 | .stop = rt2x00mac_stop, | ||
987 | .add_interface = rt2x00mac_add_interface, | ||
988 | .remove_interface = rt2x00mac_remove_interface, | ||
989 | .config = rt2x00mac_config, | ||
990 | .configure_filter = rt2x00mac_configure_filter, | ||
991 | .set_key = rt2x00mac_set_key, | ||
992 | .sw_scan_start = rt2x00mac_sw_scan_start, | ||
993 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
994 | .get_stats = rt2x00mac_get_stats, | ||
995 | .get_tkip_seq = rt2800_get_tkip_seq, | ||
996 | .set_rts_threshold = rt2800_set_rts_threshold, | ||
997 | .bss_info_changed = rt2x00mac_bss_info_changed, | ||
998 | .conf_tx = rt2800_conf_tx, | ||
999 | .get_tsf = rt2800_get_tsf, | ||
1000 | .rfkill_poll = rt2x00mac_rfkill_poll, | ||
1001 | .ampdu_action = rt2800_ampdu_action, | ||
1002 | }; | ||
1003 | |||
1004 | static const struct rt2800_ops rt2800pci_rt2800_ops = { | ||
1005 | .register_read = rt2x00pci_register_read, | ||
1006 | .register_read_lock = rt2x00pci_register_read, /* same for PCI */ | ||
1007 | .register_write = rt2x00pci_register_write, | ||
1008 | .register_write_lock = rt2x00pci_register_write, /* same for PCI */ | ||
1009 | .register_multiread = rt2x00pci_register_multiread, | ||
1010 | .register_multiwrite = rt2x00pci_register_multiwrite, | ||
1011 | .regbusy_read = rt2x00pci_regbusy_read, | ||
1012 | .drv_write_firmware = rt2800pci_write_firmware, | ||
1013 | .drv_init_registers = rt2800pci_init_registers, | ||
1014 | }; | ||
1015 | |||
1049 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 1016 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
1050 | .irq_handler = rt2800pci_interrupt, | 1017 | .irq_handler = rt2800pci_interrupt, |
1018 | .irq_handler_thread = rt2800pci_interrupt_thread, | ||
1051 | .probe_hw = rt2800pci_probe_hw, | 1019 | .probe_hw = rt2800pci_probe_hw, |
1052 | .get_firmware_name = rt2800pci_get_firmware_name, | 1020 | .get_firmware_name = rt2800pci_get_firmware_name, |
1053 | .check_firmware = rt2800pci_check_firmware, | 1021 | .check_firmware = rt2800_check_firmware, |
1054 | .load_firmware = rt2800pci_load_firmware, | 1022 | .load_firmware = rt2800_load_firmware, |
1055 | .initialize = rt2x00pci_initialize, | 1023 | .initialize = rt2x00pci_initialize, |
1056 | .uninitialize = rt2x00pci_uninitialize, | 1024 | .uninitialize = rt2x00pci_uninitialize, |
1057 | .get_entry_state = rt2800pci_get_entry_state, | 1025 | .get_entry_state = rt2800pci_get_entry_state, |
@@ -1109,7 +1077,8 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
1109 | .tx = &rt2800pci_queue_tx, | 1077 | .tx = &rt2800pci_queue_tx, |
1110 | .bcn = &rt2800pci_queue_bcn, | 1078 | .bcn = &rt2800pci_queue_bcn, |
1111 | .lib = &rt2800pci_rt2x00_ops, | 1079 | .lib = &rt2800pci_rt2x00_ops, |
1112 | .hw = &rt2800_mac80211_ops, | 1080 | .drv = &rt2800pci_rt2800_ops, |
1081 | .hw = &rt2800pci_mac80211_ops, | ||
1113 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 1082 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
1114 | .debugfs = &rt2800_rt2x00debug, | 1083 | .debugfs = &rt2800_rt2x00debug, |
1115 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | 1084 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ |