diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 165 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500pci.c | 159 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 73 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 192 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 35 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 69 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00lib.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00link.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 44 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00pci.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00reg.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 226 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 49 |
19 files changed, 795 insertions, 343 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 54ca49ad3472..2725f3c4442e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -46,7 +46,7 @@ | |||
46 | * These indirect registers work with busy bits, | 46 | * These indirect registers work with busy bits, |
47 | * and we will try maximal REGISTER_BUSY_COUNT times to access | 47 | * and we will try maximal REGISTER_BUSY_COUNT times to access |
48 | * the register while taking a REGISTER_BUSY_DELAY us delay | 48 | * the register while taking a REGISTER_BUSY_DELAY us delay |
49 | * between each attampt. When the busy bit is still set at that time, | 49 | * between each attempt. When the busy bit is still set at that time, |
50 | * the access attempt is considered to have failed, | 50 | * the access attempt is considered to have failed, |
51 | * and we will print an error. | 51 | * and we will print an error. |
52 | */ | 52 | */ |
@@ -305,9 +305,7 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
305 | * Enable synchronisation. | 305 | * Enable synchronisation. |
306 | */ | 306 | */ |
307 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 307 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
308 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | ||
309 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); | 308 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); |
310 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
311 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 309 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
312 | } | 310 | } |
313 | 311 | ||
@@ -647,6 +645,11 @@ static void rt2400pci_start_queue(struct data_queue *queue) | |||
647 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 645 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); |
648 | break; | 646 | break; |
649 | case QID_BEACON: | 647 | case QID_BEACON: |
648 | /* | ||
649 | * Allow the tbtt tasklet to be scheduled. | ||
650 | */ | ||
651 | tasklet_enable(&rt2x00dev->tbtt_tasklet); | ||
652 | |||
650 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 653 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
651 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | 654 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); |
652 | rt2x00_set_field32(®, CSR14_TBCN, 1); | 655 | rt2x00_set_field32(®, CSR14_TBCN, 1); |
@@ -708,6 +711,11 @@ static void rt2400pci_stop_queue(struct data_queue *queue) | |||
708 | rt2x00_set_field32(®, CSR14_TBCN, 0); | 711 | rt2x00_set_field32(®, CSR14_TBCN, 0); |
709 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 712 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
710 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 713 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
714 | |||
715 | /* | ||
716 | * Wait for possibly running tbtt tasklets. | ||
717 | */ | ||
718 | tasklet_disable(&rt2x00dev->tbtt_tasklet); | ||
711 | break; | 719 | break; |
712 | default: | 720 | default: |
713 | break; | 721 | break; |
@@ -963,9 +971,9 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
963 | static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 971 | static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
964 | enum dev_state state) | 972 | enum dev_state state) |
965 | { | 973 | { |
966 | int mask = (state == STATE_RADIO_IRQ_OFF) || | 974 | int mask = (state == STATE_RADIO_IRQ_OFF); |
967 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
968 | u32 reg; | 975 | u32 reg; |
976 | unsigned long flags; | ||
969 | 977 | ||
970 | /* | 978 | /* |
971 | * When interrupts are being enabled, the interrupt registers | 979 | * When interrupts are being enabled, the interrupt registers |
@@ -974,12 +982,20 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
974 | if (state == STATE_RADIO_IRQ_ON) { | 982 | if (state == STATE_RADIO_IRQ_ON) { |
975 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | 983 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); |
976 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | 984 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); |
985 | |||
986 | /* | ||
987 | * Enable tasklets. | ||
988 | */ | ||
989 | tasklet_enable(&rt2x00dev->txstatus_tasklet); | ||
990 | tasklet_enable(&rt2x00dev->rxdone_tasklet); | ||
977 | } | 991 | } |
978 | 992 | ||
979 | /* | 993 | /* |
980 | * Only toggle the interrupts bits we are going to use. | 994 | * Only toggle the interrupts bits we are going to use. |
981 | * Non-checked interrupt bits are disabled by default. | 995 | * Non-checked interrupt bits are disabled by default. |
982 | */ | 996 | */ |
997 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
998 | |||
983 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 999 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
984 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); | 1000 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); |
985 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); | 1001 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); |
@@ -987,6 +1003,17 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
987 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); | 1003 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); |
988 | rt2x00_set_field32(®, CSR8_RXDONE, mask); | 1004 | rt2x00_set_field32(®, CSR8_RXDONE, mask); |
989 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1005 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); |
1006 | |||
1007 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1008 | |||
1009 | if (state == STATE_RADIO_IRQ_OFF) { | ||
1010 | /* | ||
1011 | * Ensure that all tasklets are finished before | ||
1012 | * disabling the interrupts. | ||
1013 | */ | ||
1014 | tasklet_disable(&rt2x00dev->txstatus_tasklet); | ||
1015 | tasklet_disable(&rt2x00dev->rxdone_tasklet); | ||
1016 | } | ||
990 | } | 1017 | } |
991 | 1018 | ||
992 | static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 1019 | static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
@@ -1059,9 +1086,7 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1059 | rt2400pci_disable_radio(rt2x00dev); | 1086 | rt2400pci_disable_radio(rt2x00dev); |
1060 | break; | 1087 | break; |
1061 | case STATE_RADIO_IRQ_ON: | 1088 | case STATE_RADIO_IRQ_ON: |
1062 | case STATE_RADIO_IRQ_ON_ISR: | ||
1063 | case STATE_RADIO_IRQ_OFF: | 1089 | case STATE_RADIO_IRQ_OFF: |
1064 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1065 | rt2400pci_toggle_irq(rt2x00dev, state); | 1090 | rt2400pci_toggle_irq(rt2x00dev, state); |
1066 | break; | 1091 | break; |
1067 | case STATE_DEEP_SLEEP: | 1092 | case STATE_DEEP_SLEEP: |
@@ -1183,8 +1208,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, | |||
1183 | /* | 1208 | /* |
1184 | * Enable beaconing again. | 1209 | * Enable beaconing again. |
1185 | */ | 1210 | */ |
1186 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | ||
1187 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
1188 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); | 1211 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); |
1189 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 1212 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
1190 | } | 1213 | } |
@@ -1289,57 +1312,71 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1289 | } | 1312 | } |
1290 | } | 1313 | } |
1291 | 1314 | ||
1292 | static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance) | 1315 | static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, |
1316 | struct rt2x00_field32 irq_field) | ||
1293 | { | 1317 | { |
1294 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1318 | unsigned long flags; |
1295 | u32 reg = rt2x00dev->irqvalue[0]; | 1319 | u32 reg; |
1296 | 1320 | ||
1297 | /* | 1321 | /* |
1298 | * Handle interrupts, walk through all bits | 1322 | * Enable a single interrupt. The interrupt mask register |
1299 | * and run the tasks, the bits are checked in order of | 1323 | * access needs locking. |
1300 | * priority. | ||
1301 | */ | 1324 | */ |
1325 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1302 | 1326 | ||
1303 | /* | 1327 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
1304 | * 1 - Beacon timer expired interrupt. | 1328 | rt2x00_set_field32(®, irq_field, 0); |
1305 | */ | 1329 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); |
1306 | if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) | ||
1307 | rt2x00lib_beacondone(rt2x00dev); | ||
1308 | 1330 | ||
1309 | /* | 1331 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
1310 | * 2 - Rx ring done interrupt. | 1332 | } |
1311 | */ | ||
1312 | if (rt2x00_get_field32(reg, CSR7_RXDONE)) | ||
1313 | rt2x00pci_rxdone(rt2x00dev); | ||
1314 | 1333 | ||
1315 | /* | 1334 | static void rt2400pci_txstatus_tasklet(unsigned long data) |
1316 | * 3 - Atim ring transmit done interrupt. | 1335 | { |
1317 | */ | 1336 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
1318 | if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) | 1337 | u32 reg; |
1319 | rt2400pci_txdone(rt2x00dev, QID_ATIM); | 1338 | unsigned long flags; |
1320 | 1339 | ||
1321 | /* | 1340 | /* |
1322 | * 4 - Priority ring transmit done interrupt. | 1341 | * Handle all tx queues. |
1323 | */ | 1342 | */ |
1324 | if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) | 1343 | rt2400pci_txdone(rt2x00dev, QID_ATIM); |
1325 | rt2400pci_txdone(rt2x00dev, QID_AC_VO); | 1344 | rt2400pci_txdone(rt2x00dev, QID_AC_VO); |
1345 | rt2400pci_txdone(rt2x00dev, QID_AC_VI); | ||
1326 | 1346 | ||
1327 | /* | 1347 | /* |
1328 | * 5 - Tx ring transmit done interrupt. | 1348 | * Enable all TXDONE interrupts again. |
1329 | */ | 1349 | */ |
1330 | if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) | 1350 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
1331 | rt2400pci_txdone(rt2x00dev, QID_AC_VI); | ||
1332 | 1351 | ||
1333 | /* Enable interrupts again. */ | 1352 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
1334 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 1353 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); |
1335 | STATE_RADIO_IRQ_ON_ISR); | 1354 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); |
1336 | return IRQ_HANDLED; | 1355 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); |
1356 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | ||
1357 | |||
1358 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1359 | } | ||
1360 | |||
1361 | static void rt2400pci_tbtt_tasklet(unsigned long data) | ||
1362 | { | ||
1363 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
1364 | rt2x00lib_beacondone(rt2x00dev); | ||
1365 | rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); | ||
1366 | } | ||
1367 | |||
1368 | static void rt2400pci_rxdone_tasklet(unsigned long data) | ||
1369 | { | ||
1370 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
1371 | rt2x00pci_rxdone(rt2x00dev); | ||
1372 | rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); | ||
1337 | } | 1373 | } |
1338 | 1374 | ||
1339 | static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | 1375 | static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) |
1340 | { | 1376 | { |
1341 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1377 | struct rt2x00_dev *rt2x00dev = dev_instance; |
1342 | u32 reg; | 1378 | u32 reg, mask; |
1379 | unsigned long flags; | ||
1343 | 1380 | ||
1344 | /* | 1381 | /* |
1345 | * Get the interrupt sources & saved to local variable. | 1382 | * Get the interrupt sources & saved to local variable. |
@@ -1354,14 +1391,44 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | |||
1354 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 1391 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
1355 | return IRQ_HANDLED; | 1392 | return IRQ_HANDLED; |
1356 | 1393 | ||
1357 | /* Store irqvalues for use in the interrupt thread. */ | 1394 | mask = reg; |
1358 | rt2x00dev->irqvalue[0] = reg; | ||
1359 | 1395 | ||
1360 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | 1396 | /* |
1361 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 1397 | * Schedule tasklets for interrupt handling. |
1362 | STATE_RADIO_IRQ_OFF_ISR); | 1398 | */ |
1399 | if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) | ||
1400 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); | ||
1363 | 1401 | ||
1364 | return IRQ_WAKE_THREAD; | 1402 | if (rt2x00_get_field32(reg, CSR7_RXDONE)) |
1403 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
1404 | |||
1405 | if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) || | ||
1406 | rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) || | ||
1407 | rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) { | ||
1408 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
1409 | /* | ||
1410 | * Mask out all txdone interrupts. | ||
1411 | */ | ||
1412 | rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1); | ||
1413 | rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1); | ||
1414 | rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1); | ||
1415 | } | ||
1416 | |||
1417 | /* | ||
1418 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
1419 | * the tasklet will reenable the appropriate interrupts. | ||
1420 | */ | ||
1421 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1422 | |||
1423 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | ||
1424 | reg |= mask; | ||
1425 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | ||
1426 | |||
1427 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1428 | |||
1429 | |||
1430 | |||
1431 | return IRQ_HANDLED; | ||
1365 | } | 1432 | } |
1366 | 1433 | ||
1367 | /* | 1434 | /* |
@@ -1655,7 +1722,9 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { | |||
1655 | 1722 | ||
1656 | static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | 1723 | static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { |
1657 | .irq_handler = rt2400pci_interrupt, | 1724 | .irq_handler = rt2400pci_interrupt, |
1658 | .irq_handler_thread = rt2400pci_interrupt_thread, | 1725 | .txstatus_tasklet = rt2400pci_txstatus_tasklet, |
1726 | .tbtt_tasklet = rt2400pci_tbtt_tasklet, | ||
1727 | .rxdone_tasklet = rt2400pci_rxdone_tasklet, | ||
1659 | .probe_hw = rt2400pci_probe_hw, | 1728 | .probe_hw = rt2400pci_probe_hw, |
1660 | .initialize = rt2x00pci_initialize, | 1729 | .initialize = rt2x00pci_initialize, |
1661 | .uninitialize = rt2x00pci_uninitialize, | 1730 | .uninitialize = rt2x00pci_uninitialize, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index a9ff26a27724..3ef1fb4185c0 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -311,9 +311,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
311 | * Enable synchronisation. | 311 | * Enable synchronisation. |
312 | */ | 312 | */ |
313 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 313 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
314 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | ||
315 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); | 314 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); |
316 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
317 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 315 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
318 | } | 316 | } |
319 | 317 | ||
@@ -737,6 +735,11 @@ static void rt2500pci_start_queue(struct data_queue *queue) | |||
737 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 735 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); |
738 | break; | 736 | break; |
739 | case QID_BEACON: | 737 | case QID_BEACON: |
738 | /* | ||
739 | * Allow the tbtt tasklet to be scheduled. | ||
740 | */ | ||
741 | tasklet_enable(&rt2x00dev->tbtt_tasklet); | ||
742 | |||
740 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 743 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
741 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | 744 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); |
742 | rt2x00_set_field32(®, CSR14_TBCN, 1); | 745 | rt2x00_set_field32(®, CSR14_TBCN, 1); |
@@ -798,6 +801,11 @@ static void rt2500pci_stop_queue(struct data_queue *queue) | |||
798 | rt2x00_set_field32(®, CSR14_TBCN, 0); | 801 | rt2x00_set_field32(®, CSR14_TBCN, 0); |
799 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 802 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
800 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 803 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
804 | |||
805 | /* | ||
806 | * Wait for possibly running tbtt tasklets. | ||
807 | */ | ||
808 | tasklet_disable(&rt2x00dev->tbtt_tasklet); | ||
801 | break; | 809 | break; |
802 | default: | 810 | default: |
803 | break; | 811 | break; |
@@ -1118,9 +1126,9 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1118 | static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 1126 | static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
1119 | enum dev_state state) | 1127 | enum dev_state state) |
1120 | { | 1128 | { |
1121 | int mask = (state == STATE_RADIO_IRQ_OFF) || | 1129 | int mask = (state == STATE_RADIO_IRQ_OFF); |
1122 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
1123 | u32 reg; | 1130 | u32 reg; |
1131 | unsigned long flags; | ||
1124 | 1132 | ||
1125 | /* | 1133 | /* |
1126 | * When interrupts are being enabled, the interrupt registers | 1134 | * When interrupts are being enabled, the interrupt registers |
@@ -1129,12 +1137,20 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1129 | if (state == STATE_RADIO_IRQ_ON) { | 1137 | if (state == STATE_RADIO_IRQ_ON) { |
1130 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | 1138 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); |
1131 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | 1139 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); |
1140 | |||
1141 | /* | ||
1142 | * Enable tasklets. | ||
1143 | */ | ||
1144 | tasklet_enable(&rt2x00dev->txstatus_tasklet); | ||
1145 | tasklet_enable(&rt2x00dev->rxdone_tasklet); | ||
1132 | } | 1146 | } |
1133 | 1147 | ||
1134 | /* | 1148 | /* |
1135 | * Only toggle the interrupts bits we are going to use. | 1149 | * Only toggle the interrupts bits we are going to use. |
1136 | * Non-checked interrupt bits are disabled by default. | 1150 | * Non-checked interrupt bits are disabled by default. |
1137 | */ | 1151 | */ |
1152 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1153 | |||
1138 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1154 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
1139 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); | 1155 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); |
1140 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); | 1156 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); |
@@ -1142,6 +1158,16 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1142 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); | 1158 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); |
1143 | rt2x00_set_field32(®, CSR8_RXDONE, mask); | 1159 | rt2x00_set_field32(®, CSR8_RXDONE, mask); |
1144 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1160 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); |
1161 | |||
1162 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1163 | |||
1164 | if (state == STATE_RADIO_IRQ_OFF) { | ||
1165 | /* | ||
1166 | * Ensure that all tasklets are finished. | ||
1167 | */ | ||
1168 | tasklet_disable(&rt2x00dev->txstatus_tasklet); | ||
1169 | tasklet_disable(&rt2x00dev->rxdone_tasklet); | ||
1170 | } | ||
1145 | } | 1171 | } |
1146 | 1172 | ||
1147 | static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 1173 | static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
@@ -1214,9 +1240,7 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1214 | rt2500pci_disable_radio(rt2x00dev); | 1240 | rt2500pci_disable_radio(rt2x00dev); |
1215 | break; | 1241 | break; |
1216 | case STATE_RADIO_IRQ_ON: | 1242 | case STATE_RADIO_IRQ_ON: |
1217 | case STATE_RADIO_IRQ_ON_ISR: | ||
1218 | case STATE_RADIO_IRQ_OFF: | 1243 | case STATE_RADIO_IRQ_OFF: |
1219 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1220 | rt2500pci_toggle_irq(rt2x00dev, state); | 1244 | rt2500pci_toggle_irq(rt2x00dev, state); |
1221 | break; | 1245 | break; |
1222 | case STATE_DEEP_SLEEP: | 1246 | case STATE_DEEP_SLEEP: |
@@ -1337,8 +1361,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, | |||
1337 | /* | 1361 | /* |
1338 | * Enable beaconing again. | 1362 | * Enable beaconing again. |
1339 | */ | 1363 | */ |
1340 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | ||
1341 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
1342 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); | 1364 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); |
1343 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 1365 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
1344 | } | 1366 | } |
@@ -1422,58 +1444,71 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1422 | } | 1444 | } |
1423 | } | 1445 | } |
1424 | 1446 | ||
1425 | static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance) | 1447 | static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, |
1448 | struct rt2x00_field32 irq_field) | ||
1426 | { | 1449 | { |
1427 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1450 | unsigned long flags; |
1428 | u32 reg = rt2x00dev->irqvalue[0]; | 1451 | u32 reg; |
1429 | 1452 | ||
1430 | /* | 1453 | /* |
1431 | * Handle interrupts, walk through all bits | 1454 | * Enable a single interrupt. The interrupt mask register |
1432 | * and run the tasks, the bits are checked in order of | 1455 | * access needs locking. |
1433 | * priority. | ||
1434 | */ | 1456 | */ |
1457 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1435 | 1458 | ||
1436 | /* | 1459 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
1437 | * 1 - Beacon timer expired interrupt. | 1460 | rt2x00_set_field32(®, irq_field, 0); |
1438 | */ | 1461 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); |
1439 | if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) | ||
1440 | rt2x00lib_beacondone(rt2x00dev); | ||
1441 | 1462 | ||
1442 | /* | 1463 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
1443 | * 2 - Rx ring done interrupt. | 1464 | } |
1444 | */ | ||
1445 | if (rt2x00_get_field32(reg, CSR7_RXDONE)) | ||
1446 | rt2x00pci_rxdone(rt2x00dev); | ||
1447 | 1465 | ||
1448 | /* | 1466 | static void rt2500pci_txstatus_tasklet(unsigned long data) |
1449 | * 3 - Atim ring transmit done interrupt. | 1467 | { |
1450 | */ | 1468 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
1451 | if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) | 1469 | u32 reg; |
1452 | rt2500pci_txdone(rt2x00dev, QID_ATIM); | 1470 | unsigned long flags; |
1453 | 1471 | ||
1454 | /* | 1472 | /* |
1455 | * 4 - Priority ring transmit done interrupt. | 1473 | * Handle all tx queues. |
1456 | */ | 1474 | */ |
1457 | if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) | 1475 | rt2500pci_txdone(rt2x00dev, QID_ATIM); |
1458 | rt2500pci_txdone(rt2x00dev, QID_AC_VO); | 1476 | rt2500pci_txdone(rt2x00dev, QID_AC_VO); |
1477 | rt2500pci_txdone(rt2x00dev, QID_AC_VI); | ||
1459 | 1478 | ||
1460 | /* | 1479 | /* |
1461 | * 5 - Tx ring transmit done interrupt. | 1480 | * Enable all TXDONE interrupts again. |
1462 | */ | 1481 | */ |
1463 | if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) | 1482 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
1464 | rt2500pci_txdone(rt2x00dev, QID_AC_VI); | 1483 | |
1484 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | ||
1485 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); | ||
1486 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); | ||
1487 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); | ||
1488 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | ||
1465 | 1489 | ||
1466 | /* Enable interrupts again. */ | 1490 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
1467 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 1491 | } |
1468 | STATE_RADIO_IRQ_ON_ISR); | ||
1469 | 1492 | ||
1470 | return IRQ_HANDLED; | 1493 | static void rt2500pci_tbtt_tasklet(unsigned long data) |
1494 | { | ||
1495 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
1496 | rt2x00lib_beacondone(rt2x00dev); | ||
1497 | rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); | ||
1498 | } | ||
1499 | |||
1500 | static void rt2500pci_rxdone_tasklet(unsigned long data) | ||
1501 | { | ||
1502 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
1503 | rt2x00pci_rxdone(rt2x00dev); | ||
1504 | rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); | ||
1471 | } | 1505 | } |
1472 | 1506 | ||
1473 | static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | 1507 | static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) |
1474 | { | 1508 | { |
1475 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1509 | struct rt2x00_dev *rt2x00dev = dev_instance; |
1476 | u32 reg; | 1510 | u32 reg, mask; |
1511 | unsigned long flags; | ||
1477 | 1512 | ||
1478 | /* | 1513 | /* |
1479 | * Get the interrupt sources & saved to local variable. | 1514 | * Get the interrupt sources & saved to local variable. |
@@ -1488,14 +1523,42 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | |||
1488 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 1523 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
1489 | return IRQ_HANDLED; | 1524 | return IRQ_HANDLED; |
1490 | 1525 | ||
1491 | /* Store irqvalues for use in the interrupt thread. */ | 1526 | mask = reg; |
1492 | rt2x00dev->irqvalue[0] = reg; | ||
1493 | 1527 | ||
1494 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | 1528 | /* |
1495 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 1529 | * Schedule tasklets for interrupt handling. |
1496 | STATE_RADIO_IRQ_OFF_ISR); | 1530 | */ |
1531 | if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) | ||
1532 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); | ||
1497 | 1533 | ||
1498 | return IRQ_WAKE_THREAD; | 1534 | if (rt2x00_get_field32(reg, CSR7_RXDONE)) |
1535 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
1536 | |||
1537 | if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) || | ||
1538 | rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) || | ||
1539 | rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) { | ||
1540 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
1541 | /* | ||
1542 | * Mask out all txdone interrupts. | ||
1543 | */ | ||
1544 | rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1); | ||
1545 | rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1); | ||
1546 | rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1); | ||
1547 | } | ||
1548 | |||
1549 | /* | ||
1550 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
1551 | * the tasklet will reenable the appropriate interrupts. | ||
1552 | */ | ||
1553 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1554 | |||
1555 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | ||
1556 | reg |= mask; | ||
1557 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | ||
1558 | |||
1559 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1560 | |||
1561 | return IRQ_HANDLED; | ||
1499 | } | 1562 | } |
1500 | 1563 | ||
1501 | /* | 1564 | /* |
@@ -1952,7 +2015,9 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { | |||
1952 | 2015 | ||
1953 | static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { | 2016 | static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { |
1954 | .irq_handler = rt2500pci_interrupt, | 2017 | .irq_handler = rt2500pci_interrupt, |
1955 | .irq_handler_thread = rt2500pci_interrupt_thread, | 2018 | .txstatus_tasklet = rt2500pci_txstatus_tasklet, |
2019 | .tbtt_tasklet = rt2500pci_tbtt_tasklet, | ||
2020 | .rxdone_tasklet = rt2500pci_rxdone_tasklet, | ||
1956 | .probe_hw = rt2500pci_probe_hw, | 2021 | .probe_hw = rt2500pci_probe_hw, |
1957 | .initialize = rt2x00pci_initialize, | 2022 | .initialize = rt2x00pci_initialize, |
1958 | .uninitialize = rt2x00pci_uninitialize, | 2023 | .uninitialize = rt2x00pci_uninitialize, |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 6b3b1de46792..01f385d5846c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -478,9 +478,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
478 | rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); | 478 | rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); |
479 | 479 | ||
480 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); | 480 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); |
481 | rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); | ||
482 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); | 481 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); |
483 | rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); | ||
484 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); | 482 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); |
485 | } | 483 | } |
486 | 484 | ||
@@ -1056,9 +1054,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1056 | rt2500usb_disable_radio(rt2x00dev); | 1054 | rt2500usb_disable_radio(rt2x00dev); |
1057 | break; | 1055 | break; |
1058 | case STATE_RADIO_IRQ_ON: | 1056 | case STATE_RADIO_IRQ_ON: |
1059 | case STATE_RADIO_IRQ_ON_ISR: | ||
1060 | case STATE_RADIO_IRQ_OFF: | 1057 | case STATE_RADIO_IRQ_OFF: |
1061 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1062 | /* No support, but no error either */ | 1058 | /* No support, but no error either */ |
1063 | break; | 1059 | break; |
1064 | case STATE_DEEP_SLEEP: | 1060 | case STATE_DEEP_SLEEP: |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index c7e615cebac1..ec8159ce0ee8 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -372,8 +372,12 @@ | |||
372 | 372 | ||
373 | /* | 373 | /* |
374 | * US_CYC_CNT | 374 | * US_CYC_CNT |
375 | * BT_MODE_EN: Bluetooth mode enable | ||
376 | * CLOCK CYCLE: Clock cycle count in 1us. | ||
377 | * PCI:0x21, PCIE:0x7d, USB:0x1e | ||
375 | */ | 378 | */ |
376 | #define US_CYC_CNT 0x02a4 | 379 | #define US_CYC_CNT 0x02a4 |
380 | #define US_CYC_CNT_BT_MODE_EN FIELD32(0x00000100) | ||
377 | #define US_CYC_CNT_CLOCK_CYCLE FIELD32(0x000000ff) | 381 | #define US_CYC_CNT_CLOCK_CYCLE FIELD32(0x000000ff) |
378 | 382 | ||
379 | /* | 383 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index f8ba01cbc6dd..c9bf074342ba 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -818,8 +818,6 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | |||
818 | /* | 818 | /* |
819 | * Enable beaconing again. | 819 | * Enable beaconing again. |
820 | */ | 820 | */ |
821 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
822 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
823 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | 821 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); |
824 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 822 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
825 | 823 | ||
@@ -831,8 +829,8 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | |||
831 | } | 829 | } |
832 | EXPORT_SYMBOL_GPL(rt2800_write_beacon); | 830 | EXPORT_SYMBOL_GPL(rt2800_write_beacon); |
833 | 831 | ||
834 | static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, | 832 | static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev, |
835 | unsigned int beacon_base) | 833 | unsigned int beacon_base) |
836 | { | 834 | { |
837 | int i; | 835 | int i; |
838 | 836 | ||
@@ -845,6 +843,33 @@ static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, | |||
845 | rt2800_register_write(rt2x00dev, beacon_base + i, 0); | 843 | rt2800_register_write(rt2x00dev, beacon_base + i, 0); |
846 | } | 844 | } |
847 | 845 | ||
846 | void rt2800_clear_beacon(struct queue_entry *entry) | ||
847 | { | ||
848 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
849 | u32 reg; | ||
850 | |||
851 | /* | ||
852 | * Disable beaconing while we are reloading the beacon data, | ||
853 | * otherwise we might be sending out invalid data. | ||
854 | */ | ||
855 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
856 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
857 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
858 | |||
859 | /* | ||
860 | * Clear beacon. | ||
861 | */ | ||
862 | rt2800_clear_beacon_register(rt2x00dev, | ||
863 | HW_BEACON_OFFSET(entry->entry_idx)); | ||
864 | |||
865 | /* | ||
866 | * Enabled beaconing again. | ||
867 | */ | ||
868 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
869 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
870 | } | ||
871 | EXPORT_SYMBOL_GPL(rt2800_clear_beacon); | ||
872 | |||
848 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 873 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
849 | const struct rt2x00debug rt2800_rt2x00debug = { | 874 | const struct rt2x00debug rt2800_rt2x00debug = { |
850 | .owner = THIS_MODULE, | 875 | .owner = THIS_MODULE, |
@@ -1005,7 +1030,7 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, | |||
1005 | 1030 | ||
1006 | memset(&wcid_entry, 0, sizeof(wcid_entry)); | 1031 | memset(&wcid_entry, 0, sizeof(wcid_entry)); |
1007 | if (crypto->cmd == SET_KEY) | 1032 | if (crypto->cmd == SET_KEY) |
1008 | memcpy(&wcid_entry, crypto->address, ETH_ALEN); | 1033 | memcpy(wcid_entry.mac, crypto->address, ETH_ALEN); |
1009 | rt2800_register_multiwrite(rt2x00dev, offset, | 1034 | rt2800_register_multiwrite(rt2x00dev, offset, |
1010 | &wcid_entry, sizeof(wcid_entry)); | 1035 | &wcid_entry, sizeof(wcid_entry)); |
1011 | } | 1036 | } |
@@ -1155,29 +1180,11 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | |||
1155 | 1180 | ||
1156 | if (flags & CONFIG_UPDATE_TYPE) { | 1181 | if (flags & CONFIG_UPDATE_TYPE) { |
1157 | /* | 1182 | /* |
1158 | * Clear current synchronisation setup. | ||
1159 | */ | ||
1160 | rt2800_clear_beacon(rt2x00dev, | ||
1161 | HW_BEACON_OFFSET(intf->beacon->entry_idx)); | ||
1162 | /* | ||
1163 | * Enable synchronisation. | 1183 | * Enable synchronisation. |
1164 | */ | 1184 | */ |
1165 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 1185 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
1166 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
1167 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); | 1186 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); |
1168 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, | ||
1169 | (conf->sync == TSF_SYNC_ADHOC || | ||
1170 | conf->sync == TSF_SYNC_AP_NONE)); | ||
1171 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1187 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1172 | |||
1173 | /* | ||
1174 | * Enable pre tbtt interrupt for beaconing modes | ||
1175 | */ | ||
1176 | rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
1177 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, | ||
1178 | (conf->sync == TSF_SYNC_AP_NONE)); | ||
1179 | rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
1180 | |||
1181 | } | 1188 | } |
1182 | 1189 | ||
1183 | if (flags & CONFIG_UPDATE_MAC) { | 1190 | if (flags & CONFIG_UPDATE_MAC) { |
@@ -2187,19 +2194,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
2187 | /* | 2194 | /* |
2188 | * Clear all beacons | 2195 | * Clear all beacons |
2189 | */ | 2196 | */ |
2190 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0); | 2197 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0); |
2191 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1); | 2198 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1); |
2192 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2); | 2199 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2); |
2193 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3); | 2200 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3); |
2194 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4); | 2201 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4); |
2195 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5); | 2202 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5); |
2196 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6); | 2203 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6); |
2197 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7); | 2204 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7); |
2198 | 2205 | ||
2199 | if (rt2x00_is_usb(rt2x00dev)) { | 2206 | if (rt2x00_is_usb(rt2x00dev)) { |
2200 | rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); | 2207 | rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); |
2201 | rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30); | 2208 | rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30); |
2202 | rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); | 2209 | rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); |
2210 | } else if (rt2x00_is_pcie(rt2x00dev)) { | ||
2211 | rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); | ||
2212 | rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 125); | ||
2213 | rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); | ||
2203 | } | 2214 | } |
2204 | 2215 | ||
2205 | rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); | 2216 | rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 3efafb78ff77..0c92d86a36f4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -156,6 +156,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev); | |||
156 | void rt2800_txdone_entry(struct queue_entry *entry, u32 status); | 156 | void rt2800_txdone_entry(struct queue_entry *entry, u32 status); |
157 | 157 | ||
158 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); | 158 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); |
159 | void rt2800_clear_beacon(struct queue_entry *entry); | ||
159 | 160 | ||
160 | extern const struct rt2x00debug rt2800_rt2x00debug; | 161 | extern const struct rt2x00debug rt2800_rt2x00debug; |
161 | 162 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index bfc2fc5c1c22..8f4dfc3d8023 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -200,11 +200,22 @@ static void rt2800pci_start_queue(struct data_queue *queue) | |||
200 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 200 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
201 | break; | 201 | break; |
202 | case QID_BEACON: | 202 | case QID_BEACON: |
203 | /* | ||
204 | * Allow beacon tasklets to be scheduled for periodic | ||
205 | * beacon updates. | ||
206 | */ | ||
207 | tasklet_enable(&rt2x00dev->tbtt_tasklet); | ||
208 | tasklet_enable(&rt2x00dev->pretbtt_tasklet); | ||
209 | |||
203 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 210 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
204 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | 211 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); |
205 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | 212 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); |
206 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | 213 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); |
207 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 214 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
215 | |||
216 | rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
217 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); | ||
218 | rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
208 | break; | 219 | break; |
209 | default: | 220 | default: |
210 | break; | 221 | break; |
@@ -250,6 +261,16 @@ static void rt2800pci_stop_queue(struct data_queue *queue) | |||
250 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | 261 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); |
251 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | 262 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); |
252 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 263 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
264 | |||
265 | rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
266 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); | ||
267 | rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
268 | |||
269 | /* | ||
270 | * Wait for tbtt tasklets to finish. | ||
271 | */ | ||
272 | tasklet_disable(&rt2x00dev->tbtt_tasklet); | ||
273 | tasklet_disable(&rt2x00dev->pretbtt_tasklet); | ||
253 | break; | 274 | break; |
254 | default: | 275 | default: |
255 | break; | 276 | break; |
@@ -397,9 +418,9 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | |||
397 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 418 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
398 | enum dev_state state) | 419 | enum dev_state state) |
399 | { | 420 | { |
400 | int mask = (state == STATE_RADIO_IRQ_ON) || | 421 | int mask = (state == STATE_RADIO_IRQ_ON); |
401 | (state == STATE_RADIO_IRQ_ON_ISR); | ||
402 | u32 reg; | 422 | u32 reg; |
423 | unsigned long flags; | ||
403 | 424 | ||
404 | /* | 425 | /* |
405 | * When interrupts are being enabled, the interrupt registers | 426 | * When interrupts are being enabled, the interrupt registers |
@@ -408,8 +429,17 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
408 | if (state == STATE_RADIO_IRQ_ON) { | 429 | if (state == STATE_RADIO_IRQ_ON) { |
409 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 430 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
410 | rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | 431 | rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); |
432 | |||
433 | /* | ||
434 | * Enable tasklets. The beacon related tasklets are | ||
435 | * enabled when the beacon queue is started. | ||
436 | */ | ||
437 | tasklet_enable(&rt2x00dev->txstatus_tasklet); | ||
438 | tasklet_enable(&rt2x00dev->rxdone_tasklet); | ||
439 | tasklet_enable(&rt2x00dev->autowake_tasklet); | ||
411 | } | 440 | } |
412 | 441 | ||
442 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
413 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); | 443 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); |
414 | rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); | 444 | rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); |
415 | rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); | 445 | rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); |
@@ -430,6 +460,17 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
430 | rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); | 460 | rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); |
431 | rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); | 461 | rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); |
432 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | 462 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); |
463 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
464 | |||
465 | if (state == STATE_RADIO_IRQ_OFF) { | ||
466 | /* | ||
467 | * Ensure that all tasklets are finished before | ||
468 | * disabling the interrupts. | ||
469 | */ | ||
470 | tasklet_disable(&rt2x00dev->txstatus_tasklet); | ||
471 | tasklet_disable(&rt2x00dev->rxdone_tasklet); | ||
472 | tasklet_disable(&rt2x00dev->autowake_tasklet); | ||
473 | } | ||
433 | } | 474 | } |
434 | 475 | ||
435 | static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) | 476 | static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) |
@@ -522,9 +563,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
522 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); | 563 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); |
523 | break; | 564 | break; |
524 | case STATE_RADIO_IRQ_ON: | 565 | case STATE_RADIO_IRQ_ON: |
525 | case STATE_RADIO_IRQ_ON_ISR: | ||
526 | case STATE_RADIO_IRQ_OFF: | 566 | case STATE_RADIO_IRQ_OFF: |
527 | case STATE_RADIO_IRQ_OFF_ISR: | ||
528 | rt2800pci_toggle_irq(rt2x00dev, state); | 567 | rt2800pci_toggle_irq(rt2x00dev, state); |
529 | break; | 568 | break; |
530 | case STATE_DEEP_SLEEP: | 569 | case STATE_DEEP_SLEEP: |
@@ -636,6 +675,12 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
636 | */ | 675 | */ |
637 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | 676 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; |
638 | 677 | ||
678 | /* | ||
679 | * The hardware has already checked the Michael Mic and has | ||
680 | * stripped it from the frame. Signal this to mac80211. | ||
681 | */ | ||
682 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
683 | |||
639 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | 684 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) |
640 | rxdesc->flags |= RX_FLAG_DECRYPTED; | 685 | rxdesc->flags |= RX_FLAG_DECRYPTED; |
641 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | 686 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) |
@@ -710,45 +755,60 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
710 | } | 755 | } |
711 | } | 756 | } |
712 | 757 | ||
713 | static void rt2800pci_txstatus_tasklet(unsigned long data) | 758 | static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, |
714 | { | 759 | struct rt2x00_field32 irq_field) |
715 | rt2800pci_txdone((struct rt2x00_dev *)data); | ||
716 | } | ||
717 | |||
718 | static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) | ||
719 | { | 760 | { |
720 | struct rt2x00_dev *rt2x00dev = dev_instance; | 761 | unsigned long flags; |
721 | u32 reg = rt2x00dev->irqvalue[0]; | 762 | u32 reg; |
722 | 763 | ||
723 | /* | 764 | /* |
724 | * 1 - Pre TBTT interrupt. | 765 | * Enable a single interrupt. The interrupt mask register |
766 | * access needs locking. | ||
725 | */ | 767 | */ |
726 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) | 768 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
727 | rt2x00lib_pretbtt(rt2x00dev); | 769 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); |
770 | rt2x00_set_field32(®, irq_field, 1); | ||
771 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
772 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
773 | } | ||
728 | 774 | ||
729 | /* | 775 | static void rt2800pci_txstatus_tasklet(unsigned long data) |
730 | * 2 - Beacondone interrupt. | 776 | { |
731 | */ | 777 | rt2800pci_txdone((struct rt2x00_dev *)data); |
732 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) | ||
733 | rt2x00lib_beacondone(rt2x00dev); | ||
734 | 778 | ||
735 | /* | 779 | /* |
736 | * 3 - Rx ring done interrupt. | 780 | * No need to enable the tx status interrupt here as we always |
781 | * leave it enabled to minimize the possibility of a tx status | ||
782 | * register overflow. See comment in interrupt handler. | ||
737 | */ | 783 | */ |
738 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) | 784 | } |
739 | rt2x00pci_rxdone(rt2x00dev); | ||
740 | 785 | ||
741 | /* | 786 | static void rt2800pci_pretbtt_tasklet(unsigned long data) |
742 | * 4 - Auto wakeup interrupt. | 787 | { |
743 | */ | 788 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
744 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | 789 | rt2x00lib_pretbtt(rt2x00dev); |
745 | rt2800pci_wakeup(rt2x00dev); | 790 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT); |
791 | } | ||
746 | 792 | ||
747 | /* Enable interrupts again. */ | 793 | static void rt2800pci_tbtt_tasklet(unsigned long data) |
748 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 794 | { |
749 | STATE_RADIO_IRQ_ON_ISR); | 795 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
796 | rt2x00lib_beacondone(rt2x00dev); | ||
797 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); | ||
798 | } | ||
750 | 799 | ||
751 | return IRQ_HANDLED; | 800 | static void rt2800pci_rxdone_tasklet(unsigned long data) |
801 | { | ||
802 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
803 | rt2x00pci_rxdone(rt2x00dev); | ||
804 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); | ||
805 | } | ||
806 | |||
807 | static void rt2800pci_autowake_tasklet(unsigned long data) | ||
808 | { | ||
809 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
810 | rt2800pci_wakeup(rt2x00dev); | ||
811 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP); | ||
752 | } | 812 | } |
753 | 813 | ||
754 | static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | 814 | static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) |
@@ -794,8 +854,8 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | |||
794 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | 854 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) |
795 | { | 855 | { |
796 | struct rt2x00_dev *rt2x00dev = dev_instance; | 856 | struct rt2x00_dev *rt2x00dev = dev_instance; |
797 | u32 reg; | 857 | u32 reg, mask; |
798 | irqreturn_t ret = IRQ_HANDLED; | 858 | unsigned long flags; |
799 | 859 | ||
800 | /* Read status and ACK all interrupts */ | 860 | /* Read status and ACK all interrupts */ |
801 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 861 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
@@ -807,38 +867,44 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | |||
807 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 867 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
808 | return IRQ_HANDLED; | 868 | return IRQ_HANDLED; |
809 | 869 | ||
810 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | 870 | /* |
811 | rt2800pci_txstatus_interrupt(rt2x00dev); | 871 | * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits |
872 | * for interrupts and interrupt masks we can just use the value of | ||
873 | * INT_SOURCE_CSR to create the interrupt mask. | ||
874 | */ | ||
875 | mask = ~reg; | ||
812 | 876 | ||
813 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) || | 877 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { |
814 | rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) || | 878 | rt2800pci_txstatus_interrupt(rt2x00dev); |
815 | rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) || | ||
816 | rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) { | ||
817 | /* | 879 | /* |
818 | * All other interrupts are handled in the interrupt thread. | 880 | * Never disable the TX_FIFO_STATUS interrupt. |
819 | * Store irqvalue for use in the interrupt thread. | ||
820 | */ | 881 | */ |
821 | rt2x00dev->irqvalue[0] = reg; | 882 | rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); |
883 | } | ||
822 | 884 | ||
823 | /* | 885 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) |
824 | * Disable interrupts, will be enabled again in the | 886 | tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); |
825 | * interrupt thread. | ||
826 | */ | ||
827 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
828 | STATE_RADIO_IRQ_OFF_ISR); | ||
829 | 887 | ||
830 | /* | 888 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) |
831 | * Leave the TX_FIFO_STATUS interrupt enabled to not lose any | 889 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); |
832 | * tx status reports. | ||
833 | */ | ||
834 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
835 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
836 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
837 | 890 | ||
838 | ret = IRQ_WAKE_THREAD; | 891 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) |
839 | } | 892 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); |
840 | 893 | ||
841 | return ret; | 894 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) |
895 | tasklet_schedule(&rt2x00dev->autowake_tasklet); | ||
896 | |||
897 | /* | ||
898 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
899 | * the tasklet will reenable the appropriate interrupts. | ||
900 | */ | ||
901 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
902 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
903 | reg &= mask; | ||
904 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
905 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
906 | |||
907 | return IRQ_HANDLED; | ||
842 | } | 908 | } |
843 | 909 | ||
844 | /* | 910 | /* |
@@ -953,8 +1019,11 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
953 | 1019 | ||
954 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 1020 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
955 | .irq_handler = rt2800pci_interrupt, | 1021 | .irq_handler = rt2800pci_interrupt, |
956 | .irq_handler_thread = rt2800pci_interrupt_thread, | 1022 | .txstatus_tasklet = rt2800pci_txstatus_tasklet, |
957 | .txstatus_tasklet = rt2800pci_txstatus_tasklet, | 1023 | .pretbtt_tasklet = rt2800pci_pretbtt_tasklet, |
1024 | .tbtt_tasklet = rt2800pci_tbtt_tasklet, | ||
1025 | .rxdone_tasklet = rt2800pci_rxdone_tasklet, | ||
1026 | .autowake_tasklet = rt2800pci_autowake_tasklet, | ||
958 | .probe_hw = rt2800pci_probe_hw, | 1027 | .probe_hw = rt2800pci_probe_hw, |
959 | .get_firmware_name = rt2800pci_get_firmware_name, | 1028 | .get_firmware_name = rt2800pci_get_firmware_name, |
960 | .check_firmware = rt2800_check_firmware, | 1029 | .check_firmware = rt2800_check_firmware, |
@@ -974,6 +1043,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
974 | .write_tx_desc = rt2800pci_write_tx_desc, | 1043 | .write_tx_desc = rt2800pci_write_tx_desc, |
975 | .write_tx_data = rt2800_write_tx_data, | 1044 | .write_tx_data = rt2800_write_tx_data, |
976 | .write_beacon = rt2800_write_beacon, | 1045 | .write_beacon = rt2800_write_beacon, |
1046 | .clear_beacon = rt2800_clear_beacon, | ||
977 | .fill_rxdone = rt2800pci_fill_rxdone, | 1047 | .fill_rxdone = rt2800pci_fill_rxdone, |
978 | .config_shared_key = rt2800_config_shared_key, | 1048 | .config_shared_key = rt2800_config_shared_key, |
979 | .config_pairwise_key = rt2800_config_pairwise_key, | 1049 | .config_pairwise_key = rt2800_config_pairwise_key, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index b97a4a54ff4c..5d91561e0de7 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -253,9 +253,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
253 | rt2800usb_set_state(rt2x00dev, STATE_SLEEP); | 253 | rt2800usb_set_state(rt2x00dev, STATE_SLEEP); |
254 | break; | 254 | break; |
255 | case STATE_RADIO_IRQ_ON: | 255 | case STATE_RADIO_IRQ_ON: |
256 | case STATE_RADIO_IRQ_ON_ISR: | ||
257 | case STATE_RADIO_IRQ_OFF: | 256 | case STATE_RADIO_IRQ_OFF: |
258 | case STATE_RADIO_IRQ_OFF_ISR: | ||
259 | /* No support, but no error either */ | 257 | /* No support, but no error either */ |
260 | break; | 258 | break; |
261 | case STATE_DEEP_SLEEP: | 259 | case STATE_DEEP_SLEEP: |
@@ -486,6 +484,12 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
486 | */ | 484 | */ |
487 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | 485 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; |
488 | 486 | ||
487 | /* | ||
488 | * The hardware has already checked the Michael Mic and has | ||
489 | * stripped it from the frame. Signal this to mac80211. | ||
490 | */ | ||
491 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
492 | |||
489 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | 493 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) |
490 | rxdesc->flags |= RX_FLAG_DECRYPTED; | 494 | rxdesc->flags |= RX_FLAG_DECRYPTED; |
491 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | 495 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) |
@@ -633,6 +637,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
633 | .write_tx_desc = rt2800usb_write_tx_desc, | 637 | .write_tx_desc = rt2800usb_write_tx_desc, |
634 | .write_tx_data = rt2800usb_write_tx_data, | 638 | .write_tx_data = rt2800usb_write_tx_data, |
635 | .write_beacon = rt2800_write_beacon, | 639 | .write_beacon = rt2800_write_beacon, |
640 | .clear_beacon = rt2800_clear_beacon, | ||
636 | .get_tx_data_len = rt2800usb_get_tx_data_len, | 641 | .get_tx_data_len = rt2800usb_get_tx_data_len, |
637 | .fill_rxdone = rt2800usb_fill_rxdone, | 642 | .fill_rxdone = rt2800usb_fill_rxdone, |
638 | .config_shared_key = rt2800_config_shared_key, | 643 | .config_shared_key = rt2800_config_shared_key, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 84aaf393da43..39bc2faf1793 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -368,6 +368,7 @@ struct rt2x00_intf { | |||
368 | * dedicated beacon entry. | 368 | * dedicated beacon entry. |
369 | */ | 369 | */ |
370 | struct queue_entry *beacon; | 370 | struct queue_entry *beacon; |
371 | bool enable_beacon; | ||
371 | 372 | ||
372 | /* | 373 | /* |
373 | * Actions that needed rescheduling. | 374 | * Actions that needed rescheduling. |
@@ -511,14 +512,13 @@ struct rt2x00lib_ops { | |||
511 | irq_handler_t irq_handler; | 512 | irq_handler_t irq_handler; |
512 | 513 | ||
513 | /* | 514 | /* |
514 | * Threaded Interrupt handlers. | ||
515 | */ | ||
516 | irq_handler_t irq_handler_thread; | ||
517 | |||
518 | /* | ||
519 | * TX status tasklet handler. | 515 | * TX status tasklet handler. |
520 | */ | 516 | */ |
521 | void (*txstatus_tasklet) (unsigned long data); | 517 | void (*txstatus_tasklet) (unsigned long data); |
518 | void (*pretbtt_tasklet) (unsigned long data); | ||
519 | void (*tbtt_tasklet) (unsigned long data); | ||
520 | void (*rxdone_tasklet) (unsigned long data); | ||
521 | void (*autowake_tasklet) (unsigned long data); | ||
522 | 522 | ||
523 | /* | 523 | /* |
524 | * Device init handlers. | 524 | * Device init handlers. |
@@ -573,6 +573,7 @@ struct rt2x00lib_ops { | |||
573 | struct txentry_desc *txdesc); | 573 | struct txentry_desc *txdesc); |
574 | void (*write_beacon) (struct queue_entry *entry, | 574 | void (*write_beacon) (struct queue_entry *entry, |
575 | struct txentry_desc *txdesc); | 575 | struct txentry_desc *txdesc); |
576 | void (*clear_beacon) (struct queue_entry *entry); | ||
576 | int (*get_tx_data_len) (struct queue_entry *entry); | 577 | int (*get_tx_data_len) (struct queue_entry *entry); |
577 | 578 | ||
578 | /* | 579 | /* |
@@ -788,10 +789,12 @@ struct rt2x00_dev { | |||
788 | * - Open ap interface count. | 789 | * - Open ap interface count. |
789 | * - Open sta interface count. | 790 | * - Open sta interface count. |
790 | * - Association count. | 791 | * - Association count. |
792 | * - Beaconing enabled count. | ||
791 | */ | 793 | */ |
792 | unsigned int intf_ap_count; | 794 | unsigned int intf_ap_count; |
793 | unsigned int intf_sta_count; | 795 | unsigned int intf_sta_count; |
794 | unsigned int intf_associated; | 796 | unsigned int intf_associated; |
797 | unsigned int intf_beaconing; | ||
795 | 798 | ||
796 | /* | 799 | /* |
797 | * Link quality | 800 | * Link quality |
@@ -857,6 +860,13 @@ struct rt2x00_dev { | |||
857 | */ | 860 | */ |
858 | struct ieee80211_low_level_stats low_level_stats; | 861 | struct ieee80211_low_level_stats low_level_stats; |
859 | 862 | ||
863 | /** | ||
864 | * Work queue for all work which should not be placed | ||
865 | * on the mac80211 workqueue (because of dependencies | ||
866 | * between various work structures). | ||
867 | */ | ||
868 | struct workqueue_struct *workqueue; | ||
869 | |||
860 | /* | 870 | /* |
861 | * Scheduled work. | 871 | * Scheduled work. |
862 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() | 872 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() |
@@ -887,12 +897,6 @@ struct rt2x00_dev { | |||
887 | const struct firmware *fw; | 897 | const struct firmware *fw; |
888 | 898 | ||
889 | /* | 899 | /* |
890 | * Interrupt values, stored between interrupt service routine | ||
891 | * and interrupt thread routine. | ||
892 | */ | ||
893 | u32 irqvalue[2]; | ||
894 | |||
895 | /* | ||
896 | * FIFO for storing tx status reports between isr and tasklet. | 900 | * FIFO for storing tx status reports between isr and tasklet. |
897 | */ | 901 | */ |
898 | DECLARE_KFIFO_PTR(txstatus_fifo, u32); | 902 | DECLARE_KFIFO_PTR(txstatus_fifo, u32); |
@@ -901,6 +905,15 @@ struct rt2x00_dev { | |||
901 | * Tasklet for processing tx status reports (rt2800pci). | 905 | * Tasklet for processing tx status reports (rt2800pci). |
902 | */ | 906 | */ |
903 | struct tasklet_struct txstatus_tasklet; | 907 | struct tasklet_struct txstatus_tasklet; |
908 | struct tasklet_struct pretbtt_tasklet; | ||
909 | struct tasklet_struct tbtt_tasklet; | ||
910 | struct tasklet_struct rxdone_tasklet; | ||
911 | struct tasklet_struct autowake_tasklet; | ||
912 | |||
913 | /* | ||
914 | * Protect the interrupt mask register. | ||
915 | */ | ||
916 | spinlock_t irqmask_lock; | ||
904 | }; | 917 | }; |
905 | 918 | ||
906 | /* | 919 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 31b7db05abd9..9de9dbe94399 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -121,7 +121,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | |||
121 | return; | 121 | return; |
122 | 122 | ||
123 | if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) | 123 | if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) |
124 | rt2x00queue_update_beacon(rt2x00dev, vif, true); | 124 | rt2x00queue_update_beacon(rt2x00dev, vif); |
125 | } | 125 | } |
126 | 126 | ||
127 | static void rt2x00lib_intf_scheduled(struct work_struct *work) | 127 | static void rt2x00lib_intf_scheduled(struct work_struct *work) |
@@ -174,7 +174,13 @@ static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac, | |||
174 | vif->type != NL80211_IFTYPE_WDS) | 174 | vif->type != NL80211_IFTYPE_WDS) |
175 | return; | 175 | return; |
176 | 176 | ||
177 | rt2x00queue_update_beacon(rt2x00dev, vif, true); | 177 | /* |
178 | * Update the beacon without locking. This is safe on PCI devices | ||
179 | * as they only update the beacon periodically here. This should | ||
180 | * never be called for USB devices. | ||
181 | */ | ||
182 | WARN_ON(rt2x00_is_usb(rt2x00dev)); | ||
183 | rt2x00queue_update_beacon_locked(rt2x00dev, vif); | ||
178 | } | 184 | } |
179 | 185 | ||
180 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | 186 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) |
@@ -183,9 +189,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
183 | return; | 189 | return; |
184 | 190 | ||
185 | /* send buffered bc/mc frames out for every bssid */ | 191 | /* send buffered bc/mc frames out for every bssid */ |
186 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 192 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
187 | rt2x00lib_bc_buffer_iter, | 193 | rt2x00lib_bc_buffer_iter, |
188 | rt2x00dev); | 194 | rt2x00dev); |
189 | /* | 195 | /* |
190 | * Devices with pre tbtt interrupt don't need to update the beacon | 196 | * Devices with pre tbtt interrupt don't need to update the beacon |
191 | * here as they will fetch the next beacon directly prior to | 197 | * here as they will fetch the next beacon directly prior to |
@@ -195,9 +201,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
195 | return; | 201 | return; |
196 | 202 | ||
197 | /* fetch next beacon */ | 203 | /* fetch next beacon */ |
198 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 204 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
199 | rt2x00lib_beaconupdate_iter, | 205 | rt2x00lib_beaconupdate_iter, |
200 | rt2x00dev); | 206 | rt2x00dev); |
201 | } | 207 | } |
202 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); | 208 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); |
203 | 209 | ||
@@ -207,9 +213,9 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev) | |||
207 | return; | 213 | return; |
208 | 214 | ||
209 | /* fetch next beacon */ | 215 | /* fetch next beacon */ |
210 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 216 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
211 | rt2x00lib_beaconupdate_iter, | 217 | rt2x00lib_beaconupdate_iter, |
212 | rt2x00dev); | 218 | rt2x00dev); |
213 | } | 219 | } |
214 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); | 220 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); |
215 | 221 | ||
@@ -815,15 +821,29 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
815 | GFP_KERNEL); | 821 | GFP_KERNEL); |
816 | if (status) | 822 | if (status) |
817 | return status; | 823 | return status; |
824 | } | ||
818 | 825 | ||
819 | /* tasklet for processing the tx status reports. */ | 826 | /* |
820 | if (rt2x00dev->ops->lib->txstatus_tasklet) | 827 | * Initialize tasklets if used by the driver. Tasklets are |
821 | tasklet_init(&rt2x00dev->txstatus_tasklet, | 828 | * disabled until the interrupts are turned on. The driver |
822 | rt2x00dev->ops->lib->txstatus_tasklet, | 829 | * has to handle that. |
823 | (unsigned long)rt2x00dev); | 830 | */ |
824 | 831 | #define RT2X00_TASKLET_INIT(taskletname) \ | |
832 | if (rt2x00dev->ops->lib->taskletname) { \ | ||
833 | tasklet_init(&rt2x00dev->taskletname, \ | ||
834 | rt2x00dev->ops->lib->taskletname, \ | ||
835 | (unsigned long)rt2x00dev); \ | ||
836 | tasklet_disable(&rt2x00dev->taskletname); \ | ||
825 | } | 837 | } |
826 | 838 | ||
839 | RT2X00_TASKLET_INIT(txstatus_tasklet); | ||
840 | RT2X00_TASKLET_INIT(pretbtt_tasklet); | ||
841 | RT2X00_TASKLET_INIT(tbtt_tasklet); | ||
842 | RT2X00_TASKLET_INIT(rxdone_tasklet); | ||
843 | RT2X00_TASKLET_INIT(autowake_tasklet); | ||
844 | |||
845 | #undef RT2X00_TASKLET_INIT | ||
846 | |||
827 | /* | 847 | /* |
828 | * Register HW. | 848 | * Register HW. |
829 | */ | 849 | */ |
@@ -952,6 +972,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
952 | { | 972 | { |
953 | int retval = -ENOMEM; | 973 | int retval = -ENOMEM; |
954 | 974 | ||
975 | spin_lock_init(&rt2x00dev->irqmask_lock); | ||
955 | mutex_init(&rt2x00dev->csr_mutex); | 976 | mutex_init(&rt2x00dev->csr_mutex); |
956 | 977 | ||
957 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); | 978 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
@@ -976,8 +997,15 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
976 | BIT(NL80211_IFTYPE_WDS); | 997 | BIT(NL80211_IFTYPE_WDS); |
977 | 998 | ||
978 | /* | 999 | /* |
979 | * Initialize configuration work. | 1000 | * Initialize work. |
980 | */ | 1001 | */ |
1002 | rt2x00dev->workqueue = | ||
1003 | alloc_ordered_workqueue(wiphy_name(rt2x00dev->hw->wiphy), 0); | ||
1004 | if (!rt2x00dev->workqueue) { | ||
1005 | retval = -ENOMEM; | ||
1006 | goto exit; | ||
1007 | } | ||
1008 | |||
981 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); | 1009 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); |
982 | 1010 | ||
983 | /* | 1011 | /* |
@@ -1036,6 +1064,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1036 | cancel_work_sync(&rt2x00dev->intf_work); | 1064 | cancel_work_sync(&rt2x00dev->intf_work); |
1037 | cancel_work_sync(&rt2x00dev->rxdone_work); | 1065 | cancel_work_sync(&rt2x00dev->rxdone_work); |
1038 | cancel_work_sync(&rt2x00dev->txdone_work); | 1066 | cancel_work_sync(&rt2x00dev->txdone_work); |
1067 | destroy_workqueue(rt2x00dev->workqueue); | ||
1039 | 1068 | ||
1040 | /* | 1069 | /* |
1041 | * Free the tx status fifo. | 1070 | * Free the tx status fifo. |
@@ -1046,6 +1075,10 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1046 | * Kill the tx status tasklet. | 1075 | * Kill the tx status tasklet. |
1047 | */ | 1076 | */ |
1048 | tasklet_kill(&rt2x00dev->txstatus_tasklet); | 1077 | tasklet_kill(&rt2x00dev->txstatus_tasklet); |
1078 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
1079 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
1080 | tasklet_kill(&rt2x00dev->rxdone_tasklet); | ||
1081 | tasklet_kill(&rt2x00dev->autowake_tasklet); | ||
1049 | 1082 | ||
1050 | /* | 1083 | /* |
1051 | * Uninitialize device. | 1084 | * Uninitialize device. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index a105c500627b..2d94cbaf5f4a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -157,14 +157,30 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, | |||
157 | bool local); | 157 | bool local); |
158 | 158 | ||
159 | /** | 159 | /** |
160 | * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware | 160 | * rt2x00queue_update_beacon - Send new beacon from mac80211 |
161 | * to hardware. Handles locking by itself (mutex). | ||
161 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 162 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
162 | * @vif: Interface for which the beacon should be updated. | 163 | * @vif: Interface for which the beacon should be updated. |
163 | * @enable_beacon: Enable beaconing | ||
164 | */ | 164 | */ |
165 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | 165 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, |
166 | struct ieee80211_vif *vif, | 166 | struct ieee80211_vif *vif); |
167 | const bool enable_beacon); | 167 | |
168 | /** | ||
169 | * rt2x00queue_update_beacon_locked - Send new beacon from mac80211 | ||
170 | * to hardware. Caller needs to ensure locking. | ||
171 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
172 | * @vif: Interface for which the beacon should be updated. | ||
173 | */ | ||
174 | int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev, | ||
175 | struct ieee80211_vif *vif); | ||
176 | |||
177 | /** | ||
178 | * rt2x00queue_clear_beacon - Clear beacon in hardware | ||
179 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
180 | * @vif: Interface for which the beacon should be updated. | ||
181 | */ | ||
182 | int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, | ||
183 | struct ieee80211_vif *vif); | ||
168 | 184 | ||
169 | /** | 185 | /** |
170 | * rt2x00queue_index_inc - Index incrementation function | 186 | * rt2x00queue_index_inc - Index incrementation function |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index bfda60eaf4ef..c975b0a12e95 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -417,7 +417,8 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) | |||
417 | !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) | 417 | !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) |
418 | return; | 418 | return; |
419 | 419 | ||
420 | schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); | 420 | ieee80211_queue_delayed_work(rt2x00dev->hw, |
421 | &link->watchdog_work, WATCHDOG_INTERVAL); | ||
421 | } | 422 | } |
422 | 423 | ||
423 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) | 424 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) |
@@ -441,7 +442,9 @@ static void rt2x00link_watchdog(struct work_struct *work) | |||
441 | rt2x00dev->ops->lib->watchdog(rt2x00dev); | 442 | rt2x00dev->ops->lib->watchdog(rt2x00dev); |
442 | 443 | ||
443 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 444 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
444 | schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); | 445 | ieee80211_queue_delayed_work(rt2x00dev->hw, |
446 | &link->watchdog_work, | ||
447 | WATCHDOG_INTERVAL); | ||
445 | } | 448 | } |
446 | 449 | ||
447 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) | 450 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f3da051df39e..6a66021d8f65 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -617,11 +617,47 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
617 | bss_conf->bssid); | 617 | bss_conf->bssid); |
618 | 618 | ||
619 | /* | 619 | /* |
620 | * Update the beacon. | 620 | * Update the beacon. This is only required on USB devices. PCI |
621 | * devices fetch beacons periodically. | ||
621 | */ | 622 | */ |
622 | if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) | 623 | if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev)) |
623 | rt2x00queue_update_beacon(rt2x00dev, vif, | 624 | rt2x00queue_update_beacon(rt2x00dev, vif); |
624 | bss_conf->enable_beacon); | 625 | |
626 | /* | ||
627 | * Start/stop beaconing. | ||
628 | */ | ||
629 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | ||
630 | if (!bss_conf->enable_beacon && intf->enable_beacon) { | ||
631 | rt2x00queue_clear_beacon(rt2x00dev, vif); | ||
632 | rt2x00dev->intf_beaconing--; | ||
633 | intf->enable_beacon = false; | ||
634 | |||
635 | if (rt2x00dev->intf_beaconing == 0) { | ||
636 | /* | ||
637 | * Last beaconing interface disabled | ||
638 | * -> stop beacon queue. | ||
639 | */ | ||
640 | mutex_lock(&intf->beacon_skb_mutex); | ||
641 | rt2x00queue_stop_queue(rt2x00dev->bcn); | ||
642 | mutex_unlock(&intf->beacon_skb_mutex); | ||
643 | } | ||
644 | |||
645 | |||
646 | } else if (bss_conf->enable_beacon && !intf->enable_beacon) { | ||
647 | rt2x00dev->intf_beaconing++; | ||
648 | intf->enable_beacon = true; | ||
649 | |||
650 | if (rt2x00dev->intf_beaconing == 1) { | ||
651 | /* | ||
652 | * First beaconing interface enabled | ||
653 | * -> start beacon queue. | ||
654 | */ | ||
655 | mutex_lock(&intf->beacon_skb_mutex); | ||
656 | rt2x00queue_start_queue(rt2x00dev->bcn); | ||
657 | mutex_unlock(&intf->beacon_skb_mutex); | ||
658 | } | ||
659 | } | ||
660 | } | ||
625 | 661 | ||
626 | /* | 662 | /* |
627 | * When the association status has changed we must reset the link | 663 | * When the association status has changed we must reset the link |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index ace0b668c04e..4dd82b0b0520 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -160,10 +160,9 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) | |||
160 | /* | 160 | /* |
161 | * Register interrupt handler. | 161 | * Register interrupt handler. |
162 | */ | 162 | */ |
163 | status = request_threaded_irq(rt2x00dev->irq, | 163 | status = request_irq(rt2x00dev->irq, |
164 | rt2x00dev->ops->lib->irq_handler, | 164 | rt2x00dev->ops->lib->irq_handler, |
165 | rt2x00dev->ops->lib->irq_handler_thread, | 165 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); |
166 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); | ||
167 | if (status) { | 166 | if (status) { |
168 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", | 167 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", |
169 | rt2x00dev->irq, status); | 168 | rt2x00dev->irq, status); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index ca82b3a91697..fa17c83b9685 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -566,13 +566,10 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, | |||
566 | return 0; | 566 | return 0; |
567 | } | 567 | } |
568 | 568 | ||
569 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | 569 | int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, |
570 | struct ieee80211_vif *vif, | 570 | struct ieee80211_vif *vif) |
571 | const bool enable_beacon) | ||
572 | { | 571 | { |
573 | struct rt2x00_intf *intf = vif_to_intf(vif); | 572 | struct rt2x00_intf *intf = vif_to_intf(vif); |
574 | struct skb_frame_desc *skbdesc; | ||
575 | struct txentry_desc txdesc; | ||
576 | 573 | ||
577 | if (unlikely(!intf->beacon)) | 574 | if (unlikely(!intf->beacon)) |
578 | return -ENOBUFS; | 575 | return -ENOBUFS; |
@@ -584,17 +581,36 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | |||
584 | */ | 581 | */ |
585 | rt2x00queue_free_skb(intf->beacon); | 582 | rt2x00queue_free_skb(intf->beacon); |
586 | 583 | ||
587 | if (!enable_beacon) { | 584 | /* |
588 | rt2x00queue_stop_queue(intf->beacon->queue); | 585 | * Clear beacon (single bssid devices don't need to clear the beacon |
589 | mutex_unlock(&intf->beacon_skb_mutex); | 586 | * since the beacon queue will get stopped anyway). |
590 | return 0; | 587 | */ |
591 | } | 588 | if (rt2x00dev->ops->lib->clear_beacon) |
589 | rt2x00dev->ops->lib->clear_beacon(intf->beacon); | ||
590 | |||
591 | mutex_unlock(&intf->beacon_skb_mutex); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev, | ||
597 | struct ieee80211_vif *vif) | ||
598 | { | ||
599 | struct rt2x00_intf *intf = vif_to_intf(vif); | ||
600 | struct skb_frame_desc *skbdesc; | ||
601 | struct txentry_desc txdesc; | ||
602 | |||
603 | if (unlikely(!intf->beacon)) | ||
604 | return -ENOBUFS; | ||
605 | |||
606 | /* | ||
607 | * Clean up the beacon skb. | ||
608 | */ | ||
609 | rt2x00queue_free_skb(intf->beacon); | ||
592 | 610 | ||
593 | intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); | 611 | intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); |
594 | if (!intf->beacon->skb) { | 612 | if (!intf->beacon->skb) |
595 | mutex_unlock(&intf->beacon_skb_mutex); | ||
596 | return -ENOMEM; | 613 | return -ENOMEM; |
597 | } | ||
598 | 614 | ||
599 | /* | 615 | /* |
600 | * Copy all TX descriptor information into txdesc, | 616 | * Copy all TX descriptor information into txdesc, |
@@ -611,13 +627,25 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | |||
611 | skbdesc->entry = intf->beacon; | 627 | skbdesc->entry = intf->beacon; |
612 | 628 | ||
613 | /* | 629 | /* |
614 | * Send beacon to hardware and enable beacon genaration.. | 630 | * Send beacon to hardware. |
615 | */ | 631 | */ |
616 | rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); | 632 | rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); |
617 | 633 | ||
634 | return 0; | ||
635 | |||
636 | } | ||
637 | |||
638 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | ||
639 | struct ieee80211_vif *vif) | ||
640 | { | ||
641 | struct rt2x00_intf *intf = vif_to_intf(vif); | ||
642 | int ret; | ||
643 | |||
644 | mutex_lock(&intf->beacon_skb_mutex); | ||
645 | ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif); | ||
618 | mutex_unlock(&intf->beacon_skb_mutex); | 646 | mutex_unlock(&intf->beacon_skb_mutex); |
619 | 647 | ||
620 | return 0; | 648 | return ret; |
621 | } | 649 | } |
622 | 650 | ||
623 | void rt2x00queue_for_each_entry(struct data_queue *queue, | 651 | void rt2x00queue_for_each_entry(struct data_queue *queue, |
@@ -885,7 +913,7 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) | |||
885 | * The queue flush has failed... | 913 | * The queue flush has failed... |
886 | */ | 914 | */ |
887 | if (unlikely(!rt2x00queue_empty(queue))) | 915 | if (unlikely(!rt2x00queue_empty(queue))) |
888 | WARNING(queue->rt2x00dev, "Queue %d failed to flush", queue->qid); | 916 | WARNING(queue->rt2x00dev, "Queue %d failed to flush\n", queue->qid); |
889 | 917 | ||
890 | /* | 918 | /* |
891 | * Restore the queue to the previous status | 919 | * Restore the queue to the previous status |
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index e8259ae48ced..6f867eec49cc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h | |||
@@ -85,8 +85,6 @@ enum dev_state { | |||
85 | STATE_RADIO_OFF, | 85 | STATE_RADIO_OFF, |
86 | STATE_RADIO_IRQ_ON, | 86 | STATE_RADIO_IRQ_ON, |
87 | STATE_RADIO_IRQ_OFF, | 87 | STATE_RADIO_IRQ_OFF, |
88 | STATE_RADIO_IRQ_ON_ISR, | ||
89 | STATE_RADIO_IRQ_OFF_ISR, | ||
90 | }; | 88 | }; |
91 | 89 | ||
92 | /* | 90 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 1a9937d5aff6..fbe735f5b352 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -227,7 +227,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
227 | * Schedule the delayed work for reading the TX status | 227 | * Schedule the delayed work for reading the TX status |
228 | * from the device. | 228 | * from the device. |
229 | */ | 229 | */ |
230 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); | 230 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); |
231 | } | 231 | } |
232 | 232 | ||
233 | static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 233 | static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) |
@@ -320,7 +320,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
320 | * Schedule the delayed work for reading the RX status | 320 | * Schedule the delayed work for reading the RX status |
321 | * from the device. | 321 | * from the device. |
322 | */ | 322 | */ |
323 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); | 323 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); |
324 | } | 324 | } |
325 | 325 | ||
326 | static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) | 326 | static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) |
@@ -429,7 +429,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue) | |||
429 | * Schedule the completion handler manually, when this | 429 | * Schedule the completion handler manually, when this |
430 | * worker function runs, it should cleanup the queue. | 430 | * worker function runs, it should cleanup the queue. |
431 | */ | 431 | */ |
432 | ieee80211_queue_work(queue->rt2x00dev->hw, completion); | 432 | queue_work(queue->rt2x00dev->workqueue, completion); |
433 | 433 | ||
434 | /* | 434 | /* |
435 | * Wait for a little while to give the driver | 435 | * Wait for a little while to give the driver |
@@ -453,7 +453,7 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) | |||
453 | WARNING(queue->rt2x00dev, "TX queue %d status timed out," | 453 | WARNING(queue->rt2x00dev, "TX queue %d status timed out," |
454 | " invoke forced tx handler\n", queue->qid); | 454 | " invoke forced tx handler\n", queue->qid); |
455 | 455 | ||
456 | ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); | 456 | queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work); |
457 | } | 457 | } |
458 | 458 | ||
459 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) | 459 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8de44dd401e0..dd2164d4d57b 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -551,26 +551,14 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
551 | struct rt2x00intf_conf *conf, | 551 | struct rt2x00intf_conf *conf, |
552 | const unsigned int flags) | 552 | const unsigned int flags) |
553 | { | 553 | { |
554 | unsigned int beacon_base; | ||
555 | u32 reg; | 554 | u32 reg; |
556 | 555 | ||
557 | if (flags & CONFIG_UPDATE_TYPE) { | 556 | if (flags & CONFIG_UPDATE_TYPE) { |
558 | /* | 557 | /* |
559 | * Clear current synchronisation setup. | ||
560 | * For the Beacon base registers, we only need to clear | ||
561 | * the first byte since that byte contains the VALID and OWNER | ||
562 | * bits which (when set to 0) will invalidate the entire beacon. | ||
563 | */ | ||
564 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
565 | rt2x00pci_register_write(rt2x00dev, beacon_base, 0); | ||
566 | |||
567 | /* | ||
568 | * Enable synchronisation. | 558 | * Enable synchronisation. |
569 | */ | 559 | */ |
570 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 560 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); |
571 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
572 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); | 561 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); |
573 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
574 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 562 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); |
575 | } | 563 | } |
576 | 564 | ||
@@ -1154,6 +1142,11 @@ static void rt61pci_start_queue(struct data_queue *queue) | |||
1154 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | 1142 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); |
1155 | break; | 1143 | break; |
1156 | case QID_BEACON: | 1144 | case QID_BEACON: |
1145 | /* | ||
1146 | * Allow the tbtt tasklet to be scheduled. | ||
1147 | */ | ||
1148 | tasklet_enable(&rt2x00dev->tbtt_tasklet); | ||
1149 | |||
1157 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 1150 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); |
1158 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | 1151 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); |
1159 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | 1152 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); |
@@ -1233,6 +1226,11 @@ static void rt61pci_stop_queue(struct data_queue *queue) | |||
1233 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | 1226 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); |
1234 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 1227 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); |
1235 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 1228 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); |
1229 | |||
1230 | /* | ||
1231 | * Wait for possibly running tbtt tasklets. | ||
1232 | */ | ||
1233 | tasklet_disable(&rt2x00dev->tbtt_tasklet); | ||
1236 | break; | 1234 | break; |
1237 | default: | 1235 | default: |
1238 | break; | 1236 | break; |
@@ -1719,9 +1717,9 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1719 | static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 1717 | static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
1720 | enum dev_state state) | 1718 | enum dev_state state) |
1721 | { | 1719 | { |
1722 | int mask = (state == STATE_RADIO_IRQ_OFF) || | 1720 | int mask = (state == STATE_RADIO_IRQ_OFF); |
1723 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
1724 | u32 reg; | 1721 | u32 reg; |
1722 | unsigned long flags; | ||
1725 | 1723 | ||
1726 | /* | 1724 | /* |
1727 | * When interrupts are being enabled, the interrupt registers | 1725 | * When interrupts are being enabled, the interrupt registers |
@@ -1733,12 +1731,21 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1733 | 1731 | ||
1734 | rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); | 1732 | rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); |
1735 | rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); | 1733 | rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); |
1734 | |||
1735 | /* | ||
1736 | * Enable tasklets. | ||
1737 | */ | ||
1738 | tasklet_enable(&rt2x00dev->txstatus_tasklet); | ||
1739 | tasklet_enable(&rt2x00dev->rxdone_tasklet); | ||
1740 | tasklet_enable(&rt2x00dev->autowake_tasklet); | ||
1736 | } | 1741 | } |
1737 | 1742 | ||
1738 | /* | 1743 | /* |
1739 | * Only toggle the interrupts bits we are going to use. | 1744 | * Only toggle the interrupts bits we are going to use. |
1740 | * Non-checked interrupt bits are disabled by default. | 1745 | * Non-checked interrupt bits are disabled by default. |
1741 | */ | 1746 | */ |
1747 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1748 | |||
1742 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | 1749 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); |
1743 | rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); | 1750 | rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); |
1744 | rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); | 1751 | rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); |
@@ -1758,6 +1765,17 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1758 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); | 1765 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); |
1759 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_TWAKEUP, mask); | 1766 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_TWAKEUP, mask); |
1760 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); | 1767 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); |
1768 | |||
1769 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1770 | |||
1771 | if (state == STATE_RADIO_IRQ_OFF) { | ||
1772 | /* | ||
1773 | * Ensure that all tasklets are finished. | ||
1774 | */ | ||
1775 | tasklet_disable(&rt2x00dev->txstatus_tasklet); | ||
1776 | tasklet_disable(&rt2x00dev->rxdone_tasklet); | ||
1777 | tasklet_disable(&rt2x00dev->autowake_tasklet); | ||
1778 | } | ||
1761 | } | 1779 | } |
1762 | 1780 | ||
1763 | static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 1781 | static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
@@ -1833,9 +1851,7 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1833 | rt61pci_disable_radio(rt2x00dev); | 1851 | rt61pci_disable_radio(rt2x00dev); |
1834 | break; | 1852 | break; |
1835 | case STATE_RADIO_IRQ_ON: | 1853 | case STATE_RADIO_IRQ_ON: |
1836 | case STATE_RADIO_IRQ_ON_ISR: | ||
1837 | case STATE_RADIO_IRQ_OFF: | 1854 | case STATE_RADIO_IRQ_OFF: |
1838 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1839 | rt61pci_toggle_irq(rt2x00dev, state); | 1855 | rt61pci_toggle_irq(rt2x00dev, state); |
1840 | break; | 1856 | break; |
1841 | case STATE_DEEP_SLEEP: | 1857 | case STATE_DEEP_SLEEP: |
@@ -2002,8 +2018,6 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
2002 | */ | 2018 | */ |
2003 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); | 2019 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); |
2004 | 2020 | ||
2005 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
2006 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
2007 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | 2021 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); |
2008 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 2022 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); |
2009 | 2023 | ||
@@ -2014,6 +2028,32 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
2014 | entry->skb = NULL; | 2028 | entry->skb = NULL; |
2015 | } | 2029 | } |
2016 | 2030 | ||
2031 | static void rt61pci_clear_beacon(struct queue_entry *entry) | ||
2032 | { | ||
2033 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
2034 | u32 reg; | ||
2035 | |||
2036 | /* | ||
2037 | * Disable beaconing while we are reloading the beacon data, | ||
2038 | * otherwise we might be sending out invalid data. | ||
2039 | */ | ||
2040 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
2041 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
2042 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
2043 | |||
2044 | /* | ||
2045 | * Clear beacon. | ||
2046 | */ | ||
2047 | rt2x00pci_register_write(rt2x00dev, | ||
2048 | HW_BEACON_OFFSET(entry->entry_idx), 0); | ||
2049 | |||
2050 | /* | ||
2051 | * Enable beaconing again. | ||
2052 | */ | ||
2053 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | ||
2054 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
2055 | } | ||
2056 | |||
2017 | /* | 2057 | /* |
2018 | * RX control handlers | 2058 | * RX control handlers |
2019 | */ | 2059 | */ |
@@ -2078,9 +2118,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, | |||
2078 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | 2118 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; |
2079 | 2119 | ||
2080 | /* | 2120 | /* |
2081 | * FIXME: Legacy driver indicates that the frame does | 2121 | * The hardware has already checked the Michael Mic and has |
2082 | * contain the Michael Mic. Unfortunately, in rt2x00 | 2122 | * stripped it from the frame. Signal this to mac80211. |
2083 | * the MIC seems to be missing completely... | ||
2084 | */ | 2123 | */ |
2085 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | 2124 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; |
2086 | 2125 | ||
@@ -2211,61 +2250,80 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) | |||
2211 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | 2250 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); |
2212 | } | 2251 | } |
2213 | 2252 | ||
2214 | static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance) | 2253 | static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, |
2254 | struct rt2x00_field32 irq_field) | ||
2215 | { | 2255 | { |
2216 | struct rt2x00_dev *rt2x00dev = dev_instance; | 2256 | unsigned long flags; |
2217 | u32 reg = rt2x00dev->irqvalue[0]; | 2257 | u32 reg; |
2218 | u32 reg_mcu = rt2x00dev->irqvalue[1]; | ||
2219 | 2258 | ||
2220 | /* | 2259 | /* |
2221 | * Handle interrupts, walk through all bits | 2260 | * Enable a single interrupt. The interrupt mask register |
2222 | * and run the tasks, the bits are checked in order of | 2261 | * access needs locking. |
2223 | * priority. | ||
2224 | */ | 2262 | */ |
2263 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
2225 | 2264 | ||
2226 | /* | 2265 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); |
2227 | * 1 - Rx ring done interrupt. | 2266 | rt2x00_set_field32(®, irq_field, 0); |
2228 | */ | 2267 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); |
2229 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE)) | ||
2230 | rt2x00pci_rxdone(rt2x00dev); | ||
2231 | 2268 | ||
2232 | /* | 2269 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
2233 | * 2 - Tx ring done interrupt. | 2270 | } |
2234 | */ | ||
2235 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE)) | ||
2236 | rt61pci_txdone(rt2x00dev); | ||
2237 | 2271 | ||
2238 | /* | 2272 | static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev, |
2239 | * 3 - Handle MCU command done. | 2273 | struct rt2x00_field32 irq_field) |
2240 | */ | 2274 | { |
2241 | if (reg_mcu) | 2275 | unsigned long flags; |
2242 | rt2x00pci_register_write(rt2x00dev, | 2276 | u32 reg; |
2243 | M2H_CMD_DONE_CSR, 0xffffffff); | ||
2244 | 2277 | ||
2245 | /* | 2278 | /* |
2246 | * 4 - MCU Autowakeup interrupt. | 2279 | * Enable a single MCU interrupt. The interrupt mask register |
2280 | * access needs locking. | ||
2247 | */ | 2281 | */ |
2248 | if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) | 2282 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
2249 | rt61pci_wakeup(rt2x00dev); | ||
2250 | 2283 | ||
2251 | /* | 2284 | rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); |
2252 | * 5 - Beacon done interrupt. | 2285 | rt2x00_set_field32(®, irq_field, 0); |
2253 | */ | 2286 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); |
2254 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) | ||
2255 | rt2x00lib_beacondone(rt2x00dev); | ||
2256 | 2287 | ||
2257 | /* Enable interrupts again. */ | 2288 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
2258 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 2289 | } |
2259 | STATE_RADIO_IRQ_ON_ISR); | 2290 | |
2260 | return IRQ_HANDLED; | 2291 | static void rt61pci_txstatus_tasklet(unsigned long data) |
2292 | { | ||
2293 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
2294 | rt61pci_txdone(rt2x00dev); | ||
2295 | rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE); | ||
2296 | } | ||
2297 | |||
2298 | static void rt61pci_tbtt_tasklet(unsigned long data) | ||
2299 | { | ||
2300 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
2301 | rt2x00lib_beacondone(rt2x00dev); | ||
2302 | rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE); | ||
2303 | } | ||
2304 | |||
2305 | static void rt61pci_rxdone_tasklet(unsigned long data) | ||
2306 | { | ||
2307 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
2308 | rt2x00pci_rxdone(rt2x00dev); | ||
2309 | rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); | ||
2261 | } | 2310 | } |
2262 | 2311 | ||
2312 | static void rt61pci_autowake_tasklet(unsigned long data) | ||
2313 | { | ||
2314 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
2315 | rt61pci_wakeup(rt2x00dev); | ||
2316 | rt2x00pci_register_write(rt2x00dev, | ||
2317 | M2H_CMD_DONE_CSR, 0xffffffff); | ||
2318 | rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP); | ||
2319 | } | ||
2263 | 2320 | ||
2264 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | 2321 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) |
2265 | { | 2322 | { |
2266 | struct rt2x00_dev *rt2x00dev = dev_instance; | 2323 | struct rt2x00_dev *rt2x00dev = dev_instance; |
2267 | u32 reg_mcu; | 2324 | u32 reg_mcu, mask_mcu; |
2268 | u32 reg; | 2325 | u32 reg, mask; |
2326 | unsigned long flags; | ||
2269 | 2327 | ||
2270 | /* | 2328 | /* |
2271 | * Get the interrupt sources & saved to local variable. | 2329 | * Get the interrupt sources & saved to local variable. |
@@ -2283,14 +2341,46 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2283 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 2341 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
2284 | return IRQ_HANDLED; | 2342 | return IRQ_HANDLED; |
2285 | 2343 | ||
2286 | /* Store irqvalues for use in the interrupt thread. */ | 2344 | /* |
2287 | rt2x00dev->irqvalue[0] = reg; | 2345 | * Schedule tasklets for interrupt handling. |
2288 | rt2x00dev->irqvalue[1] = reg_mcu; | 2346 | */ |
2347 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE)) | ||
2348 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
2349 | |||
2350 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE)) | ||
2351 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
2289 | 2352 | ||
2290 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | 2353 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) |
2291 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 2354 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); |
2292 | STATE_RADIO_IRQ_OFF_ISR); | 2355 | |
2293 | return IRQ_WAKE_THREAD; | 2356 | if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) |
2357 | tasklet_schedule(&rt2x00dev->autowake_tasklet); | ||
2358 | |||
2359 | /* | ||
2360 | * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits | ||
2361 | * for interrupts and interrupt masks we can just use the value of | ||
2362 | * INT_SOURCE_CSR to create the interrupt mask. | ||
2363 | */ | ||
2364 | mask = reg; | ||
2365 | mask_mcu = reg_mcu; | ||
2366 | |||
2367 | /* | ||
2368 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
2369 | * the tasklet will reenable the appropriate interrupts. | ||
2370 | */ | ||
2371 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
2372 | |||
2373 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
2374 | reg |= mask; | ||
2375 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
2376 | |||
2377 | rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); | ||
2378 | reg |= mask_mcu; | ||
2379 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); | ||
2380 | |||
2381 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
2382 | |||
2383 | return IRQ_HANDLED; | ||
2294 | } | 2384 | } |
2295 | 2385 | ||
2296 | /* | 2386 | /* |
@@ -2884,7 +2974,10 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2884 | 2974 | ||
2885 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | 2975 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { |
2886 | .irq_handler = rt61pci_interrupt, | 2976 | .irq_handler = rt61pci_interrupt, |
2887 | .irq_handler_thread = rt61pci_interrupt_thread, | 2977 | .txstatus_tasklet = rt61pci_txstatus_tasklet, |
2978 | .tbtt_tasklet = rt61pci_tbtt_tasklet, | ||
2979 | .rxdone_tasklet = rt61pci_rxdone_tasklet, | ||
2980 | .autowake_tasklet = rt61pci_autowake_tasklet, | ||
2888 | .probe_hw = rt61pci_probe_hw, | 2981 | .probe_hw = rt61pci_probe_hw, |
2889 | .get_firmware_name = rt61pci_get_firmware_name, | 2982 | .get_firmware_name = rt61pci_get_firmware_name, |
2890 | .check_firmware = rt61pci_check_firmware, | 2983 | .check_firmware = rt61pci_check_firmware, |
@@ -2903,6 +2996,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | |||
2903 | .stop_queue = rt61pci_stop_queue, | 2996 | .stop_queue = rt61pci_stop_queue, |
2904 | .write_tx_desc = rt61pci_write_tx_desc, | 2997 | .write_tx_desc = rt61pci_write_tx_desc, |
2905 | .write_beacon = rt61pci_write_beacon, | 2998 | .write_beacon = rt61pci_write_beacon, |
2999 | .clear_beacon = rt61pci_clear_beacon, | ||
2906 | .fill_rxdone = rt61pci_fill_rxdone, | 3000 | .fill_rxdone = rt61pci_fill_rxdone, |
2907 | .config_shared_key = rt61pci_config_shared_key, | 3001 | .config_shared_key = rt61pci_config_shared_key, |
2908 | .config_pairwise_key = rt61pci_config_pairwise_key, | 3002 | .config_pairwise_key = rt61pci_config_pairwise_key, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 029be3c6c030..5ff72deea8d4 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -502,26 +502,14 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
502 | struct rt2x00intf_conf *conf, | 502 | struct rt2x00intf_conf *conf, |
503 | const unsigned int flags) | 503 | const unsigned int flags) |
504 | { | 504 | { |
505 | unsigned int beacon_base; | ||
506 | u32 reg; | 505 | u32 reg; |
507 | 506 | ||
508 | if (flags & CONFIG_UPDATE_TYPE) { | 507 | if (flags & CONFIG_UPDATE_TYPE) { |
509 | /* | 508 | /* |
510 | * Clear current synchronisation setup. | ||
511 | * For the Beacon base registers we only need to clear | ||
512 | * the first byte since that byte contains the VALID and OWNER | ||
513 | * bits which (when set to 0) will invalidate the entire beacon. | ||
514 | */ | ||
515 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
516 | rt2x00usb_register_write(rt2x00dev, beacon_base, 0); | ||
517 | |||
518 | /* | ||
519 | * Enable synchronisation. | 509 | * Enable synchronisation. |
520 | */ | 510 | */ |
521 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); | 511 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
522 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
523 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); | 512 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); |
524 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
525 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 513 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
526 | } | 514 | } |
527 | 515 | ||
@@ -1440,9 +1428,7 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1440 | rt73usb_disable_radio(rt2x00dev); | 1428 | rt73usb_disable_radio(rt2x00dev); |
1441 | break; | 1429 | break; |
1442 | case STATE_RADIO_IRQ_ON: | 1430 | case STATE_RADIO_IRQ_ON: |
1443 | case STATE_RADIO_IRQ_ON_ISR: | ||
1444 | case STATE_RADIO_IRQ_OFF: | 1431 | case STATE_RADIO_IRQ_OFF: |
1445 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1446 | /* No support, but no error either */ | 1432 | /* No support, but no error either */ |
1447 | break; | 1433 | break; |
1448 | case STATE_DEEP_SLEEP: | 1434 | case STATE_DEEP_SLEEP: |
@@ -1590,8 +1576,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry, | |||
1590 | */ | 1576 | */ |
1591 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); | 1577 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); |
1592 | 1578 | ||
1593 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
1594 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
1595 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | 1579 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); |
1596 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 1580 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
1597 | 1581 | ||
@@ -1602,6 +1586,33 @@ static void rt73usb_write_beacon(struct queue_entry *entry, | |||
1602 | entry->skb = NULL; | 1586 | entry->skb = NULL; |
1603 | } | 1587 | } |
1604 | 1588 | ||
1589 | static void rt73usb_clear_beacon(struct queue_entry *entry) | ||
1590 | { | ||
1591 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1592 | unsigned int beacon_base; | ||
1593 | u32 reg; | ||
1594 | |||
1595 | /* | ||
1596 | * Disable beaconing while we are reloading the beacon data, | ||
1597 | * otherwise we might be sending out invalid data. | ||
1598 | */ | ||
1599 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
1600 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
1601 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
1602 | |||
1603 | /* | ||
1604 | * Clear beacon. | ||
1605 | */ | ||
1606 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | ||
1607 | rt2x00usb_register_write(rt2x00dev, beacon_base, 0); | ||
1608 | |||
1609 | /* | ||
1610 | * Enable beaconing again. | ||
1611 | */ | ||
1612 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | ||
1613 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
1614 | } | ||
1615 | |||
1605 | static int rt73usb_get_tx_data_len(struct queue_entry *entry) | 1616 | static int rt73usb_get_tx_data_len(struct queue_entry *entry) |
1606 | { | 1617 | { |
1607 | int length; | 1618 | int length; |
@@ -1698,9 +1709,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1698 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | 1709 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; |
1699 | 1710 | ||
1700 | /* | 1711 | /* |
1701 | * FIXME: Legacy driver indicates that the frame does | 1712 | * The hardware has already checked the Michael Mic and has |
1702 | * contain the Michael Mic. Unfortunately, in rt2x00 | 1713 | * stripped it from the frame. Signal this to mac80211. |
1703 | * the MIC seems to be missing completely... | ||
1704 | */ | 1714 | */ |
1705 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | 1715 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; |
1706 | 1716 | ||
@@ -2313,6 +2323,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { | |||
2313 | .flush_queue = rt2x00usb_flush_queue, | 2323 | .flush_queue = rt2x00usb_flush_queue, |
2314 | .write_tx_desc = rt73usb_write_tx_desc, | 2324 | .write_tx_desc = rt73usb_write_tx_desc, |
2315 | .write_beacon = rt73usb_write_beacon, | 2325 | .write_beacon = rt73usb_write_beacon, |
2326 | .clear_beacon = rt73usb_clear_beacon, | ||
2316 | .get_tx_data_len = rt73usb_get_tx_data_len, | 2327 | .get_tx_data_len = rt73usb_get_tx_data_len, |
2317 | .fill_rxdone = rt73usb_fill_rxdone, | 2328 | .fill_rxdone = rt73usb_fill_rxdone, |
2318 | .config_shared_key = rt73usb_config_shared_key, | 2329 | .config_shared_key = rt73usb_config_shared_key, |