aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-12-19 16:51:57 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 15:58:33 -0500
commit3ebbbb56a162b8f9b9a77bc7810b9d4e0868e039 (patch)
tree0d4a7c60d8cdee68878a97bbc4b9d358396f7ba3 /drivers/net/wireless/b43
parente808e586b77a10949e209f8a00cb8bf27e51df12 (diff)
b43: Use 64bit atomic register access for TSF
On modern b43 devices with core rev >=3, the hardware guarantees us an atomic 64bit read/write of the TSF, if we access the lower 32bits first. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r--drivers/net/wireless/b43/main.c89
1 files changed, 20 insertions, 69 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index dad0781b4b6..ba989ae132a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -526,52 +526,20 @@ void b43_hf_write(struct b43_wldev *dev, u64 value)
526 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi); 526 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
527} 527}
528 528
529void b43_tsf_read(struct b43_wldev *dev, u64 * tsf) 529void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
530{ 530{
531 /* We need to be careful. As we read the TSF from multiple 531 u32 low, high;
532 * registers, we should take care of register overflows.
533 * In theory, the whole tsf read process should be atomic.
534 * We try to be atomic here, by restaring the read process,
535 * if any of the high registers changed (overflew).
536 */
537 if (dev->dev->id.revision >= 3) {
538 u32 low, high, high2;
539
540 do {
541 high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
542 low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW);
543 high2 = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
544 } while (unlikely(high != high2));
545
546 *tsf = high;
547 *tsf <<= 32;
548 *tsf |= low;
549 } else {
550 u64 tmp;
551 u16 v0, v1, v2, v3;
552 u16 test1, test2, test3;
553 532
554 do { 533 B43_WARN_ON(dev->dev->id.revision < 3);
555 v3 = b43_read16(dev, B43_MMIO_TSF_3);
556 v2 = b43_read16(dev, B43_MMIO_TSF_2);
557 v1 = b43_read16(dev, B43_MMIO_TSF_1);
558 v0 = b43_read16(dev, B43_MMIO_TSF_0);
559 534
560 test3 = b43_read16(dev, B43_MMIO_TSF_3); 535 /* The hardware guarantees us an atomic read, if we
561 test2 = b43_read16(dev, B43_MMIO_TSF_2); 536 * read the low register first. */
562 test1 = b43_read16(dev, B43_MMIO_TSF_1); 537 low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW);
563 } while (v3 != test3 || v2 != test2 || v1 != test1); 538 high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
564 539
565 *tsf = v3; 540 *tsf = high;
566 *tsf <<= 48; 541 *tsf <<= 32;
567 tmp = v2; 542 *tsf |= low;
568 tmp <<= 32;
569 *tsf |= tmp;
570 tmp = v1;
571 tmp <<= 16;
572 *tsf |= tmp;
573 *tsf |= v0;
574 }
575} 543}
576 544
577static void b43_time_lock(struct b43_wldev *dev) 545static void b43_time_lock(struct b43_wldev *dev)
@@ -598,35 +566,18 @@ static void b43_time_unlock(struct b43_wldev *dev)
598 566
599static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf) 567static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
600{ 568{
601 /* Be careful with the in-progress timer. 569 u32 low, high;
602 * First zero out the low register, so we have a full
603 * register-overflow duration to complete the operation.
604 */
605 if (dev->dev->id.revision >= 3) {
606 u32 lo = (tsf & 0x00000000FFFFFFFFULL);
607 u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
608 570
609 b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, 0); 571 B43_WARN_ON(dev->dev->id.revision < 3);
610 mmiowb();
611 b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, hi);
612 mmiowb();
613 b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, lo);
614 } else {
615 u16 v0 = (tsf & 0x000000000000FFFFULL);
616 u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
617 u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
618 u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
619 572
620 b43_write16(dev, B43_MMIO_TSF_0, 0); 573 low = tsf;
621 mmiowb(); 574 high = (tsf >> 32);
622 b43_write16(dev, B43_MMIO_TSF_3, v3); 575 /* The hardware guarantees us an atomic write, if we
623 mmiowb(); 576 * write the low register first. */
624 b43_write16(dev, B43_MMIO_TSF_2, v2); 577 b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, low);
625 mmiowb(); 578 mmiowb();
626 b43_write16(dev, B43_MMIO_TSF_1, v1); 579 b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, high);
627 mmiowb(); 580 mmiowb();
628 b43_write16(dev, B43_MMIO_TSF_0, v0);
629 }
630} 581}
631 582
632void b43_tsf_write(struct b43_wldev *dev, u64 tsf) 583void b43_tsf_write(struct b43_wldev *dev, u64 tsf)