diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 178 |
1 files changed, 45 insertions, 133 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 4f85f7b4244..5a2dfe87c6b 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -28,7 +28,6 @@ | |||
28 | Supported chipsets: RT2800U. | 28 | Supported chipsets: RT2800U. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/crc-ccitt.h> | ||
32 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
33 | #include <linux/etherdevice.h> | 32 | #include <linux/etherdevice.h> |
34 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -57,84 +56,10 @@ static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) | |||
57 | return FIRMWARE_RT2870; | 56 | return FIRMWARE_RT2870; |
58 | } | 57 | } |
59 | 58 | ||
60 | static bool rt2800usb_check_crc(const u8 *data, const size_t len) | 59 | static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, |
61 | { | ||
62 | u16 fw_crc; | ||
63 | u16 crc; | ||
64 | |||
65 | /* | ||
66 | * The last 2 bytes in the firmware array are the crc checksum itself, | ||
67 | * this means that we should never pass those 2 bytes to the crc | ||
68 | * algorithm. | ||
69 | */ | ||
70 | fw_crc = (data[len - 2] << 8 | data[len - 1]); | ||
71 | |||
72 | /* | ||
73 | * Use the crc ccitt algorithm. | ||
74 | * This will return the same value as the legacy driver which | ||
75 | * used bit ordering reversion on the both the firmware bytes | ||
76 | * before input input as well as on the final output. | ||
77 | * Obviously using crc ccitt directly is much more efficient. | ||
78 | */ | ||
79 | crc = crc_ccitt(~0, data, len - 2); | ||
80 | |||
81 | /* | ||
82 | * There is a small difference between the crc-itu-t + bitrev and | ||
83 | * the crc-ccitt crc calculation. In the latter method the 2 bytes | ||
84 | * will be swapped, use swab16 to convert the crc to the correct | ||
85 | * value. | ||
86 | */ | ||
87 | crc = swab16(crc); | ||
88 | |||
89 | return fw_crc == crc; | ||
90 | } | ||
91 | |||
92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
93 | const u8 *data, const size_t len) | 60 | const u8 *data, const size_t len) |
94 | { | 61 | { |
95 | size_t offset = 0; | ||
96 | |||
97 | /* | ||
98 | * Firmware files: | ||
99 | * There are 2 variations of the rt2870 firmware. | ||
100 | * a) size: 4kb | ||
101 | * b) size: 8kb | ||
102 | * Note that (b) contains 2 separate firmware blobs of 4k | ||
103 | * within the file. The first blob is the same firmware as (a), | ||
104 | * but the second blob is for the additional chipsets. | ||
105 | */ | ||
106 | if (len != 4096 && len != 8192) | ||
107 | return FW_BAD_LENGTH; | ||
108 | |||
109 | /* | ||
110 | * Check if we need the upper 4kb firmware data or not. | ||
111 | */ | ||
112 | if ((len == 4096) && | ||
113 | !rt2x00_rt(rt2x00dev, RT2860) && | ||
114 | !rt2x00_rt(rt2x00dev, RT2872) && | ||
115 | !rt2x00_rt(rt2x00dev, RT3070)) | ||
116 | return FW_BAD_VERSION; | ||
117 | |||
118 | /* | ||
119 | * 8kb firmware files must be checked as if it were | ||
120 | * 2 separate firmware files. | ||
121 | */ | ||
122 | while (offset < len) { | ||
123 | if (!rt2800usb_check_crc(data + offset, 4096)) | ||
124 | return FW_BAD_CRC; | ||
125 | |||
126 | offset += 4096; | ||
127 | } | ||
128 | |||
129 | return FW_OK; | ||
130 | } | ||
131 | |||
132 | static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
133 | const u8 *data, const size_t len) | ||
134 | { | ||
135 | unsigned int i; | ||
136 | int status; | 62 | int status; |
137 | u32 reg; | ||
138 | u32 offset; | 63 | u32 offset; |
139 | u32 length; | 64 | u32 length; |
140 | 65 | ||
@@ -152,21 +77,6 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
152 | } | 77 | } |
153 | 78 | ||
154 | /* | 79 | /* |
155 | * Wait for stable hardware. | ||
156 | */ | ||
157 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
158 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
159 | if (reg && reg != ~0) | ||
160 | break; | ||
161 | msleep(1); | ||
162 | } | ||
163 | |||
164 | if (i == REGISTER_BUSY_COUNT) { | ||
165 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
166 | return -EBUSY; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * Write firmware to device. | 80 | * Write firmware to device. |
171 | */ | 81 | */ |
172 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, | 82 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, |
@@ -203,28 +113,6 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
203 | udelay(10); | 113 | udelay(10); |
204 | } | 114 | } |
205 | 115 | ||
206 | /* | ||
207 | * Wait for device to stabilize. | ||
208 | */ | ||
209 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
210 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
211 | if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) | ||
212 | break; | ||
213 | msleep(1); | ||
214 | } | ||
215 | |||
216 | if (i == REGISTER_BUSY_COUNT) { | ||
217 | ERROR(rt2x00dev, "PBF system register not ready.\n"); | ||
218 | return -EBUSY; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Initialize firmware. | ||
223 | */ | ||
224 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | ||
225 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | ||
226 | msleep(1); | ||
227 | |||
228 | return 0; | 116 | return 0; |
229 | } | 117 | } |
230 | 118 | ||
@@ -406,7 +294,9 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
406 | rt2800usb_toggle_rx(rt2x00dev, state); | 294 | rt2800usb_toggle_rx(rt2x00dev, state); |
407 | break; | 295 | break; |
408 | case STATE_RADIO_IRQ_ON: | 296 | case STATE_RADIO_IRQ_ON: |
297 | case STATE_RADIO_IRQ_ON_ISR: | ||
409 | case STATE_RADIO_IRQ_OFF: | 298 | case STATE_RADIO_IRQ_OFF: |
299 | case STATE_RADIO_IRQ_OFF_ISR: | ||
410 | /* No support, but no error either */ | 300 | /* No support, but no error either */ |
411 | break; | 301 | break; |
412 | case STATE_DEEP_SLEEP: | 302 | case STATE_DEEP_SLEEP: |
@@ -563,7 +453,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
563 | /* | 453 | /* |
564 | * Process the RXWI structure. | 454 | * Process the RXWI structure. |
565 | */ | 455 | */ |
566 | rt2800_process_rxwi(entry->skb, rxdesc); | 456 | rt2800_process_rxwi(entry, rxdesc); |
567 | } | 457 | } |
568 | 458 | ||
569 | /* | 459 | /* |
@@ -580,26 +470,10 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
580 | return rt2800_validate_eeprom(rt2x00dev); | 470 | return rt2800_validate_eeprom(rt2x00dev); |
581 | } | 471 | } |
582 | 472 | ||
583 | static const struct rt2800_ops rt2800usb_rt2800_ops = { | ||
584 | .register_read = rt2x00usb_register_read, | ||
585 | .register_read_lock = rt2x00usb_register_read_lock, | ||
586 | .register_write = rt2x00usb_register_write, | ||
587 | .register_write_lock = rt2x00usb_register_write_lock, | ||
588 | |||
589 | .register_multiread = rt2x00usb_register_multiread, | ||
590 | .register_multiwrite = rt2x00usb_register_multiwrite, | ||
591 | |||
592 | .regbusy_read = rt2x00usb_regbusy_read, | ||
593 | |||
594 | .drv_init_registers = rt2800usb_init_registers, | ||
595 | }; | ||
596 | |||
597 | static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | 473 | static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) |
598 | { | 474 | { |
599 | int retval; | 475 | int retval; |
600 | 476 | ||
601 | rt2x00dev->priv = (void *)&rt2800usb_rt2800_ops; | ||
602 | |||
603 | /* | 477 | /* |
604 | * Allocate eeprom data. | 478 | * Allocate eeprom data. |
605 | */ | 479 | */ |
@@ -632,6 +506,8 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
632 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | 506 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); |
633 | if (!modparam_nohwcrypt) | 507 | if (!modparam_nohwcrypt) |
634 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 508 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
509 | __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); | ||
510 | __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); | ||
635 | 511 | ||
636 | /* | 512 | /* |
637 | * Set the rssi offset. | 513 | * Set the rssi offset. |
@@ -641,11 +517,45 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
641 | return 0; | 517 | return 0; |
642 | } | 518 | } |
643 | 519 | ||
520 | static const struct ieee80211_ops rt2800usb_mac80211_ops = { | ||
521 | .tx = rt2x00mac_tx, | ||
522 | .start = rt2x00mac_start, | ||
523 | .stop = rt2x00mac_stop, | ||
524 | .add_interface = rt2x00mac_add_interface, | ||
525 | .remove_interface = rt2x00mac_remove_interface, | ||
526 | .config = rt2x00mac_config, | ||
527 | .configure_filter = rt2x00mac_configure_filter, | ||
528 | .set_tim = rt2x00mac_set_tim, | ||
529 | .set_key = rt2x00mac_set_key, | ||
530 | .sw_scan_start = rt2x00mac_sw_scan_start, | ||
531 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
532 | .get_stats = rt2x00mac_get_stats, | ||
533 | .get_tkip_seq = rt2800_get_tkip_seq, | ||
534 | .set_rts_threshold = rt2800_set_rts_threshold, | ||
535 | .bss_info_changed = rt2x00mac_bss_info_changed, | ||
536 | .conf_tx = rt2800_conf_tx, | ||
537 | .get_tsf = rt2800_get_tsf, | ||
538 | .rfkill_poll = rt2x00mac_rfkill_poll, | ||
539 | .ampdu_action = rt2800_ampdu_action, | ||
540 | }; | ||
541 | |||
542 | static const struct rt2800_ops rt2800usb_rt2800_ops = { | ||
543 | .register_read = rt2x00usb_register_read, | ||
544 | .register_read_lock = rt2x00usb_register_read_lock, | ||
545 | .register_write = rt2x00usb_register_write, | ||
546 | .register_write_lock = rt2x00usb_register_write_lock, | ||
547 | .register_multiread = rt2x00usb_register_multiread, | ||
548 | .register_multiwrite = rt2x00usb_register_multiwrite, | ||
549 | .regbusy_read = rt2x00usb_regbusy_read, | ||
550 | .drv_write_firmware = rt2800usb_write_firmware, | ||
551 | .drv_init_registers = rt2800usb_init_registers, | ||
552 | }; | ||
553 | |||
644 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | 554 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { |
645 | .probe_hw = rt2800usb_probe_hw, | 555 | .probe_hw = rt2800usb_probe_hw, |
646 | .get_firmware_name = rt2800usb_get_firmware_name, | 556 | .get_firmware_name = rt2800usb_get_firmware_name, |
647 | .check_firmware = rt2800usb_check_firmware, | 557 | .check_firmware = rt2800_check_firmware, |
648 | .load_firmware = rt2800usb_load_firmware, | 558 | .load_firmware = rt2800_load_firmware, |
649 | .initialize = rt2x00usb_initialize, | 559 | .initialize = rt2x00usb_initialize, |
650 | .uninitialize = rt2x00usb_uninitialize, | 560 | .uninitialize = rt2x00usb_uninitialize, |
651 | .clear_entry = rt2x00usb_clear_entry, | 561 | .clear_entry = rt2x00usb_clear_entry, |
@@ -654,6 +564,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
654 | .link_stats = rt2800_link_stats, | 564 | .link_stats = rt2800_link_stats, |
655 | .reset_tuner = rt2800_reset_tuner, | 565 | .reset_tuner = rt2800_reset_tuner, |
656 | .link_tuner = rt2800_link_tuner, | 566 | .link_tuner = rt2800_link_tuner, |
567 | .watchdog = rt2x00usb_watchdog, | ||
657 | .write_tx_desc = rt2800usb_write_tx_desc, | 568 | .write_tx_desc = rt2800usb_write_tx_desc, |
658 | .write_tx_data = rt2800usb_write_tx_data, | 569 | .write_tx_data = rt2800usb_write_tx_data, |
659 | .write_beacon = rt2800_write_beacon, | 570 | .write_beacon = rt2800_write_beacon, |
@@ -703,7 +614,8 @@ static const struct rt2x00_ops rt2800usb_ops = { | |||
703 | .tx = &rt2800usb_queue_tx, | 614 | .tx = &rt2800usb_queue_tx, |
704 | .bcn = &rt2800usb_queue_bcn, | 615 | .bcn = &rt2800usb_queue_bcn, |
705 | .lib = &rt2800usb_rt2x00_ops, | 616 | .lib = &rt2800usb_rt2x00_ops, |
706 | .hw = &rt2800_mac80211_ops, | 617 | .drv = &rt2800usb_rt2800_ops, |
618 | .hw = &rt2800usb_mac80211_ops, | ||
707 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 619 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
708 | .debugfs = &rt2800_rt2x00debug, | 620 | .debugfs = &rt2800_rt2x00debug, |
709 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | 621 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ |