diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-07-13 15:57:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-07-13 15:57:29 -0400 |
commit | e300d955debdadf599c36e47eb0bc16f5976215c (patch) | |
tree | 8fafcc789dc06e90665e6eee6388af228bbd2fd7 /drivers/net/wireless/rt2x00 | |
parent | 242647bcf8464860f173f3d4d4ab3490d3558518 (diff) | |
parent | 815868e7b5c207ba42d5b317ccc51f8112732268 (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/wl12xx/wl1271_cmd.h
Diffstat (limited to 'drivers/net/wireless/rt2x00')
22 files changed, 1019 insertions, 476 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 3bedf566c8ee..5063e01410e5 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -586,9 +586,11 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev, | |||
586 | static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, | 586 | static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, |
587 | struct link_qual *qual, u8 vgc_level) | 587 | struct link_qual *qual, u8 vgc_level) |
588 | { | 588 | { |
589 | rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); | 589 | if (qual->vgc_level_reg != vgc_level) { |
590 | qual->vgc_level = vgc_level; | 590 | rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); |
591 | qual->vgc_level_reg = vgc_level; | 591 | qual->vgc_level = vgc_level; |
592 | qual->vgc_level_reg = vgc_level; | ||
593 | } | ||
592 | } | 594 | } |
593 | 595 | ||
594 | static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev, | 596 | static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev, |
@@ -877,7 +879,8 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev, | |||
877 | static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 879 | static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
878 | enum dev_state state) | 880 | enum dev_state state) |
879 | { | 881 | { |
880 | int mask = (state == STATE_RADIO_IRQ_OFF); | 882 | int mask = (state == STATE_RADIO_IRQ_OFF) || |
883 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
881 | u32 reg; | 884 | u32 reg; |
882 | 885 | ||
883 | /* | 886 | /* |
@@ -978,7 +981,9 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
978 | rt2400pci_toggle_rx(rt2x00dev, state); | 981 | rt2400pci_toggle_rx(rt2x00dev, state); |
979 | break; | 982 | break; |
980 | case STATE_RADIO_IRQ_ON: | 983 | case STATE_RADIO_IRQ_ON: |
984 | case STATE_RADIO_IRQ_ON_ISR: | ||
981 | case STATE_RADIO_IRQ_OFF: | 985 | case STATE_RADIO_IRQ_OFF: |
986 | case STATE_RADIO_IRQ_OFF_ISR: | ||
982 | rt2400pci_toggle_irq(rt2x00dev, state); | 987 | rt2400pci_toggle_irq(rt2x00dev, state); |
983 | break; | 988 | break; |
984 | case STATE_DEEP_SLEEP: | 989 | case STATE_DEEP_SLEEP: |
@@ -1233,23 +1238,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1233 | } | 1238 | } |
1234 | } | 1239 | } |
1235 | 1240 | ||
1236 | static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | 1241 | static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance) |
1237 | { | 1242 | { |
1238 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1243 | struct rt2x00_dev *rt2x00dev = dev_instance; |
1239 | u32 reg; | 1244 | u32 reg = rt2x00dev->irqvalue[0]; |
1240 | |||
1241 | /* | ||
1242 | * Get the interrupt sources & saved to local variable. | ||
1243 | * Write register value back to clear pending interrupts. | ||
1244 | */ | ||
1245 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | ||
1246 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | ||
1247 | |||
1248 | if (!reg) | ||
1249 | return IRQ_NONE; | ||
1250 | |||
1251 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
1252 | return IRQ_HANDLED; | ||
1253 | 1245 | ||
1254 | /* | 1246 | /* |
1255 | * Handle interrupts, walk through all bits | 1247 | * Handle interrupts, walk through all bits |
@@ -1287,9 +1279,40 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | |||
1287 | if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) | 1279 | if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) |
1288 | rt2400pci_txdone(rt2x00dev, QID_AC_BK); | 1280 | rt2400pci_txdone(rt2x00dev, QID_AC_BK); |
1289 | 1281 | ||
1282 | /* Enable interrupts again. */ | ||
1283 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
1284 | STATE_RADIO_IRQ_ON_ISR); | ||
1290 | return IRQ_HANDLED; | 1285 | return IRQ_HANDLED; |
1291 | } | 1286 | } |
1292 | 1287 | ||
1288 | static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | ||
1289 | { | ||
1290 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
1291 | u32 reg; | ||
1292 | |||
1293 | /* | ||
1294 | * Get the interrupt sources & saved to local variable. | ||
1295 | * Write register value back to clear pending interrupts. | ||
1296 | */ | ||
1297 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | ||
1298 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | ||
1299 | |||
1300 | if (!reg) | ||
1301 | return IRQ_NONE; | ||
1302 | |||
1303 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
1304 | return IRQ_HANDLED; | ||
1305 | |||
1306 | /* Store irqvalues for use in the interrupt thread. */ | ||
1307 | rt2x00dev->irqvalue[0] = reg; | ||
1308 | |||
1309 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | ||
1310 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
1311 | STATE_RADIO_IRQ_OFF_ISR); | ||
1312 | |||
1313 | return IRQ_WAKE_THREAD; | ||
1314 | } | ||
1315 | |||
1293 | /* | 1316 | /* |
1294 | * Device probe functions. | 1317 | * Device probe functions. |
1295 | */ | 1318 | */ |
@@ -1399,8 +1422,8 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1399 | /* | 1422 | /* |
1400 | * Check if the BBP tuning should be enabled. | 1423 | * Check if the BBP tuning should be enabled. |
1401 | */ | 1424 | */ |
1402 | if (!rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) | 1425 | if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) |
1403 | __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); | 1426 | __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); |
1404 | 1427 | ||
1405 | return 0; | 1428 | return 0; |
1406 | } | 1429 | } |
@@ -1566,7 +1589,8 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { | |||
1566 | .remove_interface = rt2x00mac_remove_interface, | 1589 | .remove_interface = rt2x00mac_remove_interface, |
1567 | .config = rt2x00mac_config, | 1590 | .config = rt2x00mac_config, |
1568 | .configure_filter = rt2x00mac_configure_filter, | 1591 | .configure_filter = rt2x00mac_configure_filter, |
1569 | .set_tim = rt2x00mac_set_tim, | 1592 | .sw_scan_start = rt2x00mac_sw_scan_start, |
1593 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
1570 | .get_stats = rt2x00mac_get_stats, | 1594 | .get_stats = rt2x00mac_get_stats, |
1571 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1595 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1572 | .conf_tx = rt2400pci_conf_tx, | 1596 | .conf_tx = rt2400pci_conf_tx, |
@@ -1577,6 +1601,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { | |||
1577 | 1601 | ||
1578 | static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | 1602 | static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { |
1579 | .irq_handler = rt2400pci_interrupt, | 1603 | .irq_handler = rt2400pci_interrupt, |
1604 | .irq_handler_thread = rt2400pci_interrupt_thread, | ||
1580 | .probe_hw = rt2400pci_probe_hw, | 1605 | .probe_hw = rt2400pci_probe_hw, |
1581 | .initialize = rt2x00pci_initialize, | 1606 | .initialize = rt2x00pci_initialize, |
1582 | .uninitialize = rt2x00pci_uninitialize, | 1607 | .uninitialize = rt2x00pci_uninitialize, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 69d231d83952..c2a555d5376b 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -626,6 +626,7 @@ static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, | |||
626 | { | 626 | { |
627 | if (qual->vgc_level_reg != vgc_level) { | 627 | if (qual->vgc_level_reg != vgc_level) { |
628 | rt2500pci_bbp_write(rt2x00dev, 17, vgc_level); | 628 | rt2500pci_bbp_write(rt2x00dev, 17, vgc_level); |
629 | qual->vgc_level = vgc_level; | ||
629 | qual->vgc_level_reg = vgc_level; | 630 | qual->vgc_level_reg = vgc_level; |
630 | } | 631 | } |
631 | } | 632 | } |
@@ -700,13 +701,10 @@ dynamic_cca_tune: | |||
700 | * R17 is inside the dynamic tuning range, | 701 | * R17 is inside the dynamic tuning range, |
701 | * start tuning the link based on the false cca counter. | 702 | * start tuning the link based on the false cca counter. |
702 | */ | 703 | */ |
703 | if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) { | 704 | if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) |
704 | rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg); | 705 | rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg); |
705 | qual->vgc_level = qual->vgc_level_reg; | 706 | else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) |
706 | } else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) { | ||
707 | rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg); | 707 | rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg); |
708 | qual->vgc_level = qual->vgc_level_reg; | ||
709 | } | ||
710 | } | 708 | } |
711 | 709 | ||
712 | /* | 710 | /* |
@@ -1035,7 +1033,8 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev, | |||
1035 | static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 1033 | static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
1036 | enum dev_state state) | 1034 | enum dev_state state) |
1037 | { | 1035 | { |
1038 | int mask = (state == STATE_RADIO_IRQ_OFF); | 1036 | int mask = (state == STATE_RADIO_IRQ_OFF) || |
1037 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
1039 | u32 reg; | 1038 | u32 reg; |
1040 | 1039 | ||
1041 | /* | 1040 | /* |
@@ -1136,7 +1135,9 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1136 | rt2500pci_toggle_rx(rt2x00dev, state); | 1135 | rt2500pci_toggle_rx(rt2x00dev, state); |
1137 | break; | 1136 | break; |
1138 | case STATE_RADIO_IRQ_ON: | 1137 | case STATE_RADIO_IRQ_ON: |
1138 | case STATE_RADIO_IRQ_ON_ISR: | ||
1139 | case STATE_RADIO_IRQ_OFF: | 1139 | case STATE_RADIO_IRQ_OFF: |
1140 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1140 | rt2500pci_toggle_irq(rt2x00dev, state); | 1141 | rt2500pci_toggle_irq(rt2x00dev, state); |
1141 | break; | 1142 | break; |
1142 | case STATE_DEEP_SLEEP: | 1143 | case STATE_DEEP_SLEEP: |
@@ -1369,23 +1370,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1369 | } | 1370 | } |
1370 | } | 1371 | } |
1371 | 1372 | ||
1372 | static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | 1373 | static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance) |
1373 | { | 1374 | { |
1374 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1375 | struct rt2x00_dev *rt2x00dev = dev_instance; |
1375 | u32 reg; | 1376 | u32 reg = rt2x00dev->irqvalue[0]; |
1376 | |||
1377 | /* | ||
1378 | * Get the interrupt sources & saved to local variable. | ||
1379 | * Write register value back to clear pending interrupts. | ||
1380 | */ | ||
1381 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | ||
1382 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | ||
1383 | |||
1384 | if (!reg) | ||
1385 | return IRQ_NONE; | ||
1386 | |||
1387 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
1388 | return IRQ_HANDLED; | ||
1389 | 1377 | ||
1390 | /* | 1378 | /* |
1391 | * Handle interrupts, walk through all bits | 1379 | * Handle interrupts, walk through all bits |
@@ -1423,9 +1411,41 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | |||
1423 | if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) | 1411 | if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) |
1424 | rt2500pci_txdone(rt2x00dev, QID_AC_BK); | 1412 | rt2500pci_txdone(rt2x00dev, QID_AC_BK); |
1425 | 1413 | ||
1414 | /* Enable interrupts again. */ | ||
1415 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
1416 | STATE_RADIO_IRQ_ON_ISR); | ||
1417 | |||
1426 | return IRQ_HANDLED; | 1418 | return IRQ_HANDLED; |
1427 | } | 1419 | } |
1428 | 1420 | ||
1421 | static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | ||
1422 | { | ||
1423 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
1424 | u32 reg; | ||
1425 | |||
1426 | /* | ||
1427 | * Get the interrupt sources & saved to local variable. | ||
1428 | * Write register value back to clear pending interrupts. | ||
1429 | */ | ||
1430 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | ||
1431 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | ||
1432 | |||
1433 | if (!reg) | ||
1434 | return IRQ_NONE; | ||
1435 | |||
1436 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
1437 | return IRQ_HANDLED; | ||
1438 | |||
1439 | /* Store irqvalues for use in the interrupt thread. */ | ||
1440 | rt2x00dev->irqvalue[0] = reg; | ||
1441 | |||
1442 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | ||
1443 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
1444 | STATE_RADIO_IRQ_OFF_ISR); | ||
1445 | |||
1446 | return IRQ_WAKE_THREAD; | ||
1447 | } | ||
1448 | |||
1429 | /* | 1449 | /* |
1430 | * Device probe functions. | 1450 | * Device probe functions. |
1431 | */ | 1451 | */ |
@@ -1557,9 +1577,8 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1557 | * Check if the BBP tuning should be enabled. | 1577 | * Check if the BBP tuning should be enabled. |
1558 | */ | 1578 | */ |
1559 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); | 1579 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); |
1560 | 1580 | if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) | |
1561 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) | 1581 | __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); |
1562 | __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); | ||
1563 | 1582 | ||
1564 | /* | 1583 | /* |
1565 | * Read the RSSI <-> dBm offset information. | 1584 | * Read the RSSI <-> dBm offset information. |
@@ -1864,7 +1883,8 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { | |||
1864 | .remove_interface = rt2x00mac_remove_interface, | 1883 | .remove_interface = rt2x00mac_remove_interface, |
1865 | .config = rt2x00mac_config, | 1884 | .config = rt2x00mac_config, |
1866 | .configure_filter = rt2x00mac_configure_filter, | 1885 | .configure_filter = rt2x00mac_configure_filter, |
1867 | .set_tim = rt2x00mac_set_tim, | 1886 | .sw_scan_start = rt2x00mac_sw_scan_start, |
1887 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
1868 | .get_stats = rt2x00mac_get_stats, | 1888 | .get_stats = rt2x00mac_get_stats, |
1869 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1889 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1870 | .conf_tx = rt2x00mac_conf_tx, | 1890 | .conf_tx = rt2x00mac_conf_tx, |
@@ -1875,6 +1895,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { | |||
1875 | 1895 | ||
1876 | static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { | 1896 | static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { |
1877 | .irq_handler = rt2500pci_interrupt, | 1897 | .irq_handler = rt2500pci_interrupt, |
1898 | .irq_handler_thread = rt2500pci_interrupt_thread, | ||
1878 | .probe_hw = rt2500pci_probe_hw, | 1899 | .probe_hw = rt2500pci_probe_hw, |
1879 | .initialize = rt2x00pci_initialize, | 1900 | .initialize = rt2x00pci_initialize, |
1880 | .uninitialize = rt2x00pci_uninitialize, | 1901 | .uninitialize = rt2x00pci_uninitialize, |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 44205526013f..242d59558b79 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1004,7 +1004,9 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1004 | rt2500usb_toggle_rx(rt2x00dev, state); | 1004 | rt2500usb_toggle_rx(rt2x00dev, state); |
1005 | break; | 1005 | break; |
1006 | case STATE_RADIO_IRQ_ON: | 1006 | case STATE_RADIO_IRQ_ON: |
1007 | case STATE_RADIO_IRQ_ON_ISR: | ||
1007 | case STATE_RADIO_IRQ_OFF: | 1008 | case STATE_RADIO_IRQ_OFF: |
1009 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1008 | /* No support, but no error either */ | 1010 | /* No support, but no error either */ |
1009 | break; | 1011 | break; |
1010 | case STATE_DEEP_SLEEP: | 1012 | case STATE_DEEP_SLEEP: |
@@ -1471,13 +1473,6 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1471 | __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); | 1473 | __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); |
1472 | 1474 | ||
1473 | /* | 1475 | /* |
1474 | * Check if the BBP tuning should be disabled. | ||
1475 | */ | ||
1476 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); | ||
1477 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) | ||
1478 | __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); | ||
1479 | |||
1480 | /* | ||
1481 | * Read the RSSI <-> dBm offset information. | 1476 | * Read the RSSI <-> dBm offset information. |
1482 | */ | 1477 | */ |
1483 | rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom); | 1478 | rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom); |
@@ -1743,7 +1738,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1743 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 1738 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
1744 | __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); | 1739 | __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); |
1745 | } | 1740 | } |
1746 | __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); | 1741 | __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); |
1747 | 1742 | ||
1748 | /* | 1743 | /* |
1749 | * Set the rssi offset. | 1744 | * Set the rssi offset. |
@@ -1763,6 +1758,8 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { | |||
1763 | .configure_filter = rt2x00mac_configure_filter, | 1758 | .configure_filter = rt2x00mac_configure_filter, |
1764 | .set_tim = rt2x00mac_set_tim, | 1759 | .set_tim = rt2x00mac_set_tim, |
1765 | .set_key = rt2x00mac_set_key, | 1760 | .set_key = rt2x00mac_set_key, |
1761 | .sw_scan_start = rt2x00mac_sw_scan_start, | ||
1762 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
1766 | .get_stats = rt2x00mac_get_stats, | 1763 | .get_stats = rt2x00mac_get_stats, |
1767 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1764 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1768 | .conf_tx = rt2x00mac_conf_tx, | 1765 | .conf_tx = rt2x00mac_conf_tx, |
@@ -1778,6 +1775,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { | |||
1778 | .rfkill_poll = rt2500usb_rfkill_poll, | 1775 | .rfkill_poll = rt2500usb_rfkill_poll, |
1779 | .link_stats = rt2500usb_link_stats, | 1776 | .link_stats = rt2500usb_link_stats, |
1780 | .reset_tuner = rt2500usb_reset_tuner, | 1777 | .reset_tuner = rt2500usb_reset_tuner, |
1778 | .watchdog = rt2x00usb_watchdog, | ||
1781 | .write_tx_desc = rt2500usb_write_tx_desc, | 1779 | .write_tx_desc = rt2500usb_write_tx_desc, |
1782 | .write_beacon = rt2500usb_write_beacon, | 1780 | .write_beacon = rt2500usb_write_beacon, |
1783 | .get_tx_data_len = rt2500usb_get_tx_data_len, | 1781 | .get_tx_data_len = rt2500usb_get_tx_data_len, |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 552f9f4c73d6..ed4ebcdde7c9 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -74,7 +74,7 @@ | |||
74 | * Signal information. | 74 | * Signal information. |
75 | * Default offset is required for RSSI <-> dBm conversion. | 75 | * Default offset is required for RSSI <-> dBm conversion. |
76 | */ | 76 | */ |
77 | #define DEFAULT_RSSI_OFFSET 120 /* FIXME */ | 77 | #define DEFAULT_RSSI_OFFSET 120 |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * Register layout information. | 80 | * Register layout information. |
@@ -719,14 +719,20 @@ | |||
719 | #define TBTT_TIMER 0x1124 | 719 | #define TBTT_TIMER 0x1124 |
720 | 720 | ||
721 | /* | 721 | /* |
722 | * INT_TIMER_CFG: | 722 | * INT_TIMER_CFG: timer configuration |
723 | * PRE_TBTT_TIMER: leadtime to tbtt for pretbtt interrupt in units of 1/16 TU | ||
724 | * GP_TIMER: period of general purpose timer in units of 1/16 TU | ||
723 | */ | 725 | */ |
724 | #define INT_TIMER_CFG 0x1128 | 726 | #define INT_TIMER_CFG 0x1128 |
727 | #define INT_TIMER_CFG_PRE_TBTT_TIMER FIELD32(0x0000ffff) | ||
728 | #define INT_TIMER_CFG_GP_TIMER FIELD32(0xffff0000) | ||
725 | 729 | ||
726 | /* | 730 | /* |
727 | * INT_TIMER_EN: GP-timer and pre-tbtt Int enable | 731 | * INT_TIMER_EN: GP-timer and pre-tbtt Int enable |
728 | */ | 732 | */ |
729 | #define INT_TIMER_EN 0x112c | 733 | #define INT_TIMER_EN 0x112c |
734 | #define INT_TIMER_EN_PRE_TBTT_TIMER FIELD32(0x00000001) | ||
735 | #define INT_TIMER_EN_GP_TIMER FIELD32(0x00000002) | ||
730 | 736 | ||
731 | /* | 737 | /* |
732 | * CH_IDLE_STA: channel idle time | 738 | * CH_IDLE_STA: channel idle time |
@@ -803,6 +809,18 @@ | |||
803 | #define EDCA_TID_AC_MAP 0x1310 | 809 | #define EDCA_TID_AC_MAP 0x1310 |
804 | 810 | ||
805 | /* | 811 | /* |
812 | * TX_PWR_CFG: | ||
813 | */ | ||
814 | #define TX_PWR_CFG_RATE0 FIELD32(0x0000000f) | ||
815 | #define TX_PWR_CFG_RATE1 FIELD32(0x000000f0) | ||
816 | #define TX_PWR_CFG_RATE2 FIELD32(0x00000f00) | ||
817 | #define TX_PWR_CFG_RATE3 FIELD32(0x0000f000) | ||
818 | #define TX_PWR_CFG_RATE4 FIELD32(0x000f0000) | ||
819 | #define TX_PWR_CFG_RATE5 FIELD32(0x00f00000) | ||
820 | #define TX_PWR_CFG_RATE6 FIELD32(0x0f000000) | ||
821 | #define TX_PWR_CFG_RATE7 FIELD32(0xf0000000) | ||
822 | |||
823 | /* | ||
806 | * TX_PWR_CFG_0: | 824 | * TX_PWR_CFG_0: |
807 | */ | 825 | */ |
808 | #define TX_PWR_CFG_0 0x1314 | 826 | #define TX_PWR_CFG_0 0x1314 |
@@ -1853,9 +1871,15 @@ struct mac_iveiv_entry { | |||
1853 | #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) | 1871 | #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) |
1854 | 1872 | ||
1855 | /* | 1873 | /* |
1856 | * EEPROM TXpower byrate: 20MHZ power | 1874 | * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode |
1857 | */ | 1875 | */ |
1858 | #define EEPROM_TXPOWER_BYRATE 0x006f | 1876 | #define EEPROM_TXPOWER_BYRATE 0x006f |
1877 | #define EEPROM_TXPOWER_BYRATE_SIZE 9 | ||
1878 | |||
1879 | #define EEPROM_TXPOWER_BYRATE_RATE0 FIELD16(0x000f) | ||
1880 | #define EEPROM_TXPOWER_BYRATE_RATE1 FIELD16(0x00f0) | ||
1881 | #define EEPROM_TXPOWER_BYRATE_RATE2 FIELD16(0x0f00) | ||
1882 | #define EEPROM_TXPOWER_BYRATE_RATE3 FIELD16(0xf000) | ||
1859 | 1883 | ||
1860 | /* | 1884 | /* |
1861 | * EEPROM BBP. | 1885 | * EEPROM BBP. |
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); |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 8313dbf441a5..091641e3c5e2 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -41,6 +41,8 @@ struct rt2800_ops { | |||
41 | const unsigned int offset, | 41 | const unsigned int offset, |
42 | const struct rt2x00_field32 field, u32 *reg); | 42 | const struct rt2x00_field32 field, u32 *reg); |
43 | 43 | ||
44 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, | ||
45 | const u8 *data, const size_t len); | ||
44 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); | 46 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); |
45 | }; | 47 | }; |
46 | 48 | ||
@@ -48,7 +50,7 @@ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, | |||
48 | const unsigned int offset, | 50 | const unsigned int offset, |
49 | u32 *value) | 51 | u32 *value) |
50 | { | 52 | { |
51 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 53 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
52 | 54 | ||
53 | rt2800ops->register_read(rt2x00dev, offset, value); | 55 | rt2800ops->register_read(rt2x00dev, offset, value); |
54 | } | 56 | } |
@@ -57,7 +59,7 @@ static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev, | |||
57 | const unsigned int offset, | 59 | const unsigned int offset, |
58 | u32 *value) | 60 | u32 *value) |
59 | { | 61 | { |
60 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 62 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
61 | 63 | ||
62 | rt2800ops->register_read_lock(rt2x00dev, offset, value); | 64 | rt2800ops->register_read_lock(rt2x00dev, offset, value); |
63 | } | 65 | } |
@@ -66,7 +68,7 @@ static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev, | |||
66 | const unsigned int offset, | 68 | const unsigned int offset, |
67 | u32 value) | 69 | u32 value) |
68 | { | 70 | { |
69 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 71 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
70 | 72 | ||
71 | rt2800ops->register_write(rt2x00dev, offset, value); | 73 | rt2800ops->register_write(rt2x00dev, offset, value); |
72 | } | 74 | } |
@@ -75,7 +77,7 @@ static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev, | |||
75 | const unsigned int offset, | 77 | const unsigned int offset, |
76 | u32 value) | 78 | u32 value) |
77 | { | 79 | { |
78 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 80 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
79 | 81 | ||
80 | rt2800ops->register_write_lock(rt2x00dev, offset, value); | 82 | rt2800ops->register_write_lock(rt2x00dev, offset, value); |
81 | } | 83 | } |
@@ -84,7 +86,7 @@ static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev, | |||
84 | const unsigned int offset, | 86 | const unsigned int offset, |
85 | void *value, const u32 length) | 87 | void *value, const u32 length) |
86 | { | 88 | { |
87 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 89 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
88 | 90 | ||
89 | rt2800ops->register_multiread(rt2x00dev, offset, value, length); | 91 | rt2800ops->register_multiread(rt2x00dev, offset, value, length); |
90 | } | 92 | } |
@@ -94,7 +96,7 @@ static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev, | |||
94 | const void *value, | 96 | const void *value, |
95 | const u32 length) | 97 | const u32 length) |
96 | { | 98 | { |
97 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 99 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
98 | 100 | ||
99 | rt2800ops->register_multiwrite(rt2x00dev, offset, value, length); | 101 | rt2800ops->register_multiwrite(rt2x00dev, offset, value, length); |
100 | } | 102 | } |
@@ -104,14 +106,22 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
104 | const struct rt2x00_field32 field, | 106 | const struct rt2x00_field32 field, |
105 | u32 *reg) | 107 | u32 *reg) |
106 | { | 108 | { |
107 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 109 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
108 | 110 | ||
109 | return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); | 111 | return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); |
110 | } | 112 | } |
111 | 113 | ||
114 | static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev, | ||
115 | const u8 *data, const size_t len) | ||
116 | { | ||
117 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; | ||
118 | |||
119 | return rt2800ops->drv_write_firmware(rt2x00dev, data, len); | ||
120 | } | ||
121 | |||
112 | static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) | 122 | static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) |
113 | { | 123 | { |
114 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | 124 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
115 | 125 | ||
116 | return rt2800ops->drv_init_registers(rt2x00dev); | 126 | return rt2800ops->drv_init_registers(rt2x00dev); |
117 | } | 127 | } |
@@ -120,8 +130,13 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
120 | const u8 command, const u8 token, | 130 | const u8 command, const u8 token, |
121 | const u8 arg0, const u8 arg1); | 131 | const u8 arg0, const u8 arg1); |
122 | 132 | ||
133 | int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
134 | const u8 *data, const size_t len); | ||
135 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
136 | const u8 *data, const size_t len); | ||
137 | |||
123 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); | 138 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); |
124 | void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); | 139 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); |
125 | 140 | ||
126 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); | 141 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); |
127 | 142 | ||
@@ -159,6 +174,14 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev); | |||
159 | int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev); | 174 | int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev); |
160 | int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev); | 175 | int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev); |
161 | 176 | ||
162 | extern const struct ieee80211_ops rt2800_mac80211_ops; | 177 | void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, |
178 | u16 *iv16); | ||
179 | int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value); | ||
180 | int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | ||
181 | const struct ieee80211_tx_queue_params *params); | ||
182 | u64 rt2800_get_tsf(struct ieee80211_hw *hw); | ||
183 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
184 | enum ieee80211_ampdu_mlme_action action, | ||
185 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | ||
163 | 186 | ||
164 | #endif /* RT2800LIB_H */ | 187 | #endif /* RT2800LIB_H */ |
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 */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 4f85f7b42441..5a2dfe87c6b6 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 */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 788b0e452cc7..c21af38cc5af 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -332,6 +332,11 @@ struct link { | |||
332 | * Work structure for scheduling periodic link tuning. | 332 | * Work structure for scheduling periodic link tuning. |
333 | */ | 333 | */ |
334 | struct delayed_work work; | 334 | struct delayed_work work; |
335 | |||
336 | /* | ||
337 | * Work structure for scheduling periodic watchdog monitoring. | ||
338 | */ | ||
339 | struct delayed_work watchdog_work; | ||
335 | }; | 340 | }; |
336 | 341 | ||
337 | /* | 342 | /* |
@@ -510,6 +515,11 @@ struct rt2x00lib_ops { | |||
510 | irq_handler_t irq_handler; | 515 | irq_handler_t irq_handler; |
511 | 516 | ||
512 | /* | 517 | /* |
518 | * Threaded Interrupt handlers. | ||
519 | */ | ||
520 | irq_handler_t irq_handler_thread; | ||
521 | |||
522 | /* | ||
513 | * Device init handlers. | 523 | * Device init handlers. |
514 | */ | 524 | */ |
515 | int (*probe_hw) (struct rt2x00_dev *rt2x00dev); | 525 | int (*probe_hw) (struct rt2x00_dev *rt2x00dev); |
@@ -543,6 +553,7 @@ struct rt2x00lib_ops { | |||
543 | struct link_qual *qual); | 553 | struct link_qual *qual); |
544 | void (*link_tuner) (struct rt2x00_dev *rt2x00dev, | 554 | void (*link_tuner) (struct rt2x00_dev *rt2x00dev, |
545 | struct link_qual *qual, const u32 count); | 555 | struct link_qual *qual, const u32 count); |
556 | void (*watchdog) (struct rt2x00_dev *rt2x00dev); | ||
546 | 557 | ||
547 | /* | 558 | /* |
548 | * TX control handlers | 559 | * TX control handlers |
@@ -610,6 +621,7 @@ struct rt2x00_ops { | |||
610 | const struct data_queue_desc *bcn; | 621 | const struct data_queue_desc *bcn; |
611 | const struct data_queue_desc *atim; | 622 | const struct data_queue_desc *atim; |
612 | const struct rt2x00lib_ops *lib; | 623 | const struct rt2x00lib_ops *lib; |
624 | const void *drv; | ||
613 | const struct ieee80211_ops *hw; | 625 | const struct ieee80211_ops *hw; |
614 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 626 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
615 | const struct rt2x00debug *debugfs; | 627 | const struct rt2x00debug *debugfs; |
@@ -628,6 +640,7 @@ enum rt2x00_flags { | |||
628 | DEVICE_STATE_INITIALIZED, | 640 | DEVICE_STATE_INITIALIZED, |
629 | DEVICE_STATE_STARTED, | 641 | DEVICE_STATE_STARTED, |
630 | DEVICE_STATE_ENABLED_RADIO, | 642 | DEVICE_STATE_ENABLED_RADIO, |
643 | DEVICE_STATE_SCANNING, | ||
631 | 644 | ||
632 | /* | 645 | /* |
633 | * Driver requirements | 646 | * Driver requirements |
@@ -646,6 +659,9 @@ enum rt2x00_flags { | |||
646 | CONFIG_SUPPORT_HW_CRYPTO, | 659 | CONFIG_SUPPORT_HW_CRYPTO, |
647 | DRIVER_SUPPORT_CONTROL_FILTERS, | 660 | DRIVER_SUPPORT_CONTROL_FILTERS, |
648 | DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, | 661 | DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, |
662 | DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, | ||
663 | DRIVER_SUPPORT_LINK_TUNING, | ||
664 | DRIVER_SUPPORT_WATCHDOG, | ||
649 | 665 | ||
650 | /* | 666 | /* |
651 | * Driver configuration | 667 | * Driver configuration |
@@ -655,7 +671,6 @@ enum rt2x00_flags { | |||
655 | CONFIG_EXTERNAL_LNA_A, | 671 | CONFIG_EXTERNAL_LNA_A, |
656 | CONFIG_EXTERNAL_LNA_BG, | 672 | CONFIG_EXTERNAL_LNA_BG, |
657 | CONFIG_DOUBLE_ANTENNA, | 673 | CONFIG_DOUBLE_ANTENNA, |
658 | CONFIG_DISABLE_LINK_TUNING, | ||
659 | CONFIG_CHANNEL_HT40, | 674 | CONFIG_CHANNEL_HT40, |
660 | }; | 675 | }; |
661 | 676 | ||
@@ -863,9 +878,10 @@ struct rt2x00_dev { | |||
863 | const struct firmware *fw; | 878 | const struct firmware *fw; |
864 | 879 | ||
865 | /* | 880 | /* |
866 | * Driver specific data. | 881 | * Interrupt values, stored between interrupt service routine |
882 | * and interrupt thread routine. | ||
867 | */ | 883 | */ |
868 | void *priv; | 884 | u32 irqvalue[2]; |
869 | }; | 885 | }; |
870 | 886 | ||
871 | /* | 887 | /* |
@@ -1052,6 +1068,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | |||
1052 | * Interrupt context handlers. | 1068 | * Interrupt context handlers. |
1053 | */ | 1069 | */ |
1054 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | 1070 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); |
1071 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); | ||
1055 | void rt2x00lib_txdone(struct queue_entry *entry, | 1072 | void rt2x00lib_txdone(struct queue_entry *entry, |
1056 | struct txdone_entry_desc *txdesc); | 1073 | struct txdone_entry_desc *txdesc); |
1057 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | 1074 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, |
@@ -1081,6 +1098,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1081 | #else | 1098 | #else |
1082 | #define rt2x00mac_set_key NULL | 1099 | #define rt2x00mac_set_key NULL |
1083 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ | 1100 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ |
1101 | void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw); | ||
1102 | void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw); | ||
1084 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, | 1103 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, |
1085 | struct ieee80211_low_level_stats *stats); | 1104 | struct ieee80211_low_level_stats *stats); |
1086 | void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | 1105 | void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 8dbd634dae27..953dc4f2c6af 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -41,10 +41,12 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, | |||
41 | 41 | ||
42 | switch (type) { | 42 | switch (type) { |
43 | case NL80211_IFTYPE_ADHOC: | 43 | case NL80211_IFTYPE_ADHOC: |
44 | conf.sync = TSF_SYNC_ADHOC; | ||
45 | break; | ||
44 | case NL80211_IFTYPE_AP: | 46 | case NL80211_IFTYPE_AP: |
45 | case NL80211_IFTYPE_MESH_POINT: | 47 | case NL80211_IFTYPE_MESH_POINT: |
46 | case NL80211_IFTYPE_WDS: | 48 | case NL80211_IFTYPE_WDS: |
47 | conf.sync = TSF_SYNC_BEACON; | 49 | conf.sync = TSF_SYNC_AP_NONE; |
48 | break; | 50 | break; |
49 | case NL80211_IFTYPE_STATION: | 51 | case NL80211_IFTYPE_STATION: |
50 | conf.sync = TSF_SYNC_INFRA; | 52 | conf.sync = TSF_SYNC_INFRA; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 12ee7bdedd02..f59b9f7226a8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -70,6 +70,11 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
70 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); | 70 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * Start watchdog monitoring. | ||
74 | */ | ||
75 | rt2x00link_start_watchdog(rt2x00dev); | ||
76 | |||
77 | /* | ||
73 | * Start the TX queues. | 78 | * Start the TX queues. |
74 | */ | 79 | */ |
75 | ieee80211_wake_queues(rt2x00dev->hw); | 80 | ieee80211_wake_queues(rt2x00dev->hw); |
@@ -89,6 +94,11 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
89 | rt2x00queue_stop_queues(rt2x00dev); | 94 | rt2x00queue_stop_queues(rt2x00dev); |
90 | 95 | ||
91 | /* | 96 | /* |
97 | * Stop watchdog monitoring. | ||
98 | */ | ||
99 | rt2x00link_stop_watchdog(rt2x00dev); | ||
100 | |||
101 | /* | ||
92 | * Disable RX. | 102 | * Disable RX. |
93 | */ | 103 | */ |
94 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); | 104 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); |
@@ -168,10 +178,32 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work) | |||
168 | /* | 178 | /* |
169 | * Interrupt context handlers. | 179 | * Interrupt context handlers. |
170 | */ | 180 | */ |
171 | static void rt2x00lib_beacondone_iter(void *data, u8 *mac, | 181 | static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac, |
172 | struct ieee80211_vif *vif) | 182 | struct ieee80211_vif *vif) |
173 | { | 183 | { |
174 | struct rt2x00_intf *intf = vif_to_intf(vif); | 184 | struct rt2x00_dev *rt2x00dev = data; |
185 | struct sk_buff *skb; | ||
186 | |||
187 | /* | ||
188 | * Only AP mode interfaces do broad- and multicast buffering | ||
189 | */ | ||
190 | if (vif->type != NL80211_IFTYPE_AP) | ||
191 | return; | ||
192 | |||
193 | /* | ||
194 | * Send out buffered broad- and multicast frames | ||
195 | */ | ||
196 | skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif); | ||
197 | while (skb) { | ||
198 | rt2x00mac_tx(rt2x00dev->hw, skb); | ||
199 | skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac, | ||
204 | struct ieee80211_vif *vif) | ||
205 | { | ||
206 | struct rt2x00_dev *rt2x00dev = data; | ||
175 | 207 | ||
176 | if (vif->type != NL80211_IFTYPE_AP && | 208 | if (vif->type != NL80211_IFTYPE_AP && |
177 | vif->type != NL80211_IFTYPE_ADHOC && | 209 | vif->type != NL80211_IFTYPE_ADHOC && |
@@ -179,9 +211,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, | |||
179 | vif->type != NL80211_IFTYPE_WDS) | 211 | vif->type != NL80211_IFTYPE_WDS) |
180 | return; | 212 | return; |
181 | 213 | ||
182 | spin_lock(&intf->lock); | 214 | rt2x00queue_update_beacon(rt2x00dev, vif, true); |
183 | intf->delayed_flags |= DELAYED_UPDATE_BEACON; | ||
184 | spin_unlock(&intf->lock); | ||
185 | } | 215 | } |
186 | 216 | ||
187 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | 217 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) |
@@ -189,14 +219,37 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
189 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 219 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
190 | return; | 220 | return; |
191 | 221 | ||
192 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, | 222 | /* send buffered bc/mc frames out for every bssid */ |
193 | rt2x00lib_beacondone_iter, | 223 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, |
194 | rt2x00dev); | 224 | rt2x00lib_bc_buffer_iter, |
225 | rt2x00dev); | ||
226 | /* | ||
227 | * Devices with pre tbtt interrupt don't need to update the beacon | ||
228 | * here as they will fetch the next beacon directly prior to | ||
229 | * transmission. | ||
230 | */ | ||
231 | if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags)) | ||
232 | return; | ||
195 | 233 | ||
196 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work); | 234 | /* fetch next beacon */ |
235 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | ||
236 | rt2x00lib_beaconupdate_iter, | ||
237 | rt2x00dev); | ||
197 | } | 238 | } |
198 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); | 239 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); |
199 | 240 | ||
241 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev) | ||
242 | { | ||
243 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
244 | return; | ||
245 | |||
246 | /* fetch next beacon */ | ||
247 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | ||
248 | rt2x00lib_beaconupdate_iter, | ||
249 | rt2x00dev); | ||
250 | } | ||
251 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); | ||
252 | |||
200 | void rt2x00lib_txdone(struct queue_entry *entry, | 253 | void rt2x00lib_txdone(struct queue_entry *entry, |
201 | struct txdone_entry_desc *txdesc) | 254 | struct txdone_entry_desc *txdesc) |
202 | { | 255 | { |
@@ -330,9 +383,17 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
330 | * send the status report back. | 383 | * send the status report back. |
331 | */ | 384 | */ |
332 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) | 385 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) |
333 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | 386 | /* |
387 | * Only PCI and SOC devices process the tx status in process | ||
388 | * context. Hence use ieee80211_tx_status for PCI and SOC | ||
389 | * devices and stick to ieee80211_tx_status_irqsafe for USB. | ||
390 | */ | ||
391 | if (rt2x00_is_usb(rt2x00dev)) | ||
392 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | ||
393 | else | ||
394 | ieee80211_tx_status(rt2x00dev->hw, entry->skb); | ||
334 | else | 395 | else |
335 | dev_kfree_skb_irq(entry->skb); | 396 | dev_kfree_skb_any(entry->skb); |
336 | 397 | ||
337 | /* | 398 | /* |
338 | * Make this entry available for reuse. | 399 | * Make this entry available for reuse. |
@@ -479,7 +540,16 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
479 | */ | 540 | */ |
480 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | 541 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); |
481 | memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); | 542 | memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); |
482 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); | 543 | |
544 | /* | ||
545 | * Currently only PCI and SOC devices handle rx interrupts in process | ||
546 | * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni | ||
547 | * for PCI and SOC devices. | ||
548 | */ | ||
549 | if (rt2x00_is_usb(rt2x00dev)) | ||
550 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); | ||
551 | else | ||
552 | ieee80211_rx_ni(rt2x00dev->hw, entry->skb); | ||
483 | 553 | ||
484 | /* | 554 | /* |
485 | * Replace the skb with the freshly allocated one. | 555 | * Replace the skb with the freshly allocated one. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index ed27de1de57b..dc5c6574aaf4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -30,6 +30,7 @@ | |||
30 | /* | 30 | /* |
31 | * Interval defines | 31 | * Interval defines |
32 | */ | 32 | */ |
33 | #define WATCHDOG_INTERVAL round_jiffies_relative(HZ) | ||
33 | #define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) | 34 | #define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) |
34 | 35 | ||
35 | /* | 36 | /* |
@@ -257,11 +258,30 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev); | |||
257 | void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna); | 258 | void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna); |
258 | 259 | ||
259 | /** | 260 | /** |
260 | * rt2x00link_register - Initialize link tuning functionality | 261 | * rt2x00link_start_watchdog - Start periodic watchdog monitoring |
261 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 262 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
262 | * | 263 | * |
263 | * Initialize work structure and all link tuning related | 264 | * This start the watchdog periodic work, this work will |
264 | * parameters. This will not start the link tuning process itself. | 265 | *be executed periodically until &rt2x00link_stop_watchdog has |
266 | * been called. | ||
267 | */ | ||
268 | void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev); | ||
269 | |||
270 | /** | ||
271 | * rt2x00link_stop_watchdog - Stop periodic watchdog monitoring | ||
272 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
273 | * | ||
274 | * After this function completed the watchdog monitoring will not | ||
275 | * be running until &rt2x00link_start_watchdog is called. | ||
276 | */ | ||
277 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev); | ||
278 | |||
279 | /** | ||
280 | * rt2x00link_register - Initialize link tuning & watchdog functionality | ||
281 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
282 | * | ||
283 | * Initialize work structure and all link tuning and watchdog related | ||
284 | * parameters. This will not start the periodic work itself. | ||
265 | */ | 285 | */ |
266 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev); | 286 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev); |
267 | 287 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 2f8136cab7d8..666cef3f8472 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -278,6 +278,15 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) | |||
278 | if (!rt2x00dev->intf_sta_count) | 278 | if (!rt2x00dev->intf_sta_count) |
279 | return; | 279 | return; |
280 | 280 | ||
281 | /** | ||
282 | * While scanning, link tuning is disabled. By default | ||
283 | * the most sensitive settings will be used to make sure | ||
284 | * that all beacons and probe responses will be recieved | ||
285 | * during the scan. | ||
286 | */ | ||
287 | if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) | ||
288 | return; | ||
289 | |||
281 | rt2x00link_reset_tuner(rt2x00dev, false); | 290 | rt2x00link_reset_tuner(rt2x00dev, false); |
282 | 291 | ||
283 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 292 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
@@ -293,6 +302,7 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) | |||
293 | void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) | 302 | void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) |
294 | { | 303 | { |
295 | struct link_qual *qual = &rt2x00dev->link.qual; | 304 | struct link_qual *qual = &rt2x00dev->link.qual; |
305 | u8 vgc_level = qual->vgc_level_reg; | ||
296 | 306 | ||
297 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 307 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
298 | return; | 308 | return; |
@@ -309,6 +319,13 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) | |||
309 | memset(qual, 0, sizeof(*qual)); | 319 | memset(qual, 0, sizeof(*qual)); |
310 | 320 | ||
311 | /* | 321 | /* |
322 | * Restore the VGC level as stored in the registers, | ||
323 | * the driver can use this to determine if the register | ||
324 | * must be updated during reset or not. | ||
325 | */ | ||
326 | qual->vgc_level_reg = vgc_level; | ||
327 | |||
328 | /* | ||
312 | * Reset the link tuner. | 329 | * Reset the link tuner. |
313 | */ | 330 | */ |
314 | rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual); | 331 | rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual); |
@@ -338,7 +355,8 @@ static void rt2x00link_tuner(struct work_struct *work) | |||
338 | * When the radio is shutting down we should | 355 | * When the radio is shutting down we should |
339 | * immediately cease all link tuning. | 356 | * immediately cease all link tuning. |
340 | */ | 357 | */ |
341 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 358 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
359 | test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) | ||
342 | return; | 360 | return; |
343 | 361 | ||
344 | /* | 362 | /* |
@@ -359,10 +377,11 @@ static void rt2x00link_tuner(struct work_struct *work) | |||
359 | qual->rssi = link->avg_rssi.avg; | 377 | qual->rssi = link->avg_rssi.avg; |
360 | 378 | ||
361 | /* | 379 | /* |
362 | * Only perform the link tuning when Link tuning | 380 | * Check if link tuning is supported by the hardware, some hardware |
363 | * has been enabled (This could have been disabled from the EEPROM). | 381 | * do not support link tuning at all, while other devices can disable |
382 | * the feature from the EEPROM. | ||
364 | */ | 383 | */ |
365 | if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) | 384 | if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags)) |
366 | rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); | 385 | rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); |
367 | 386 | ||
368 | /* | 387 | /* |
@@ -388,7 +407,45 @@ static void rt2x00link_tuner(struct work_struct *work) | |||
388 | &link->work, LINK_TUNE_INTERVAL); | 407 | &link->work, LINK_TUNE_INTERVAL); |
389 | } | 408 | } |
390 | 409 | ||
410 | void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) | ||
411 | { | ||
412 | struct link *link = &rt2x00dev->link; | ||
413 | |||
414 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || | ||
415 | !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) | ||
416 | return; | ||
417 | |||
418 | ieee80211_queue_delayed_work(rt2x00dev->hw, | ||
419 | &link->watchdog_work, WATCHDOG_INTERVAL); | ||
420 | } | ||
421 | |||
422 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) | ||
423 | { | ||
424 | cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work); | ||
425 | } | ||
426 | |||
427 | static void rt2x00link_watchdog(struct work_struct *work) | ||
428 | { | ||
429 | struct rt2x00_dev *rt2x00dev = | ||
430 | container_of(work, struct rt2x00_dev, link.watchdog_work.work); | ||
431 | struct link *link = &rt2x00dev->link; | ||
432 | |||
433 | /* | ||
434 | * When the radio is shutting down we should | ||
435 | * immediately cease the watchdog monitoring. | ||
436 | */ | ||
437 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
438 | return; | ||
439 | |||
440 | rt2x00dev->ops->lib->watchdog(rt2x00dev); | ||
441 | |||
442 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
443 | ieee80211_queue_delayed_work(rt2x00dev->hw, | ||
444 | &link->watchdog_work, WATCHDOG_INTERVAL); | ||
445 | } | ||
446 | |||
391 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) | 447 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) |
392 | { | 448 | { |
449 | INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); | ||
393 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); | 450 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); |
394 | } | 451 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3b838c0bf59f..4d8d2320c9fd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -347,9 +347,11 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) | |||
347 | /* | 347 | /* |
348 | * Some configuration parameters (e.g. channel and antenna values) can | 348 | * Some configuration parameters (e.g. channel and antenna values) can |
349 | * only be set when the radio is enabled, but do require the RX to | 349 | * only be set when the radio is enabled, but do require the RX to |
350 | * be off. | 350 | * be off. During this period we should keep link tuning enabled, |
351 | * if for any reason the link tuner must be reset, this will be | ||
352 | * handled by rt2x00lib_config(). | ||
351 | */ | 353 | */ |
352 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); | 354 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); |
353 | 355 | ||
354 | /* | 356 | /* |
355 | * When we've just turned on the radio, we want to reprogram | 357 | * When we've just turned on the radio, we want to reprogram |
@@ -367,7 +369,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) | |||
367 | rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); | 369 | rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); |
368 | 370 | ||
369 | /* Turn RX back on */ | 371 | /* Turn RX back on */ |
370 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); | 372 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); |
371 | 373 | ||
372 | return 0; | 374 | return 0; |
373 | } | 375 | } |
@@ -431,12 +433,36 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
431 | } | 433 | } |
432 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); | 434 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); |
433 | 435 | ||
436 | static void rt2x00mac_set_tim_iter(void *data, u8 *mac, | ||
437 | struct ieee80211_vif *vif) | ||
438 | { | ||
439 | struct rt2x00_intf *intf = vif_to_intf(vif); | ||
440 | |||
441 | if (vif->type != NL80211_IFTYPE_AP && | ||
442 | vif->type != NL80211_IFTYPE_ADHOC && | ||
443 | vif->type != NL80211_IFTYPE_MESH_POINT && | ||
444 | vif->type != NL80211_IFTYPE_WDS) | ||
445 | return; | ||
446 | |||
447 | spin_lock(&intf->lock); | ||
448 | intf->delayed_flags |= DELAYED_UPDATE_BEACON; | ||
449 | spin_unlock(&intf->lock); | ||
450 | } | ||
451 | |||
434 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 452 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
435 | bool set) | 453 | bool set) |
436 | { | 454 | { |
437 | struct rt2x00_dev *rt2x00dev = hw->priv; | 455 | struct rt2x00_dev *rt2x00dev = hw->priv; |
438 | 456 | ||
439 | rt2x00lib_beacondone(rt2x00dev); | 457 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
458 | return 0; | ||
459 | |||
460 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, | ||
461 | rt2x00mac_set_tim_iter, | ||
462 | rt2x00dev); | ||
463 | |||
464 | /* queue work to upodate the beacon template */ | ||
465 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work); | ||
440 | return 0; | 466 | return 0; |
441 | } | 467 | } |
442 | EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); | 468 | EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); |
@@ -540,6 +566,22 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
540 | EXPORT_SYMBOL_GPL(rt2x00mac_set_key); | 566 | EXPORT_SYMBOL_GPL(rt2x00mac_set_key); |
541 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ | 567 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ |
542 | 568 | ||
569 | void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) | ||
570 | { | ||
571 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
572 | __set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); | ||
573 | rt2x00link_stop_tuner(rt2x00dev); | ||
574 | } | ||
575 | EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); | ||
576 | |||
577 | void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw) | ||
578 | { | ||
579 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
580 | __clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); | ||
581 | rt2x00link_start_tuner(rt2x00dev); | ||
582 | } | ||
583 | EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete); | ||
584 | |||
543 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, | 585 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, |
544 | struct ieee80211_low_level_stats *stats) | 586 | struct ieee80211_low_level_stats *stats) |
545 | { | 587 | { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index fc9da8358784..19b262e1ddbe 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -153,8 +153,10 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) | |||
153 | /* | 153 | /* |
154 | * Register interrupt handler. | 154 | * Register interrupt handler. |
155 | */ | 155 | */ |
156 | status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler, | 156 | status = request_threaded_irq(rt2x00dev->irq, |
157 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); | 157 | rt2x00dev->ops->lib->irq_handler, |
158 | rt2x00dev->ops->lib->irq_handler_thread, | ||
159 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); | ||
158 | if (status) { | 160 | if (status) { |
159 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", | 161 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", |
160 | rt2x00dev->irq, status); | 162 | rt2x00dev->irq, status); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 5097fe0f9f51..a3401d301058 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -688,9 +688,11 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) | |||
688 | 688 | ||
689 | if (index == Q_INDEX) { | 689 | if (index == Q_INDEX) { |
690 | queue->length++; | 690 | queue->length++; |
691 | queue->last_index = jiffies; | ||
691 | } else if (index == Q_INDEX_DONE) { | 692 | } else if (index == Q_INDEX_DONE) { |
692 | queue->length--; | 693 | queue->length--; |
693 | queue->count++; | 694 | queue->count++; |
695 | queue->last_index_done = jiffies; | ||
694 | } | 696 | } |
695 | 697 | ||
696 | spin_unlock_irqrestore(&queue->lock, irqflags); | 698 | spin_unlock_irqrestore(&queue->lock, irqflags); |
@@ -704,6 +706,8 @@ static void rt2x00queue_reset(struct data_queue *queue) | |||
704 | 706 | ||
705 | queue->count = 0; | 707 | queue->count = 0; |
706 | queue->length = 0; | 708 | queue->length = 0; |
709 | queue->last_index = jiffies; | ||
710 | queue->last_index_done = jiffies; | ||
707 | memset(queue->index, 0, sizeof(queue->index)); | 711 | memset(queue->index, 0, sizeof(queue->index)); |
708 | 712 | ||
709 | spin_unlock_irqrestore(&queue->lock, irqflags); | 713 | spin_unlock_irqrestore(&queue->lock, irqflags); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index bd54f55a8cb9..191e7775a9c0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -446,6 +446,8 @@ struct data_queue { | |||
446 | enum data_queue_qid qid; | 446 | enum data_queue_qid qid; |
447 | 447 | ||
448 | spinlock_t lock; | 448 | spinlock_t lock; |
449 | unsigned long last_index; | ||
450 | unsigned long last_index_done; | ||
449 | unsigned int count; | 451 | unsigned int count; |
450 | unsigned short limit; | 452 | unsigned short limit; |
451 | unsigned short threshold; | 453 | unsigned short threshold; |
@@ -599,6 +601,15 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) | |||
599 | } | 601 | } |
600 | 602 | ||
601 | /** | 603 | /** |
604 | * rt2x00queue_timeout - Check if a timeout occured for this queue | ||
605 | * @queue: Queue to check. | ||
606 | */ | ||
607 | static inline int rt2x00queue_timeout(struct data_queue *queue) | ||
608 | { | ||
609 | return time_after(queue->last_index, queue->last_index_done + (HZ / 10)); | ||
610 | } | ||
611 | |||
612 | /** | ||
602 | * _rt2x00_desc_read - Read a word from the hardware descriptor. | 613 | * _rt2x00_desc_read - Read a word from the hardware descriptor. |
603 | * @desc: Base descriptor address | 614 | * @desc: Base descriptor address |
604 | * @word: Word index from where the descriptor should be read. | 615 | * @word: Word index from where the descriptor should be read. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index b9fe94873ee0..cef94621cef7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h | |||
@@ -63,7 +63,8 @@ enum led_mode { | |||
63 | enum tsf_sync { | 63 | enum tsf_sync { |
64 | TSF_SYNC_NONE = 0, | 64 | TSF_SYNC_NONE = 0, |
65 | TSF_SYNC_INFRA = 1, | 65 | TSF_SYNC_INFRA = 1, |
66 | TSF_SYNC_BEACON = 2, | 66 | TSF_SYNC_ADHOC = 2, |
67 | TSF_SYNC_AP_NONE = 3, | ||
67 | }; | 68 | }; |
68 | 69 | ||
69 | /* | 70 | /* |
@@ -88,6 +89,8 @@ enum dev_state { | |||
88 | STATE_RADIO_RX_OFF_LINK, | 89 | STATE_RADIO_RX_OFF_LINK, |
89 | STATE_RADIO_IRQ_ON, | 90 | STATE_RADIO_IRQ_ON, |
90 | STATE_RADIO_IRQ_OFF, | 91 | STATE_RADIO_IRQ_OFF, |
92 | STATE_RADIO_IRQ_ON_ISR, | ||
93 | STATE_RADIO_IRQ_OFF_ISR, | ||
91 | }; | 94 | }; |
92 | 95 | ||
93 | /* | 96 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index a22837c560fd..ff3a36622d1b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -292,6 +292,56 @@ void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
292 | } | 292 | } |
293 | EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); | 293 | EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); |
294 | 294 | ||
295 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | ||
296 | { | ||
297 | struct queue_entry_priv_usb *entry_priv; | ||
298 | unsigned short threshold = queue->threshold; | ||
299 | |||
300 | WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid); | ||
301 | |||
302 | /* | ||
303 | * Temporarily disable the TX queue, this will force mac80211 | ||
304 | * to use the other queues until this queue has been restored. | ||
305 | * | ||
306 | * Set the queue threshold to the queue limit. This prevents the | ||
307 | * queue from being enabled during the txdone handler. | ||
308 | */ | ||
309 | queue->threshold = queue->limit; | ||
310 | ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid); | ||
311 | |||
312 | /* | ||
313 | * Reset all currently uploaded TX frames. | ||
314 | */ | ||
315 | while (!rt2x00queue_empty(queue)) { | ||
316 | entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data; | ||
317 | usb_kill_urb(entry_priv->urb); | ||
318 | |||
319 | /* | ||
320 | * We need a short delay here to wait for | ||
321 | * the URB to be canceled and invoked the tx_done handler. | ||
322 | */ | ||
323 | udelay(200); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * The queue has been reset, and mac80211 is allowed to use the | ||
328 | * queue again. | ||
329 | */ | ||
330 | queue->threshold = threshold; | ||
331 | ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); | ||
332 | } | ||
333 | |||
334 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) | ||
335 | { | ||
336 | struct data_queue *queue; | ||
337 | |||
338 | tx_queue_for_each(rt2x00dev, queue) { | ||
339 | if (rt2x00queue_timeout(queue)) | ||
340 | rt2x00usb_watchdog_reset_tx(queue); | ||
341 | } | ||
342 | } | ||
343 | EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); | ||
344 | |||
295 | /* | 345 | /* |
296 | * RX data handlers. | 346 | * RX data handlers. |
297 | */ | 347 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 2b7a1889e72f..d3d3ddc40875 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -399,6 +399,16 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
399 | void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, | 399 | void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, |
400 | const enum data_queue_qid qid); | 400 | const enum data_queue_qid qid); |
401 | 401 | ||
402 | /** | ||
403 | * rt2x00usb_watchdog - Watchdog for USB communication | ||
404 | * @rt2x00dev: Pointer to &struct rt2x00_dev | ||
405 | * | ||
406 | * Check the health of the USB communication and determine | ||
407 | * if timeouts have occured. If this is the case, this function | ||
408 | * will reset all communication to restore functionality again. | ||
409 | */ | ||
410 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev); | ||
411 | |||
402 | /* | 412 | /* |
403 | * Device initialization handlers. | 413 | * Device initialization handlers. |
404 | */ | 414 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 0123fbc22ca2..e539c6cb636f 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1622,7 +1622,8 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev, | |||
1622 | static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 1622 | static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
1623 | enum dev_state state) | 1623 | enum dev_state state) |
1624 | { | 1624 | { |
1625 | int mask = (state == STATE_RADIO_IRQ_OFF); | 1625 | int mask = (state == STATE_RADIO_IRQ_OFF) || |
1626 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
1626 | u32 reg; | 1627 | u32 reg; |
1627 | 1628 | ||
1628 | /* | 1629 | /* |
@@ -1739,7 +1740,9 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1739 | rt61pci_toggle_rx(rt2x00dev, state); | 1740 | rt61pci_toggle_rx(rt2x00dev, state); |
1740 | break; | 1741 | break; |
1741 | case STATE_RADIO_IRQ_ON: | 1742 | case STATE_RADIO_IRQ_ON: |
1743 | case STATE_RADIO_IRQ_ON_ISR: | ||
1742 | case STATE_RADIO_IRQ_OFF: | 1744 | case STATE_RADIO_IRQ_OFF: |
1745 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1743 | rt61pci_toggle_irq(rt2x00dev, state); | 1746 | rt61pci_toggle_irq(rt2x00dev, state); |
1744 | break; | 1747 | break; |
1745 | case STATE_DEEP_SLEEP: | 1748 | case STATE_DEEP_SLEEP: |
@@ -2147,27 +2150,11 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) | |||
2147 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | 2150 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); |
2148 | } | 2151 | } |
2149 | 2152 | ||
2150 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | 2153 | static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance) |
2151 | { | 2154 | { |
2152 | struct rt2x00_dev *rt2x00dev = dev_instance; | 2155 | struct rt2x00_dev *rt2x00dev = dev_instance; |
2153 | u32 reg_mcu; | 2156 | u32 reg = rt2x00dev->irqvalue[0]; |
2154 | u32 reg; | 2157 | u32 reg_mcu = rt2x00dev->irqvalue[1]; |
2155 | |||
2156 | /* | ||
2157 | * Get the interrupt sources & saved to local variable. | ||
2158 | * Write register value back to clear pending interrupts. | ||
2159 | */ | ||
2160 | rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®_mcu); | ||
2161 | rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu); | ||
2162 | |||
2163 | rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
2164 | rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
2165 | |||
2166 | if (!reg && !reg_mcu) | ||
2167 | return IRQ_NONE; | ||
2168 | |||
2169 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
2170 | return IRQ_HANDLED; | ||
2171 | 2158 | ||
2172 | /* | 2159 | /* |
2173 | * Handle interrupts, walk through all bits | 2160 | * Handle interrupts, walk through all bits |
@@ -2206,9 +2193,45 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2206 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) | 2193 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) |
2207 | rt2x00lib_beacondone(rt2x00dev); | 2194 | rt2x00lib_beacondone(rt2x00dev); |
2208 | 2195 | ||
2196 | /* Enable interrupts again. */ | ||
2197 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
2198 | STATE_RADIO_IRQ_ON_ISR); | ||
2209 | return IRQ_HANDLED; | 2199 | return IRQ_HANDLED; |
2210 | } | 2200 | } |
2211 | 2201 | ||
2202 | |||
2203 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | ||
2204 | { | ||
2205 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
2206 | u32 reg_mcu; | ||
2207 | u32 reg; | ||
2208 | |||
2209 | /* | ||
2210 | * Get the interrupt sources & saved to local variable. | ||
2211 | * Write register value back to clear pending interrupts. | ||
2212 | */ | ||
2213 | rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®_mcu); | ||
2214 | rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu); | ||
2215 | |||
2216 | rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
2217 | rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
2218 | |||
2219 | if (!reg && !reg_mcu) | ||
2220 | return IRQ_NONE; | ||
2221 | |||
2222 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
2223 | return IRQ_HANDLED; | ||
2224 | |||
2225 | /* Store irqvalues for use in the interrupt thread. */ | ||
2226 | rt2x00dev->irqvalue[0] = reg; | ||
2227 | rt2x00dev->irqvalue[1] = reg_mcu; | ||
2228 | |||
2229 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | ||
2230 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
2231 | STATE_RADIO_IRQ_OFF_ISR); | ||
2232 | return IRQ_WAKE_THREAD; | ||
2233 | } | ||
2234 | |||
2212 | /* | 2235 | /* |
2213 | * Device probe functions. | 2236 | * Device probe functions. |
2214 | */ | 2237 | */ |
@@ -2690,6 +2713,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2690 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | 2713 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); |
2691 | if (!modparam_nohwcrypt) | 2714 | if (!modparam_nohwcrypt) |
2692 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 2715 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
2716 | __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); | ||
2693 | 2717 | ||
2694 | /* | 2718 | /* |
2695 | * Set the rssi offset. | 2719 | * Set the rssi offset. |
@@ -2781,8 +2805,9 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2781 | .remove_interface = rt2x00mac_remove_interface, | 2805 | .remove_interface = rt2x00mac_remove_interface, |
2782 | .config = rt2x00mac_config, | 2806 | .config = rt2x00mac_config, |
2783 | .configure_filter = rt2x00mac_configure_filter, | 2807 | .configure_filter = rt2x00mac_configure_filter, |
2784 | .set_tim = rt2x00mac_set_tim, | ||
2785 | .set_key = rt2x00mac_set_key, | 2808 | .set_key = rt2x00mac_set_key, |
2809 | .sw_scan_start = rt2x00mac_sw_scan_start, | ||
2810 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
2786 | .get_stats = rt2x00mac_get_stats, | 2811 | .get_stats = rt2x00mac_get_stats, |
2787 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2812 | .bss_info_changed = rt2x00mac_bss_info_changed, |
2788 | .conf_tx = rt61pci_conf_tx, | 2813 | .conf_tx = rt61pci_conf_tx, |
@@ -2792,6 +2817,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2792 | 2817 | ||
2793 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | 2818 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { |
2794 | .irq_handler = rt61pci_interrupt, | 2819 | .irq_handler = rt61pci_interrupt, |
2820 | .irq_handler_thread = rt61pci_interrupt_thread, | ||
2795 | .probe_hw = rt61pci_probe_hw, | 2821 | .probe_hw = rt61pci_probe_hw, |
2796 | .get_firmware_name = rt61pci_get_firmware_name, | 2822 | .get_firmware_name = rt61pci_get_firmware_name, |
2797 | .check_firmware = rt61pci_check_firmware, | 2823 | .check_firmware = rt61pci_check_firmware, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 286dd97e51d8..aa9de18fd410 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1400,7 +1400,9 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1400 | rt73usb_toggle_rx(rt2x00dev, state); | 1400 | rt73usb_toggle_rx(rt2x00dev, state); |
1401 | break; | 1401 | break; |
1402 | case STATE_RADIO_IRQ_ON: | 1402 | case STATE_RADIO_IRQ_ON: |
1403 | case STATE_RADIO_IRQ_ON_ISR: | ||
1403 | case STATE_RADIO_IRQ_OFF: | 1404 | case STATE_RADIO_IRQ_OFF: |
1405 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1404 | /* No support, but no error either */ | 1406 | /* No support, but no error either */ |
1405 | break; | 1407 | break; |
1406 | case STATE_DEEP_SLEEP: | 1408 | case STATE_DEEP_SLEEP: |
@@ -2135,6 +2137,8 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2135 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 2137 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
2136 | if (!modparam_nohwcrypt) | 2138 | if (!modparam_nohwcrypt) |
2137 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 2139 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
2140 | __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); | ||
2141 | __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); | ||
2138 | 2142 | ||
2139 | /* | 2143 | /* |
2140 | * Set the rssi offset. | 2144 | * Set the rssi offset. |
@@ -2228,6 +2232,8 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { | |||
2228 | .configure_filter = rt2x00mac_configure_filter, | 2232 | .configure_filter = rt2x00mac_configure_filter, |
2229 | .set_tim = rt2x00mac_set_tim, | 2233 | .set_tim = rt2x00mac_set_tim, |
2230 | .set_key = rt2x00mac_set_key, | 2234 | .set_key = rt2x00mac_set_key, |
2235 | .sw_scan_start = rt2x00mac_sw_scan_start, | ||
2236 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
2231 | .get_stats = rt2x00mac_get_stats, | 2237 | .get_stats = rt2x00mac_get_stats, |
2232 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2238 | .bss_info_changed = rt2x00mac_bss_info_changed, |
2233 | .conf_tx = rt73usb_conf_tx, | 2239 | .conf_tx = rt73usb_conf_tx, |
@@ -2248,6 +2254,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { | |||
2248 | .link_stats = rt73usb_link_stats, | 2254 | .link_stats = rt73usb_link_stats, |
2249 | .reset_tuner = rt73usb_reset_tuner, | 2255 | .reset_tuner = rt73usb_reset_tuner, |
2250 | .link_tuner = rt73usb_link_tuner, | 2256 | .link_tuner = rt73usb_link_tuner, |
2257 | .watchdog = rt2x00usb_watchdog, | ||
2251 | .write_tx_desc = rt73usb_write_tx_desc, | 2258 | .write_tx_desc = rt73usb_write_tx_desc, |
2252 | .write_beacon = rt73usb_write_beacon, | 2259 | .write_beacon = rt73usb_write_beacon, |
2253 | .get_tx_data_len = rt73usb_get_tx_data_len, | 2260 | .get_tx_data_len = rt73usb_get_tx_data_len, |