diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-02-14 12:49:18 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-02-20 16:33:14 -0500 |
commit | 168cf9af699e87d5a6f44b684583714ecabb8e71 (patch) | |
tree | 2f491d28a4a129caf7c2be306aec33c437a5cb30 | |
parent | 4a9bde9b8ab55a2bb51b57cad215a97bcf80bae2 (diff) |
firewire: remove incomplete Bus_Time CSR support
The current implementation of Bus_Time read access was buggy since it
did not ensure that Bus_Time.second_count_hi and second_count_lo came
from the same 128 seconds period.
Reported-by: HÃ¥kan Johansson <f96hajo@chalmers.se>
Instead of a fix, remove Bus_Time register support altogether. The spec
requires all cycle master capable nodes to implement this (all Linux
nodes are cycle master capable) while it also says that it "may" be
initialized by the bus manager or by the IRM standing in for a bus
manager. (Neither Linux' firewire-core nor ieee1394 nodemgr implement
this.)
Since we cannot rely on Bus_Time having been initialized by a bus
manager, it is better to return an error instead of a nonsensical value
on a read request to Bus_Time.
Alternatively, we could fix the Bus_Time read integrity bug _and_
implement (a) cycle master's write support of the register as well as
(b) bus manager's Bus_Time initialization service, i.e. preservation of
the Bus_Time when the cycle master node of a bus changes. However, that
would be quite some code for a feature that is unreliable to begin with
and very likely unused in practice.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r-- | drivers/firewire/core-cdev.c | 2 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 17 | ||||
-rw-r--r-- | drivers/firewire/core.h | 2 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 25 |
4 files changed, 15 insertions, 31 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index ecd0a4d81abf..5538d5130f7b 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
@@ -1018,7 +1018,7 @@ static int ioctl_get_cycle_timer(struct client *client, void *buffer) | |||
1018 | 1018 | ||
1019 | local_irq_disable(); | 1019 | local_irq_disable(); |
1020 | 1020 | ||
1021 | cycle_time = card->driver->get_bus_time(card); | 1021 | cycle_time = card->driver->get_cycle_time(card); |
1022 | do_gettimeofday(&tv); | 1022 | do_gettimeofday(&tv); |
1023 | 1023 | ||
1024 | local_irq_enable(); | 1024 | local_irq_enable(); |
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 495849eb13cc..673b03f8b4ec 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c | |||
@@ -921,23 +921,15 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, | |||
921 | void *payload, size_t length, void *callback_data) | 921 | void *payload, size_t length, void *callback_data) |
922 | { | 922 | { |
923 | int reg = offset & ~CSR_REGISTER_BASE; | 923 | int reg = offset & ~CSR_REGISTER_BASE; |
924 | unsigned long long bus_time; | ||
925 | __be32 *data = payload; | 924 | __be32 *data = payload; |
926 | int rcode = RCODE_COMPLETE; | 925 | int rcode = RCODE_COMPLETE; |
927 | 926 | ||
928 | switch (reg) { | 927 | switch (reg) { |
929 | case CSR_CYCLE_TIME: | 928 | case CSR_CYCLE_TIME: |
930 | case CSR_BUS_TIME: | 929 | if (TCODE_IS_READ_REQUEST(tcode) && length == 4) |
931 | if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) { | 930 | *data = cpu_to_be32(card->driver->get_cycle_time(card)); |
932 | rcode = RCODE_TYPE_ERROR; | ||
933 | break; | ||
934 | } | ||
935 | |||
936 | bus_time = card->driver->get_bus_time(card); | ||
937 | if (reg == CSR_CYCLE_TIME) | ||
938 | *data = cpu_to_be32(bus_time); | ||
939 | else | 931 | else |
940 | *data = cpu_to_be32(bus_time >> 25); | 932 | rcode = RCODE_TYPE_ERROR; |
941 | break; | 933 | break; |
942 | 934 | ||
943 | case CSR_BROADCAST_CHANNEL: | 935 | case CSR_BROADCAST_CHANNEL: |
@@ -968,6 +960,9 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, | |||
968 | case CSR_BUSY_TIMEOUT: | 960 | case CSR_BUSY_TIMEOUT: |
969 | /* FIXME: Implement this. */ | 961 | /* FIXME: Implement this. */ |
970 | 962 | ||
963 | case CSR_BUS_TIME: | ||
964 | /* Useless without initialization by the bus manager. */ | ||
965 | |||
971 | default: | 966 | default: |
972 | rcode = RCODE_ADDRESS_ERROR; | 967 | rcode = RCODE_ADDRESS_ERROR; |
973 | break; | 968 | break; |
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index ed3b1a765c00..fb0321300cce 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h | |||
@@ -70,7 +70,7 @@ struct fw_card_driver { | |||
70 | int (*enable_phys_dma)(struct fw_card *card, | 70 | int (*enable_phys_dma)(struct fw_card *card, |
71 | int node_id, int generation); | 71 | int node_id, int generation); |
72 | 72 | ||
73 | u64 (*get_bus_time)(struct fw_card *card); | 73 | u32 (*get_cycle_time)(struct fw_card *card); |
74 | 74 | ||
75 | struct fw_iso_context * | 75 | struct fw_iso_context * |
76 | (*allocate_iso_context)(struct fw_card *card, | 76 | (*allocate_iso_context)(struct fw_card *card, |
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index c3eb471d22f7..f8a71397cf6e 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/spinlock.h> | 38 | #include <linux/spinlock.h> |
39 | #include <linux/string.h> | 39 | #include <linux/string.h> |
40 | 40 | ||
41 | #include <asm/atomic.h> | ||
42 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
43 | #include <asm/page.h> | 42 | #include <asm/page.h> |
44 | #include <asm/system.h> | 43 | #include <asm/system.h> |
@@ -187,7 +186,6 @@ struct fw_ohci { | |||
187 | int node_id; | 186 | int node_id; |
188 | int generation; | 187 | int generation; |
189 | int request_generation; /* for timestamping incoming requests */ | 188 | int request_generation; /* for timestamping incoming requests */ |
190 | atomic_t bus_seconds; | ||
191 | 189 | ||
192 | bool use_dualbuffer; | 190 | bool use_dualbuffer; |
193 | bool old_uninorth; | 191 | bool old_uninorth; |
@@ -276,7 +274,7 @@ static void log_irqs(u32 evt) | |||
276 | !(evt & OHCI1394_busReset)) | 274 | !(evt & OHCI1394_busReset)) |
277 | return; | 275 | return; |
278 | 276 | ||
279 | fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, | 277 | fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, |
280 | evt & OHCI1394_selfIDComplete ? " selfID" : "", | 278 | evt & OHCI1394_selfIDComplete ? " selfID" : "", |
281 | evt & OHCI1394_RQPkt ? " AR_req" : "", | 279 | evt & OHCI1394_RQPkt ? " AR_req" : "", |
282 | evt & OHCI1394_RSPkt ? " AR_resp" : "", | 280 | evt & OHCI1394_RSPkt ? " AR_resp" : "", |
@@ -286,7 +284,6 @@ static void log_irqs(u32 evt) | |||
286 | evt & OHCI1394_isochTx ? " IT" : "", | 284 | evt & OHCI1394_isochTx ? " IT" : "", |
287 | evt & OHCI1394_postedWriteErr ? " postedWriteErr" : "", | 285 | evt & OHCI1394_postedWriteErr ? " postedWriteErr" : "", |
288 | evt & OHCI1394_cycleTooLong ? " cycleTooLong" : "", | 286 | evt & OHCI1394_cycleTooLong ? " cycleTooLong" : "", |
289 | evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "", | ||
290 | evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "", | 287 | evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "", |
291 | evt & OHCI1394_regAccessFail ? " regAccessFail" : "", | 288 | evt & OHCI1394_regAccessFail ? " regAccessFail" : "", |
292 | evt & OHCI1394_busReset ? " busReset" : "", | 289 | evt & OHCI1394_busReset ? " busReset" : "", |
@@ -294,8 +291,7 @@ static void log_irqs(u32 evt) | |||
294 | OHCI1394_RSPkt | OHCI1394_reqTxComplete | | 291 | OHCI1394_RSPkt | OHCI1394_reqTxComplete | |
295 | OHCI1394_respTxComplete | OHCI1394_isochRx | | 292 | OHCI1394_respTxComplete | OHCI1394_isochRx | |
296 | OHCI1394_isochTx | OHCI1394_postedWriteErr | | 293 | OHCI1394_isochTx | OHCI1394_postedWriteErr | |
297 | OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds | | 294 | OHCI1394_cycleTooLong | OHCI1394_cycleInconsistent | |
298 | OHCI1394_cycleInconsistent | | ||
299 | OHCI1394_regAccessFail | OHCI1394_busReset) | 295 | OHCI1394_regAccessFail | OHCI1394_busReset) |
300 | ? " ?" : ""); | 296 | ? " ?" : ""); |
301 | } | 297 | } |
@@ -1385,7 +1381,7 @@ static void bus_reset_tasklet(unsigned long data) | |||
1385 | static irqreturn_t irq_handler(int irq, void *data) | 1381 | static irqreturn_t irq_handler(int irq, void *data) |
1386 | { | 1382 | { |
1387 | struct fw_ohci *ohci = data; | 1383 | struct fw_ohci *ohci = data; |
1388 | u32 event, iso_event, cycle_time; | 1384 | u32 event, iso_event; |
1389 | int i; | 1385 | int i; |
1390 | 1386 | ||
1391 | event = reg_read(ohci, OHCI1394_IntEventClear); | 1387 | event = reg_read(ohci, OHCI1394_IntEventClear); |
@@ -1455,12 +1451,6 @@ static irqreturn_t irq_handler(int irq, void *data) | |||
1455 | fw_notify("isochronous cycle inconsistent\n"); | 1451 | fw_notify("isochronous cycle inconsistent\n"); |
1456 | } | 1452 | } |
1457 | 1453 | ||
1458 | if (event & OHCI1394_cycle64Seconds) { | ||
1459 | cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | ||
1460 | if ((cycle_time & 0x80000000) == 0) | ||
1461 | atomic_inc(&ohci->bus_seconds); | ||
1462 | } | ||
1463 | |||
1464 | return IRQ_HANDLED; | 1454 | return IRQ_HANDLED; |
1465 | } | 1455 | } |
1466 | 1456 | ||
@@ -1554,8 +1544,7 @@ static int ohci_enable(struct fw_card *card, | |||
1554 | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | | 1544 | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | |
1555 | OHCI1394_isochRx | OHCI1394_isochTx | | 1545 | OHCI1394_isochRx | OHCI1394_isochTx | |
1556 | OHCI1394_postedWriteErr | OHCI1394_cycleTooLong | | 1546 | OHCI1394_postedWriteErr | OHCI1394_cycleTooLong | |
1557 | OHCI1394_cycleInconsistent | | 1547 | OHCI1394_cycleInconsistent | OHCI1394_regAccessFail | |
1558 | OHCI1394_cycle64Seconds | OHCI1394_regAccessFail | | ||
1559 | OHCI1394_masterIntEnable); | 1548 | OHCI1394_masterIntEnable); |
1560 | if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) | 1549 | if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) |
1561 | reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); | 1550 | reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); |
@@ -1821,7 +1810,7 @@ static u32 cycle_timer_ticks(u32 cycle_timer) | |||
1821 | * error. (A PCI read should take at least 20 ticks of the 24.576 MHz timer to | 1810 | * 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.) | 1811 | * execute, so we have enough precision to compute the ratio of the differences.) |
1823 | */ | 1812 | */ |
1824 | static u64 ohci_get_bus_time(struct fw_card *card) | 1813 | static u32 ohci_get_cycle_time(struct fw_card *card) |
1825 | { | 1814 | { |
1826 | struct fw_ohci *ohci = fw_ohci(card); | 1815 | struct fw_ohci *ohci = fw_ohci(card); |
1827 | u32 c0, c1, c2; | 1816 | u32 c0, c1, c2; |
@@ -1849,7 +1838,7 @@ static u64 ohci_get_bus_time(struct fw_card *card) | |||
1849 | && i++ < 20); | 1838 | && i++ < 20); |
1850 | } | 1839 | } |
1851 | 1840 | ||
1852 | return ((u64)atomic_read(&ohci->bus_seconds) << 32) | c2; | 1841 | return c2; |
1853 | } | 1842 | } |
1854 | 1843 | ||
1855 | static void copy_iso_headers(struct iso_context *ctx, void *p) | 1844 | static void copy_iso_headers(struct iso_context *ctx, void *p) |
@@ -2426,7 +2415,7 @@ static const struct fw_card_driver ohci_driver = { | |||
2426 | .send_response = ohci_send_response, | 2415 | .send_response = ohci_send_response, |
2427 | .cancel_packet = ohci_cancel_packet, | 2416 | .cancel_packet = ohci_cancel_packet, |
2428 | .enable_phys_dma = ohci_enable_phys_dma, | 2417 | .enable_phys_dma = ohci_enable_phys_dma, |
2429 | .get_bus_time = ohci_get_bus_time, | 2418 | .get_cycle_time = ohci_get_cycle_time, |
2430 | 2419 | ||
2431 | .allocate_iso_context = ohci_allocate_iso_context, | 2420 | .allocate_iso_context = ohci_allocate_iso_context, |
2432 | .free_iso_context = ohci_free_iso_context, | 2421 | .free_iso_context = ohci_free_iso_context, |