aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2010-02-14 12:49:18 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-02-20 16:33:14 -0500
commit168cf9af699e87d5a6f44b684583714ecabb8e71 (patch)
tree2f491d28a4a129caf7c2be306aec33c437a5cb30
parent4a9bde9b8ab55a2bb51b57cad215a97bcf80bae2 (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.c2
-rw-r--r--drivers/firewire/core-transaction.c17
-rw-r--r--drivers/firewire/core.h2
-rw-r--r--drivers/firewire/ohci.c25
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)
1385static irqreturn_t irq_handler(int irq, void *data) 1381static 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 */
1824static u64 ohci_get_bus_time(struct fw_card *card) 1813static 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
1855static void copy_iso_headers(struct iso_context *ctx, void *p) 1844static 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,