diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-02-20 16:24:43 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-02-20 16:33:13 -0500 |
commit | 4a9bde9b8ab55a2bb51b57cad215a97bcf80bae2 (patch) | |
tree | e36282d7ed7e39f499e93f413cad57897477c53f /drivers/firewire | |
parent | 1c1517efe173599ca2f1526ce7a04521cd424a9f (diff) |
firewire: get_cycle_timer optimization and cleanup
ohci: Break out of the retry loop if too many attempts were necessary.
This may theoretically happen if the chip is fatally defective or if the
get_cycle_timer ioctl was performed after a CardBus controller was
ejected.
Also micro-optimize the loop by re-using the last two register reads in
the next iteration, remove a questionable inline keyword, and shuffle a
comment around.
core: ioctl_get_cycle_timer() is always called with interrupts on,
therefore local_irq_save() can be replaced by local_irq_disable().
Disabled local IRQs imply disabled preemption, hence preempt_disable()
can be removed.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-cdev.c | 16 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 57 |
2 files changed, 36 insertions, 37 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index e6d63849e78e..ecd0a4d81abf 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/firewire.h> | 25 | #include <linux/firewire.h> |
26 | #include <linux/firewire-cdev.h> | 26 | #include <linux/firewire-cdev.h> |
27 | #include <linux/idr.h> | 27 | #include <linux/idr.h> |
28 | #include <linux/irqflags.h> | ||
28 | #include <linux/jiffies.h> | 29 | #include <linux/jiffies.h> |
29 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
30 | #include <linux/kref.h> | 31 | #include <linux/kref.h> |
@@ -32,7 +33,6 @@ | |||
32 | #include <linux/module.h> | 33 | #include <linux/module.h> |
33 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
34 | #include <linux/poll.h> | 35 | #include <linux/poll.h> |
35 | #include <linux/preempt.h> | ||
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
38 | #include <linux/time.h> | 38 | #include <linux/time.h> |
@@ -1013,21 +1013,19 @@ static int ioctl_get_cycle_timer(struct client *client, void *buffer) | |||
1013 | { | 1013 | { |
1014 | struct fw_cdev_get_cycle_timer *request = buffer; | 1014 | struct fw_cdev_get_cycle_timer *request = buffer; |
1015 | struct fw_card *card = client->device->card; | 1015 | struct fw_card *card = client->device->card; |
1016 | unsigned long long bus_time; | ||
1017 | struct timeval tv; | 1016 | struct timeval tv; |
1018 | unsigned long flags; | 1017 | u32 cycle_time; |
1019 | 1018 | ||
1020 | preempt_disable(); | 1019 | local_irq_disable(); |
1021 | local_irq_save(flags); | ||
1022 | 1020 | ||
1023 | bus_time = card->driver->get_bus_time(card); | 1021 | cycle_time = card->driver->get_bus_time(card); |
1024 | do_gettimeofday(&tv); | 1022 | do_gettimeofday(&tv); |
1025 | 1023 | ||
1026 | local_irq_restore(flags); | 1024 | local_irq_enable(); |
1027 | preempt_enable(); | ||
1028 | 1025 | ||
1029 | request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; | 1026 | request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; |
1030 | request->cycle_timer = bus_time & 0xffffffff; | 1027 | request->cycle_timer = cycle_time; |
1028 | |||
1031 | return 0; | 1029 | return 0; |
1032 | } | 1030 | } |
1033 | 1031 | ||
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index bf5e11284421..c3eb471d22f7 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -1795,60 +1795,61 @@ static int ohci_enable_phys_dma(struct fw_card *card, | |||
1795 | #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ | 1795 | #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ |
1796 | } | 1796 | } |
1797 | 1797 | ||
1798 | static inline u32 cycle_timer_ticks(u32 cycle_timer) | 1798 | static u32 cycle_timer_ticks(u32 cycle_timer) |
1799 | { | 1799 | { |
1800 | u32 ticks; | 1800 | u32 ticks; |
1801 | 1801 | ||
1802 | ticks = cycle_timer & 0xfff; | 1802 | ticks = cycle_timer & 0xfff; |
1803 | ticks += 3072 * ((cycle_timer >> 12) & 0x1fff); | 1803 | ticks += 3072 * ((cycle_timer >> 12) & 0x1fff); |
1804 | ticks += (3072 * 8000) * (cycle_timer >> 25); | 1804 | ticks += (3072 * 8000) * (cycle_timer >> 25); |
1805 | |||
1805 | return ticks; | 1806 | return ticks; |
1806 | } | 1807 | } |
1807 | 1808 | ||
1809 | /* | ||
1810 | * Some controllers exhibit one or more of the following bugs when updating the | ||
1811 | * iso cycle timer register: | ||
1812 | * - When the lowest six bits are wrapping around to zero, a read that happens | ||
1813 | * at the same time will return garbage in the lowest ten bits. | ||
1814 | * - When the cycleOffset field wraps around to zero, the cycleCount field is | ||
1815 | * not incremented for about 60 ns. | ||
1816 | * - Occasionally, the entire register reads zero. | ||
1817 | * | ||
1818 | * To catch these, we read the register three times and ensure that the | ||
1819 | * difference between each two consecutive reads is approximately the same, i.e. | ||
1820 | * less than twice the other. Furthermore, any negative difference indicates an | ||
1821 | * error. (A PCI read should take at least 20 ticks of the 24.576 MHz timer to | ||
1822 | * execute, so we have enough precision to compute the ratio of the differences.) | ||
1823 | */ | ||
1808 | static u64 ohci_get_bus_time(struct fw_card *card) | 1824 | static u64 ohci_get_bus_time(struct fw_card *card) |
1809 | { | 1825 | { |
1810 | struct fw_ohci *ohci = fw_ohci(card); | 1826 | struct fw_ohci *ohci = fw_ohci(card); |
1811 | u32 c0, c1, c2; | 1827 | u32 c0, c1, c2; |
1812 | u32 t0, t1, t2; | 1828 | u32 t0, t1, t2; |
1813 | s32 diff01, diff12; | 1829 | s32 diff01, diff12; |
1814 | u64 bus_time; | 1830 | int i; |
1815 | 1831 | ||
1816 | if (!ohci->iso_cycle_timer_quirk) { | 1832 | c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); |
1833 | |||
1834 | if (ohci->iso_cycle_timer_quirk) { | ||
1835 | i = 0; | ||
1836 | c1 = c2; | ||
1817 | c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | 1837 | c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); |
1818 | } else { | ||
1819 | /* | ||
1820 | * Some controllers exhibit one or more of the following bugs | ||
1821 | * when updating the iso cycle timer register: | ||
1822 | * - When the lowest six bits are wrapping around to zero, | ||
1823 | * a read that happens at the same time will return garbage | ||
1824 | * in the lowest ten bits. | ||
1825 | * - When the cycleOffset field wraps around to zero, the | ||
1826 | * cycleCount field is not incremented for about 60 ns. | ||
1827 | * - Occasionally, the entire register reads zero. | ||
1828 | * | ||
1829 | * To catch these, we read the register three times and ensure | ||
1830 | * that the difference between each two consecutive reads is | ||
1831 | * approximately the same, i.e., less than twice the other. | ||
1832 | * Furthermore, any negative difference indicates an error. | ||
1833 | * (A PCI read should take at least 20 ticks of the 24.576 MHz | ||
1834 | * timer to execute, so we have enough precision to compute the | ||
1835 | * ratio of the differences.) | ||
1836 | */ | ||
1837 | do { | 1838 | do { |
1838 | c0 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | 1839 | c0 = c1; |
1839 | c1 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | 1840 | c1 = c2; |
1840 | c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | 1841 | c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); |
1841 | t0 = cycle_timer_ticks(c0); | 1842 | t0 = cycle_timer_ticks(c0); |
1842 | t1 = cycle_timer_ticks(c1); | 1843 | t1 = cycle_timer_ticks(c1); |
1843 | t2 = cycle_timer_ticks(c2); | 1844 | t2 = cycle_timer_ticks(c2); |
1844 | diff01 = t1 - t0; | 1845 | diff01 = t1 - t0; |
1845 | diff12 = t2 - t1; | 1846 | diff12 = t2 - t1; |
1846 | } while (diff01 <= 0 || diff12 <= 0 || | 1847 | } while ((diff01 <= 0 || diff12 <= 0 || |
1847 | diff01 / diff12 >= 2 || diff12 / diff01 >= 2); | 1848 | diff01 / diff12 >= 2 || diff12 / diff01 >= 2) |
1849 | && i++ < 20); | ||
1848 | } | 1850 | } |
1849 | bus_time = ((u64)atomic_read(&ohci->bus_seconds) << 32) | c2; | ||
1850 | 1851 | ||
1851 | return bus_time; | 1852 | return ((u64)atomic_read(&ohci->bus_seconds) << 32) | c2; |
1852 | } | 1853 | } |
1853 | 1854 | ||
1854 | static void copy_iso_headers(struct iso_context *ctx, void *p) | 1855 | static void copy_iso_headers(struct iso_context *ctx, void *p) |