diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 434 |
1 files changed, 341 insertions, 93 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index d3cf0cc39500..b66e0fd8f0fa 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -33,6 +33,7 @@ | |||
33 | Abstract: rt2800 generic device routines. | 33 | Abstract: rt2800 generic device routines. |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <linux/crc-ccitt.h> | ||
36 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
37 | #include <linux/module.h> | 38 | #include <linux/module.h> |
38 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
@@ -272,6 +273,160 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) | |||
272 | } | 273 | } |
273 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); | 274 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); |
274 | 275 | ||
276 | static bool rt2800_check_firmware_crc(const u8 *data, const size_t len) | ||
277 | { | ||
278 | u16 fw_crc; | ||
279 | u16 crc; | ||
280 | |||
281 | /* | ||
282 | * The last 2 bytes in the firmware array are the crc checksum itself, | ||
283 | * this means that we should never pass those 2 bytes to the crc | ||
284 | * algorithm. | ||
285 | */ | ||
286 | fw_crc = (data[len - 2] << 8 | data[len - 1]); | ||
287 | |||
288 | /* | ||
289 | * Use the crc ccitt algorithm. | ||
290 | * This will return the same value as the legacy driver which | ||
291 | * used bit ordering reversion on the both the firmware bytes | ||
292 | * before input input as well as on the final output. | ||
293 | * Obviously using crc ccitt directly is much more efficient. | ||
294 | */ | ||
295 | crc = crc_ccitt(~0, data, len - 2); | ||
296 | |||
297 | /* | ||
298 | * There is a small difference between the crc-itu-t + bitrev and | ||
299 | * the crc-ccitt crc calculation. In the latter method the 2 bytes | ||
300 | * will be swapped, use swab16 to convert the crc to the correct | ||
301 | * value. | ||
302 | */ | ||
303 | crc = swab16(crc); | ||
304 | |||
305 | return fw_crc == crc; | ||
306 | } | ||
307 | |||
308 | int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
309 | const u8 *data, const size_t len) | ||
310 | { | ||
311 | size_t offset = 0; | ||
312 | size_t fw_len; | ||
313 | bool multiple; | ||
314 | |||
315 | /* | ||
316 | * PCI(e) & SOC devices require firmware with a length | ||
317 | * of 8kb. USB devices require firmware files with a length | ||
318 | * of 4kb. Certain USB chipsets however require different firmware, | ||
319 | * which Ralink only provides attached to the original firmware | ||
320 | * file. Thus for USB devices, firmware files have a length | ||
321 | * which is a multiple of 4kb. | ||
322 | */ | ||
323 | if (rt2x00_is_usb(rt2x00dev)) { | ||
324 | fw_len = 4096; | ||
325 | multiple = true; | ||
326 | } else { | ||
327 | fw_len = 8192; | ||
328 | multiple = true; | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * Validate the firmware length | ||
333 | */ | ||
334 | if (len != fw_len && (!multiple || (len % fw_len) != 0)) | ||
335 | return FW_BAD_LENGTH; | ||
336 | |||
337 | /* | ||
338 | * Check if the chipset requires one of the upper parts | ||
339 | * of the firmware. | ||
340 | */ | ||
341 | if (rt2x00_is_usb(rt2x00dev) && | ||
342 | !rt2x00_rt(rt2x00dev, RT2860) && | ||
343 | !rt2x00_rt(rt2x00dev, RT2872) && | ||
344 | !rt2x00_rt(rt2x00dev, RT3070) && | ||
345 | ((len / fw_len) == 1)) | ||
346 | return FW_BAD_VERSION; | ||
347 | |||
348 | /* | ||
349 | * 8kb firmware files must be checked as if it were | ||
350 | * 2 separate firmware files. | ||
351 | */ | ||
352 | while (offset < len) { | ||
353 | if (!rt2800_check_firmware_crc(data + offset, fw_len)) | ||
354 | return FW_BAD_CRC; | ||
355 | |||
356 | offset += fw_len; | ||
357 | } | ||
358 | |||
359 | return FW_OK; | ||
360 | } | ||
361 | EXPORT_SYMBOL_GPL(rt2800_check_firmware); | ||
362 | |||
363 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
364 | const u8 *data, const size_t len) | ||
365 | { | ||
366 | unsigned int i; | ||
367 | u32 reg; | ||
368 | |||
369 | /* | ||
370 | * Wait for stable hardware. | ||
371 | */ | ||
372 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
373 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
374 | if (reg && reg != ~0) | ||
375 | break; | ||
376 | msleep(1); | ||
377 | } | ||
378 | |||
379 | if (i == REGISTER_BUSY_COUNT) { | ||
380 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
381 | return -EBUSY; | ||
382 | } | ||
383 | |||
384 | if (rt2x00_is_pci(rt2x00dev)) | ||
385 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); | ||
386 | |||
387 | /* | ||
388 | * Disable DMA, will be reenabled later when enabling | ||
389 | * the radio. | ||
390 | */ | ||
391 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
392 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
393 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
394 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
395 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
396 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
397 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
398 | |||
399 | /* | ||
400 | * Write firmware to the device. | ||
401 | */ | ||
402 | rt2800_drv_write_firmware(rt2x00dev, data, len); | ||
403 | |||
404 | /* | ||
405 | * Wait for device to stabilize. | ||
406 | */ | ||
407 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
408 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
409 | if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) | ||
410 | break; | ||
411 | msleep(1); | ||
412 | } | ||
413 | |||
414 | if (i == REGISTER_BUSY_COUNT) { | ||
415 | ERROR(rt2x00dev, "PBF system register not ready.\n"); | ||
416 | return -EBUSY; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Initialize firmware. | ||
421 | */ | ||
422 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | ||
423 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | ||
424 | msleep(1); | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | EXPORT_SYMBOL_GPL(rt2800_load_firmware); | ||
429 | |||
275 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | 430 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) |
276 | { | 431 | { |
277 | u32 word; | 432 | u32 word; |
@@ -325,9 +480,53 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | |||
325 | } | 480 | } |
326 | EXPORT_SYMBOL_GPL(rt2800_write_txwi); | 481 | EXPORT_SYMBOL_GPL(rt2800_write_txwi); |
327 | 482 | ||
328 | void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc) | 483 | static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) |
329 | { | 484 | { |
330 | __le32 *rxwi = (__le32 *) skb->data; | 485 | int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); |
486 | int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); | ||
487 | int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2); | ||
488 | u16 eeprom; | ||
489 | u8 offset0; | ||
490 | u8 offset1; | ||
491 | u8 offset2; | ||
492 | |||
493 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) { | ||
494 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); | ||
495 | offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); | ||
496 | offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); | ||
497 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); | ||
498 | offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2); | ||
499 | } else { | ||
500 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom); | ||
501 | offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0); | ||
502 | offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1); | ||
503 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); | ||
504 | offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2); | ||
505 | } | ||
506 | |||
507 | /* | ||
508 | * Convert the value from the descriptor into the RSSI value | ||
509 | * If the value in the descriptor is 0, it is considered invalid | ||
510 | * and the default (extremely low) rssi value is assumed | ||
511 | */ | ||
512 | rssi0 = (rssi0) ? (-12 - offset0 - rt2x00dev->lna_gain - rssi0) : -128; | ||
513 | rssi1 = (rssi1) ? (-12 - offset1 - rt2x00dev->lna_gain - rssi1) : -128; | ||
514 | rssi2 = (rssi2) ? (-12 - offset2 - rt2x00dev->lna_gain - rssi2) : -128; | ||
515 | |||
516 | /* | ||
517 | * mac80211 only accepts a single RSSI value. Calculating the | ||
518 | * average doesn't deliver a fair answer either since -60:-60 would | ||
519 | * be considered equally good as -50:-70 while the second is the one | ||
520 | * which gives less energy... | ||
521 | */ | ||
522 | rssi0 = max(rssi0, rssi1); | ||
523 | return max(rssi0, rssi2); | ||
524 | } | ||
525 | |||
526 | void rt2800_process_rxwi(struct queue_entry *entry, | ||
527 | struct rxdone_entry_desc *rxdesc) | ||
528 | { | ||
529 | __le32 *rxwi = (__le32 *) entry->skb->data; | ||
331 | u32 word; | 530 | u32 word; |
332 | 531 | ||
333 | rt2x00_desc_read(rxwi, 0, &word); | 532 | rt2x00_desc_read(rxwi, 0, &word); |
@@ -358,14 +557,15 @@ void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc) | |||
358 | 557 | ||
359 | rt2x00_desc_read(rxwi, 2, &word); | 558 | rt2x00_desc_read(rxwi, 2, &word); |
360 | 559 | ||
361 | rxdesc->rssi = | 560 | /* |
362 | (rt2x00_get_field32(word, RXWI_W2_RSSI0) + | 561 | * Convert descriptor AGC value to RSSI value. |
363 | rt2x00_get_field32(word, RXWI_W2_RSSI1)) / 2; | 562 | */ |
563 | rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word); | ||
364 | 564 | ||
365 | /* | 565 | /* |
366 | * Remove RXWI descriptor from start of buffer. | 566 | * Remove RXWI descriptor from start of buffer. |
367 | */ | 567 | */ |
368 | skb_pull(skb, RXWI_DESC_SIZE); | 568 | skb_pull(entry->skb, RXWI_DESC_SIZE); |
369 | } | 569 | } |
370 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); | 570 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); |
371 | 571 | ||
@@ -428,7 +628,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | |||
428 | dev_kfree_skb_any(entry->skb); | 628 | dev_kfree_skb_any(entry->skb); |
429 | entry->skb = NULL; | 629 | entry->skb = NULL; |
430 | } | 630 | } |
431 | EXPORT_SYMBOL(rt2800_write_beacon); | 631 | EXPORT_SYMBOL_GPL(rt2800_write_beacon); |
432 | 632 | ||
433 | static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, | 633 | static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, |
434 | unsigned int beacon_base) | 634 | unsigned int beacon_base) |
@@ -760,8 +960,18 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | |||
760 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | 960 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); |
761 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); | 961 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); |
762 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, | 962 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, |
763 | (conf->sync == TSF_SYNC_BEACON)); | 963 | (conf->sync == TSF_SYNC_ADHOC || |
964 | conf->sync == TSF_SYNC_AP_NONE)); | ||
764 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 965 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
966 | |||
967 | /* | ||
968 | * Enable pre tbtt interrupt for beaconing modes | ||
969 | */ | ||
970 | rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
971 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, | ||
972 | (conf->sync == TSF_SYNC_AP_NONE)); | ||
973 | rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
974 | |||
765 | } | 975 | } |
766 | 976 | ||
767 | if (flags & CONFIG_UPDATE_MAC) { | 977 | if (flags & CONFIG_UPDATE_MAC) { |
@@ -1086,66 +1296,115 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
1086 | } | 1296 | } |
1087 | 1297 | ||
1088 | static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | 1298 | static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, |
1089 | const int txpower) | 1299 | const int max_txpower) |
1090 | { | 1300 | { |
1301 | u8 txpower; | ||
1302 | u8 max_value = (u8)max_txpower; | ||
1303 | u16 eeprom; | ||
1304 | int i; | ||
1091 | u32 reg; | 1305 | u32 reg; |
1092 | u32 value = TXPOWER_G_TO_DEV(txpower); | ||
1093 | u8 r1; | 1306 | u8 r1; |
1307 | u32 offset; | ||
1094 | 1308 | ||
1309 | /* | ||
1310 | * set to normal tx power mode: +/- 0dBm | ||
1311 | */ | ||
1095 | rt2800_bbp_read(rt2x00dev, 1, &r1); | 1312 | rt2800_bbp_read(rt2x00dev, 1, &r1); |
1096 | rt2x00_set_field8(&r1, BBP1_TX_POWER, 0); | 1313 | rt2x00_set_field8(&r1, BBP1_TX_POWER, 0); |
1097 | rt2800_bbp_write(rt2x00dev, 1, r1); | 1314 | rt2800_bbp_write(rt2x00dev, 1, r1); |
1098 | 1315 | ||
1099 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | 1316 | /* |
1100 | rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); | 1317 | * The eeprom contains the tx power values for each rate. These |
1101 | rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); | 1318 | * values map to 100% tx power. Each 16bit word contains four tx |
1102 | rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); | 1319 | * power values and the order is the same as used in the TX_PWR_CFG |
1103 | rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); | 1320 | * registers. |
1104 | rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); | 1321 | */ |
1105 | rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); | 1322 | offset = TX_PWR_CFG_0; |
1106 | rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); | 1323 | |
1107 | rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); | 1324 | for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) { |
1108 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, reg); | 1325 | /* just to be safe */ |
1109 | 1326 | if (offset > TX_PWR_CFG_4) | |
1110 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_1, ®); | 1327 | break; |
1111 | rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); | 1328 | |
1112 | rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); | 1329 | rt2800_register_read(rt2x00dev, offset, ®); |
1113 | rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); | 1330 | |
1114 | rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); | 1331 | /* read the next four txpower values */ |
1115 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); | 1332 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i, |
1116 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); | 1333 | &eeprom); |
1117 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); | 1334 | |
1118 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); | 1335 | /* TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS, |
1119 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, reg); | 1336 | * TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12, |
1120 | 1337 | * TX_PWR_CFG_4: unknown */ | |
1121 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_2, ®); | 1338 | txpower = rt2x00_get_field16(eeprom, |
1122 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); | 1339 | EEPROM_TXPOWER_BYRATE_RATE0); |
1123 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); | 1340 | rt2x00_set_field32(®, TX_PWR_CFG_RATE0, |
1124 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); | 1341 | min(txpower, max_value)); |
1125 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); | 1342 | |
1126 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); | 1343 | /* TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS, |
1127 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); | 1344 | * TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13, |
1128 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); | 1345 | * TX_PWR_CFG_4: unknown */ |
1129 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); | 1346 | txpower = rt2x00_get_field16(eeprom, |
1130 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, reg); | 1347 | EEPROM_TXPOWER_BYRATE_RATE1); |
1131 | 1348 | rt2x00_set_field32(®, TX_PWR_CFG_RATE1, | |
1132 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_3, ®); | 1349 | min(txpower, max_value)); |
1133 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); | 1350 | |
1134 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); | 1351 | /* TX_PWR_CFG_0: 55MBS, TX_PWR_CFG_1: 48MBS, |
1135 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); | 1352 | * TX_PWR_CFG_2: MCS6, TX_PWR_CFG_3: MCS14, |
1136 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); | 1353 | * TX_PWR_CFG_4: unknown */ |
1137 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); | 1354 | txpower = rt2x00_get_field16(eeprom, |
1138 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); | 1355 | EEPROM_TXPOWER_BYRATE_RATE2); |
1139 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); | 1356 | rt2x00_set_field32(®, TX_PWR_CFG_RATE2, |
1140 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); | 1357 | min(txpower, max_value)); |
1141 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, reg); | 1358 | |
1142 | 1359 | /* TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS, | |
1143 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_4, ®); | 1360 | * TX_PWR_CFG_2: MCS7, TX_PWR_CFG_3: MCS15, |
1144 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); | 1361 | * TX_PWR_CFG_4: unknown */ |
1145 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); | 1362 | txpower = rt2x00_get_field16(eeprom, |
1146 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); | 1363 | EEPROM_TXPOWER_BYRATE_RATE3); |
1147 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); | 1364 | rt2x00_set_field32(®, TX_PWR_CFG_RATE3, |
1148 | rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, reg); | 1365 | min(txpower, max_value)); |
1366 | |||
1367 | /* read the next four txpower values */ | ||
1368 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1, | ||
1369 | &eeprom); | ||
1370 | |||
1371 | /* TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0, | ||
1372 | * TX_PWR_CFG_2: MCS8, TX_PWR_CFG_3: unknown, | ||
1373 | * TX_PWR_CFG_4: unknown */ | ||
1374 | txpower = rt2x00_get_field16(eeprom, | ||
1375 | EEPROM_TXPOWER_BYRATE_RATE0); | ||
1376 | rt2x00_set_field32(®, TX_PWR_CFG_RATE4, | ||
1377 | min(txpower, max_value)); | ||
1378 | |||
1379 | /* TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1, | ||
1380 | * TX_PWR_CFG_2: MCS9, TX_PWR_CFG_3: unknown, | ||
1381 | * TX_PWR_CFG_4: unknown */ | ||
1382 | txpower = rt2x00_get_field16(eeprom, | ||
1383 | EEPROM_TXPOWER_BYRATE_RATE1); | ||
1384 | rt2x00_set_field32(®, TX_PWR_CFG_RATE5, | ||
1385 | min(txpower, max_value)); | ||
1386 | |||
1387 | /* TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2, | ||
1388 | * TX_PWR_CFG_2: MCS10, TX_PWR_CFG_3: unknown, | ||
1389 | * TX_PWR_CFG_4: unknown */ | ||
1390 | txpower = rt2x00_get_field16(eeprom, | ||
1391 | EEPROM_TXPOWER_BYRATE_RATE2); | ||
1392 | rt2x00_set_field32(®, TX_PWR_CFG_RATE6, | ||
1393 | min(txpower, max_value)); | ||
1394 | |||
1395 | /* TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3, | ||
1396 | * TX_PWR_CFG_2: MCS11, TX_PWR_CFG_3: unknown, | ||
1397 | * TX_PWR_CFG_4: unknown */ | ||
1398 | txpower = rt2x00_get_field16(eeprom, | ||
1399 | EEPROM_TXPOWER_BYRATE_RATE3); | ||
1400 | rt2x00_set_field32(®, TX_PWR_CFG_RATE7, | ||
1401 | min(txpower, max_value)); | ||
1402 | |||
1403 | rt2800_register_write(rt2x00dev, offset, reg); | ||
1404 | |||
1405 | /* next TX_PWR_CFG register */ | ||
1406 | offset += 4; | ||
1407 | } | ||
1149 | } | 1408 | } |
1150 | 1409 | ||
1151 | static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, | 1410 | static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, |
@@ -1316,7 +1575,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1316 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | 1575 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); |
1317 | 1576 | ||
1318 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 1577 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
1319 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); | 1578 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 1600); |
1320 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); | 1579 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); |
1321 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); | 1580 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); |
1322 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | 1581 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); |
@@ -1638,6 +1897,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1638 | rt2800_register_read(rt2x00dev, TX_STA_CNT1, ®); | 1897 | rt2800_register_read(rt2x00dev, TX_STA_CNT1, ®); |
1639 | rt2800_register_read(rt2x00dev, TX_STA_CNT2, ®); | 1898 | rt2800_register_read(rt2x00dev, TX_STA_CNT2, ®); |
1640 | 1899 | ||
1900 | /* | ||
1901 | * Setup leadtime for pre tbtt interrupt to 6ms | ||
1902 | */ | ||
1903 | rt2800_register_read(rt2x00dev, INT_TIMER_CFG, ®); | ||
1904 | rt2x00_set_field32(®, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4); | ||
1905 | rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg); | ||
1906 | |||
1641 | return 0; | 1907 | return 0; |
1642 | } | 1908 | } |
1643 | EXPORT_SYMBOL_GPL(rt2800_init_registers); | 1909 | EXPORT_SYMBOL_GPL(rt2800_init_registers); |
@@ -2630,8 +2896,8 @@ EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode); | |||
2630 | /* | 2896 | /* |
2631 | * IEEE80211 stack callback functions. | 2897 | * IEEE80211 stack callback functions. |
2632 | */ | 2898 | */ |
2633 | static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, | 2899 | void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, |
2634 | u32 *iv32, u16 *iv16) | 2900 | u16 *iv16) |
2635 | { | 2901 | { |
2636 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2902 | struct rt2x00_dev *rt2x00dev = hw->priv; |
2637 | struct mac_iveiv_entry iveiv_entry; | 2903 | struct mac_iveiv_entry iveiv_entry; |
@@ -2644,8 +2910,9 @@ static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, | |||
2644 | memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16)); | 2910 | memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16)); |
2645 | memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32)); | 2911 | memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32)); |
2646 | } | 2912 | } |
2913 | EXPORT_SYMBOL_GPL(rt2800_get_tkip_seq); | ||
2647 | 2914 | ||
2648 | static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 2915 | int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
2649 | { | 2916 | { |
2650 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2917 | struct rt2x00_dev *rt2x00dev = hw->priv; |
2651 | u32 reg; | 2918 | u32 reg; |
@@ -2681,9 +2948,10 @@ static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
2681 | 2948 | ||
2682 | return 0; | 2949 | return 0; |
2683 | } | 2950 | } |
2951 | EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold); | ||
2684 | 2952 | ||
2685 | static int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | 2953 | int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, |
2686 | const struct ieee80211_tx_queue_params *params) | 2954 | const struct ieee80211_tx_queue_params *params) |
2687 | { | 2955 | { |
2688 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2956 | struct rt2x00_dev *rt2x00dev = hw->priv; |
2689 | struct data_queue *queue; | 2957 | struct data_queue *queue; |
@@ -2748,8 +3016,9 @@ static int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
2748 | 3016 | ||
2749 | return 0; | 3017 | return 0; |
2750 | } | 3018 | } |
3019 | EXPORT_SYMBOL_GPL(rt2800_conf_tx); | ||
2751 | 3020 | ||
2752 | static u64 rt2800_get_tsf(struct ieee80211_hw *hw) | 3021 | u64 rt2800_get_tsf(struct ieee80211_hw *hw) |
2753 | { | 3022 | { |
2754 | struct rt2x00_dev *rt2x00dev = hw->priv; | 3023 | struct rt2x00_dev *rt2x00dev = hw->priv; |
2755 | u64 tsf; | 3024 | u64 tsf; |
@@ -2762,12 +3031,11 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw) | |||
2762 | 3031 | ||
2763 | return tsf; | 3032 | return tsf; |
2764 | } | 3033 | } |
3034 | EXPORT_SYMBOL_GPL(rt2800_get_tsf); | ||
2765 | 3035 | ||
2766 | static int rt2800_ampdu_action(struct ieee80211_hw *hw, | 3036 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2767 | struct ieee80211_vif *vif, | 3037 | enum ieee80211_ampdu_mlme_action action, |
2768 | enum ieee80211_ampdu_mlme_action action, | 3038 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2769 | struct ieee80211_sta *sta, | ||
2770 | u16 tid, u16 *ssn) | ||
2771 | { | 3039 | { |
2772 | int ret = 0; | 3040 | int ret = 0; |
2773 | 3041 | ||
@@ -2791,27 +3059,7 @@ static int rt2800_ampdu_action(struct ieee80211_hw *hw, | |||
2791 | 3059 | ||
2792 | return ret; | 3060 | return ret; |
2793 | } | 3061 | } |
2794 | 3062 | EXPORT_SYMBOL_GPL(rt2800_ampdu_action); | |
2795 | const struct ieee80211_ops rt2800_mac80211_ops = { | ||
2796 | .tx = rt2x00mac_tx, | ||
2797 | .start = rt2x00mac_start, | ||
2798 | .stop = rt2x00mac_stop, | ||
2799 | .add_interface = rt2x00mac_add_interface, | ||
2800 | .remove_interface = rt2x00mac_remove_interface, | ||
2801 | .config = rt2x00mac_config, | ||
2802 | .configure_filter = rt2x00mac_configure_filter, | ||
2803 | .set_tim = rt2x00mac_set_tim, | ||
2804 | .set_key = rt2x00mac_set_key, | ||
2805 | .get_stats = rt2x00mac_get_stats, | ||
2806 | .get_tkip_seq = rt2800_get_tkip_seq, | ||
2807 | .set_rts_threshold = rt2800_set_rts_threshold, | ||
2808 | .bss_info_changed = rt2x00mac_bss_info_changed, | ||
2809 | .conf_tx = rt2800_conf_tx, | ||
2810 | .get_tsf = rt2800_get_tsf, | ||
2811 | .rfkill_poll = rt2x00mac_rfkill_poll, | ||
2812 | .ampdu_action = rt2800_ampdu_action, | ||
2813 | }; | ||
2814 | EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); | ||
2815 | 3063 | ||
2816 | MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz"); | 3064 | MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz"); |
2817 | MODULE_VERSION(DRV_VERSION); | 3065 | MODULE_VERSION(DRV_VERSION); |