diff options
-rw-r--r-- | drivers/firewire/core-cdev.c | 16 | ||||
-rw-r--r-- | drivers/firewire/core-device.c | 127 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 17 | ||||
-rw-r--r-- | drivers/firewire/core.h | 2 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 87 | ||||
-rw-r--r-- | drivers/firewire/sbp2.c | 5 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-fw.c | 39 | ||||
-rw-r--r-- | include/linux/firewire.h | 11 |
8 files changed, 180 insertions, 124 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 4eeaed57e219..3c1ac0933d24 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/string.h> | 38 | #include <linux/string.h> |
@@ -1035,21 +1035,19 @@ static int ioctl_get_cycle_timer(struct client *client, void *buffer) | |||
1035 | { | 1035 | { |
1036 | struct fw_cdev_get_cycle_timer *request = buffer; | 1036 | struct fw_cdev_get_cycle_timer *request = buffer; |
1037 | struct fw_card *card = client->device->card; | 1037 | struct fw_card *card = client->device->card; |
1038 | unsigned long long bus_time; | ||
1039 | struct timeval tv; | 1038 | struct timeval tv; |
1040 | unsigned long flags; | 1039 | u32 cycle_time; |
1041 | 1040 | ||
1042 | preempt_disable(); | 1041 | local_irq_disable(); |
1043 | local_irq_save(flags); | ||
1044 | 1042 | ||
1045 | bus_time = card->driver->get_bus_time(card); | 1043 | cycle_time = card->driver->get_cycle_time(card); |
1046 | do_gettimeofday(&tv); | 1044 | do_gettimeofday(&tv); |
1047 | 1045 | ||
1048 | local_irq_restore(flags); | 1046 | local_irq_enable(); |
1049 | preempt_enable(); | ||
1050 | 1047 | ||
1051 | request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; | 1048 | request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; |
1052 | request->cycle_timer = bus_time & 0xffffffff; | 1049 | request->cycle_timer = cycle_time; |
1050 | |||
1053 | return 0; | 1051 | return 0; |
1054 | } | 1052 | } |
1055 | 1053 | ||
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 9d0dfcbe2c1c..eecd52dc8e98 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c | |||
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | #include "core.h" | 44 | #include "core.h" |
45 | 45 | ||
46 | void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) | 46 | void fw_csr_iterator_init(struct fw_csr_iterator *ci, const u32 *p) |
47 | { | 47 | { |
48 | ci->p = p + 1; | 48 | ci->p = p + 1; |
49 | ci->end = ci->p + (p[0] >> 16); | 49 | ci->end = ci->p + (p[0] >> 16); |
@@ -59,9 +59,76 @@ int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value) | |||
59 | } | 59 | } |
60 | EXPORT_SYMBOL(fw_csr_iterator_next); | 60 | EXPORT_SYMBOL(fw_csr_iterator_next); |
61 | 61 | ||
62 | static const u32 *search_leaf(const u32 *directory, int search_key) | ||
63 | { | ||
64 | struct fw_csr_iterator ci; | ||
65 | int last_key = 0, key, value; | ||
66 | |||
67 | fw_csr_iterator_init(&ci, directory); | ||
68 | while (fw_csr_iterator_next(&ci, &key, &value)) { | ||
69 | if (last_key == search_key && | ||
70 | key == (CSR_DESCRIPTOR | CSR_LEAF)) | ||
71 | return ci.p - 1 + value; | ||
72 | |||
73 | last_key = key; | ||
74 | } | ||
75 | |||
76 | return NULL; | ||
77 | } | ||
78 | |||
79 | static int textual_leaf_to_string(const u32 *block, char *buf, size_t size) | ||
80 | { | ||
81 | unsigned int quadlets, i; | ||
82 | char c; | ||
83 | |||
84 | if (!size || !buf) | ||
85 | return -EINVAL; | ||
86 | |||
87 | quadlets = min(block[0] >> 16, 256U); | ||
88 | if (quadlets < 2) | ||
89 | return -ENODATA; | ||
90 | |||
91 | if (block[1] != 0 || block[2] != 0) | ||
92 | /* unknown language/character set */ | ||
93 | return -ENODATA; | ||
94 | |||
95 | block += 3; | ||
96 | quadlets -= 2; | ||
97 | for (i = 0; i < quadlets * 4 && i < size - 1; i++) { | ||
98 | c = block[i / 4] >> (24 - 8 * (i % 4)); | ||
99 | if (c == '\0') | ||
100 | break; | ||
101 | buf[i] = c; | ||
102 | } | ||
103 | buf[i] = '\0'; | ||
104 | |||
105 | return i; | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * fw_csr_string - reads a string from the configuration ROM | ||
110 | * @directory: e.g. root directory or unit directory | ||
111 | * @key: the key of the preceding directory entry | ||
112 | * @buf: where to put the string | ||
113 | * @size: size of @buf, in bytes | ||
114 | * | ||
115 | * The string is taken from a minimal ASCII text descriptor leaf after | ||
116 | * the immediate entry with @key. The string is zero-terminated. | ||
117 | * Returns strlen(buf) or a negative error code. | ||
118 | */ | ||
119 | int fw_csr_string(const u32 *directory, int key, char *buf, size_t size) | ||
120 | { | ||
121 | const u32 *leaf = search_leaf(directory, key); | ||
122 | if (!leaf) | ||
123 | return -ENOENT; | ||
124 | |||
125 | return textual_leaf_to_string(leaf, buf, size); | ||
126 | } | ||
127 | EXPORT_SYMBOL(fw_csr_string); | ||
128 | |||
62 | static bool is_fw_unit(struct device *dev); | 129 | static bool is_fw_unit(struct device *dev); |
63 | 130 | ||
64 | static int match_unit_directory(u32 *directory, u32 match_flags, | 131 | static int match_unit_directory(const u32 *directory, u32 match_flags, |
65 | const struct ieee1394_device_id *id) | 132 | const struct ieee1394_device_id *id) |
66 | { | 133 | { |
67 | struct fw_csr_iterator ci; | 134 | struct fw_csr_iterator ci; |
@@ -195,7 +262,7 @@ static ssize_t show_immediate(struct device *dev, | |||
195 | struct config_rom_attribute *attr = | 262 | struct config_rom_attribute *attr = |
196 | container_of(dattr, struct config_rom_attribute, attr); | 263 | container_of(dattr, struct config_rom_attribute, attr); |
197 | struct fw_csr_iterator ci; | 264 | struct fw_csr_iterator ci; |
198 | u32 *dir; | 265 | const u32 *dir; |
199 | int key, value, ret = -ENOENT; | 266 | int key, value, ret = -ENOENT; |
200 | 267 | ||
201 | down_read(&fw_device_rwsem); | 268 | down_read(&fw_device_rwsem); |
@@ -226,10 +293,10 @@ static ssize_t show_text_leaf(struct device *dev, | |||
226 | { | 293 | { |
227 | struct config_rom_attribute *attr = | 294 | struct config_rom_attribute *attr = |
228 | container_of(dattr, struct config_rom_attribute, attr); | 295 | container_of(dattr, struct config_rom_attribute, attr); |
229 | struct fw_csr_iterator ci; | 296 | const u32 *dir; |
230 | u32 *dir, *block = NULL, *p, *end; | 297 | size_t bufsize; |
231 | int length, key, value, last_key = 0, ret = -ENOENT; | 298 | char dummy_buf[2]; |
232 | char *b; | 299 | int ret; |
233 | 300 | ||
234 | down_read(&fw_device_rwsem); | 301 | down_read(&fw_device_rwsem); |
235 | 302 | ||
@@ -238,40 +305,23 @@ static ssize_t show_text_leaf(struct device *dev, | |||
238 | else | 305 | else |
239 | dir = fw_device(dev)->config_rom + 5; | 306 | dir = fw_device(dev)->config_rom + 5; |
240 | 307 | ||
241 | fw_csr_iterator_init(&ci, dir); | 308 | if (buf) { |
242 | while (fw_csr_iterator_next(&ci, &key, &value)) { | 309 | bufsize = PAGE_SIZE - 1; |
243 | if (attr->key == last_key && | 310 | } else { |
244 | key == (CSR_DESCRIPTOR | CSR_LEAF)) | 311 | buf = dummy_buf; |
245 | block = ci.p - 1 + value; | 312 | bufsize = 1; |
246 | last_key = key; | ||
247 | } | 313 | } |
248 | 314 | ||
249 | if (block == NULL) | 315 | ret = fw_csr_string(dir, attr->key, buf, bufsize); |
250 | goto out; | ||
251 | |||
252 | length = min(block[0] >> 16, 256U); | ||
253 | if (length < 3) | ||
254 | goto out; | ||
255 | 316 | ||
256 | if (block[1] != 0 || block[2] != 0) | 317 | if (ret >= 0) { |
257 | /* Unknown encoding. */ | 318 | /* Strip trailing whitespace and add newline. */ |
258 | goto out; | 319 | while (ret > 0 && isspace(buf[ret - 1])) |
259 | 320 | ret--; | |
260 | if (buf == NULL) { | 321 | strcpy(buf + ret, "\n"); |
261 | ret = length * 4; | 322 | ret++; |
262 | goto out; | ||
263 | } | 323 | } |
264 | 324 | ||
265 | b = buf; | ||
266 | end = &block[length + 1]; | ||
267 | for (p = &block[3]; p < end; p++, b += 4) | ||
268 | * (u32 *) b = (__force u32) __cpu_to_be32(*p); | ||
269 | |||
270 | /* Strip trailing whitespace and add newline. */ | ||
271 | while (b--, (isspace(*b) || *b == '\0') && b > buf); | ||
272 | strcpy(b + 1, "\n"); | ||
273 | ret = b + 2 - buf; | ||
274 | out: | ||
275 | up_read(&fw_device_rwsem); | 325 | up_read(&fw_device_rwsem); |
276 | 326 | ||
277 | return ret; | 327 | return ret; |
@@ -371,7 +421,7 @@ static ssize_t guid_show(struct device *dev, | |||
371 | return ret; | 421 | return ret; |
372 | } | 422 | } |
373 | 423 | ||
374 | static int units_sprintf(char *buf, u32 *directory) | 424 | static int units_sprintf(char *buf, const u32 *directory) |
375 | { | 425 | { |
376 | struct fw_csr_iterator ci; | 426 | struct fw_csr_iterator ci; |
377 | int key, value; | 427 | int key, value; |
@@ -453,7 +503,8 @@ static int read_rom(struct fw_device *device, | |||
453 | */ | 503 | */ |
454 | static int read_bus_info_block(struct fw_device *device, int generation) | 504 | static int read_bus_info_block(struct fw_device *device, int generation) |
455 | { | 505 | { |
456 | u32 *rom, *stack, *old_rom, *new_rom; | 506 | const u32 *old_rom, *new_rom; |
507 | u32 *rom, *stack; | ||
457 | u32 sp, key; | 508 | u32 sp, key; |
458 | int i, end, length, ret = -1; | 509 | int i, end, length, ret = -1; |
459 | 510 | ||
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 43ebf337b131..0f7c4bb978e7 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,11 +186,11 @@ 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; |
194 | bool bus_reset_packet_quirk; | 192 | bool bus_reset_packet_quirk; |
193 | bool iso_cycle_timer_quirk; | ||
195 | 194 | ||
196 | /* | 195 | /* |
197 | * Spinlock for accessing fw_ohci data. Never call out of | 196 | * Spinlock for accessing fw_ohci data. Never call out of |
@@ -275,7 +274,7 @@ static void log_irqs(u32 evt) | |||
275 | !(evt & OHCI1394_busReset)) | 274 | !(evt & OHCI1394_busReset)) |
276 | return; | 275 | return; |
277 | 276 | ||
278 | 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, |
279 | evt & OHCI1394_selfIDComplete ? " selfID" : "", | 278 | evt & OHCI1394_selfIDComplete ? " selfID" : "", |
280 | evt & OHCI1394_RQPkt ? " AR_req" : "", | 279 | evt & OHCI1394_RQPkt ? " AR_req" : "", |
281 | evt & OHCI1394_RSPkt ? " AR_resp" : "", | 280 | evt & OHCI1394_RSPkt ? " AR_resp" : "", |
@@ -285,7 +284,6 @@ static void log_irqs(u32 evt) | |||
285 | evt & OHCI1394_isochTx ? " IT" : "", | 284 | evt & OHCI1394_isochTx ? " IT" : "", |
286 | evt & OHCI1394_postedWriteErr ? " postedWriteErr" : "", | 285 | evt & OHCI1394_postedWriteErr ? " postedWriteErr" : "", |
287 | evt & OHCI1394_cycleTooLong ? " cycleTooLong" : "", | 286 | evt & OHCI1394_cycleTooLong ? " cycleTooLong" : "", |
288 | evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "", | ||
289 | evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "", | 287 | evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "", |
290 | evt & OHCI1394_regAccessFail ? " regAccessFail" : "", | 288 | evt & OHCI1394_regAccessFail ? " regAccessFail" : "", |
291 | evt & OHCI1394_busReset ? " busReset" : "", | 289 | evt & OHCI1394_busReset ? " busReset" : "", |
@@ -293,8 +291,7 @@ static void log_irqs(u32 evt) | |||
293 | OHCI1394_RSPkt | OHCI1394_reqTxComplete | | 291 | OHCI1394_RSPkt | OHCI1394_reqTxComplete | |
294 | OHCI1394_respTxComplete | OHCI1394_isochRx | | 292 | OHCI1394_respTxComplete | OHCI1394_isochRx | |
295 | OHCI1394_isochTx | OHCI1394_postedWriteErr | | 293 | OHCI1394_isochTx | OHCI1394_postedWriteErr | |
296 | OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds | | 294 | OHCI1394_cycleTooLong | OHCI1394_cycleInconsistent | |
297 | OHCI1394_cycleInconsistent | | ||
298 | OHCI1394_regAccessFail | OHCI1394_busReset) | 295 | OHCI1394_regAccessFail | OHCI1394_busReset) |
299 | ? " ?" : ""); | 296 | ? " ?" : ""); |
300 | } | 297 | } |
@@ -1384,7 +1381,7 @@ static void bus_reset_tasklet(unsigned long data) | |||
1384 | static irqreturn_t irq_handler(int irq, void *data) | 1381 | static irqreturn_t irq_handler(int irq, void *data) |
1385 | { | 1382 | { |
1386 | struct fw_ohci *ohci = data; | 1383 | struct fw_ohci *ohci = data; |
1387 | u32 event, iso_event, cycle_time; | 1384 | u32 event, iso_event; |
1388 | int i; | 1385 | int i; |
1389 | 1386 | ||
1390 | event = reg_read(ohci, OHCI1394_IntEventClear); | 1387 | event = reg_read(ohci, OHCI1394_IntEventClear); |
@@ -1454,12 +1451,6 @@ static irqreturn_t irq_handler(int irq, void *data) | |||
1454 | fw_notify("isochronous cycle inconsistent\n"); | 1451 | fw_notify("isochronous cycle inconsistent\n"); |
1455 | } | 1452 | } |
1456 | 1453 | ||
1457 | if (event & OHCI1394_cycle64Seconds) { | ||
1458 | cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | ||
1459 | if ((cycle_time & 0x80000000) == 0) | ||
1460 | atomic_inc(&ohci->bus_seconds); | ||
1461 | } | ||
1462 | |||
1463 | return IRQ_HANDLED; | 1454 | return IRQ_HANDLED; |
1464 | } | 1455 | } |
1465 | 1456 | ||
@@ -1553,8 +1544,7 @@ static int ohci_enable(struct fw_card *card, | |||
1553 | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | | 1544 | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | |
1554 | OHCI1394_isochRx | OHCI1394_isochTx | | 1545 | OHCI1394_isochRx | OHCI1394_isochTx | |
1555 | OHCI1394_postedWriteErr | OHCI1394_cycleTooLong | | 1546 | OHCI1394_postedWriteErr | OHCI1394_cycleTooLong | |
1556 | OHCI1394_cycleInconsistent | | 1547 | OHCI1394_cycleInconsistent | OHCI1394_regAccessFail | |
1557 | OHCI1394_cycle64Seconds | OHCI1394_regAccessFail | | ||
1558 | OHCI1394_masterIntEnable); | 1548 | OHCI1394_masterIntEnable); |
1559 | if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) | 1549 | if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) |
1560 | reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); | 1550 | reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); |
@@ -1794,16 +1784,61 @@ static int ohci_enable_phys_dma(struct fw_card *card, | |||
1794 | #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ | 1784 | #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ |
1795 | } | 1785 | } |
1796 | 1786 | ||
1797 | static u64 ohci_get_bus_time(struct fw_card *card) | 1787 | static u32 cycle_timer_ticks(u32 cycle_timer) |
1798 | { | 1788 | { |
1799 | struct fw_ohci *ohci = fw_ohci(card); | 1789 | u32 ticks; |
1800 | u32 cycle_time; | ||
1801 | u64 bus_time; | ||
1802 | 1790 | ||
1803 | cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | 1791 | ticks = cycle_timer & 0xfff; |
1804 | bus_time = ((u64)atomic_read(&ohci->bus_seconds) << 32) | cycle_time; | 1792 | ticks += 3072 * ((cycle_timer >> 12) & 0x1fff); |
1793 | ticks += (3072 * 8000) * (cycle_timer >> 25); | ||
1805 | 1794 | ||
1806 | return bus_time; | 1795 | return ticks; |
1796 | } | ||
1797 | |||
1798 | /* | ||
1799 | * Some controllers exhibit one or more of the following bugs when updating the | ||
1800 | * iso cycle timer register: | ||
1801 | * - When the lowest six bits are wrapping around to zero, a read that happens | ||
1802 | * at the same time will return garbage in the lowest ten bits. | ||
1803 | * - When the cycleOffset field wraps around to zero, the cycleCount field is | ||
1804 | * not incremented for about 60 ns. | ||
1805 | * - Occasionally, the entire register reads zero. | ||
1806 | * | ||
1807 | * To catch these, we read the register three times and ensure that the | ||
1808 | * difference between each two consecutive reads is approximately the same, i.e. | ||
1809 | * less than twice the other. Furthermore, any negative difference indicates an | ||
1810 | * error. (A PCI read should take at least 20 ticks of the 24.576 MHz timer to | ||
1811 | * execute, so we have enough precision to compute the ratio of the differences.) | ||
1812 | */ | ||
1813 | static u32 ohci_get_cycle_time(struct fw_card *card) | ||
1814 | { | ||
1815 | struct fw_ohci *ohci = fw_ohci(card); | ||
1816 | u32 c0, c1, c2; | ||
1817 | u32 t0, t1, t2; | ||
1818 | s32 diff01, diff12; | ||
1819 | int i; | ||
1820 | |||
1821 | c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | ||
1822 | |||
1823 | if (ohci->iso_cycle_timer_quirk) { | ||
1824 | i = 0; | ||
1825 | c1 = c2; | ||
1826 | c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | ||
1827 | do { | ||
1828 | c0 = c1; | ||
1829 | c1 = c2; | ||
1830 | c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | ||
1831 | t0 = cycle_timer_ticks(c0); | ||
1832 | t1 = cycle_timer_ticks(c1); | ||
1833 | t2 = cycle_timer_ticks(c2); | ||
1834 | diff01 = t1 - t0; | ||
1835 | diff12 = t2 - t1; | ||
1836 | } while ((diff01 <= 0 || diff12 <= 0 || | ||
1837 | diff01 / diff12 >= 2 || diff12 / diff01 >= 2) | ||
1838 | && i++ < 20); | ||
1839 | } | ||
1840 | |||
1841 | return c2; | ||
1807 | } | 1842 | } |
1808 | 1843 | ||
1809 | static void copy_iso_headers(struct iso_context *ctx, void *p) | 1844 | static void copy_iso_headers(struct iso_context *ctx, void *p) |
@@ -2383,7 +2418,7 @@ static const struct fw_card_driver ohci_driver = { | |||
2383 | .send_response = ohci_send_response, | 2418 | .send_response = ohci_send_response, |
2384 | .cancel_packet = ohci_cancel_packet, | 2419 | .cancel_packet = ohci_cancel_packet, |
2385 | .enable_phys_dma = ohci_enable_phys_dma, | 2420 | .enable_phys_dma = ohci_enable_phys_dma, |
2386 | .get_bus_time = ohci_get_bus_time, | 2421 | .get_cycle_time = ohci_get_cycle_time, |
2387 | 2422 | ||
2388 | .allocate_iso_context = ohci_allocate_iso_context, | 2423 | .allocate_iso_context = ohci_allocate_iso_context, |
2389 | .free_iso_context = ohci_free_iso_context, | 2424 | .free_iso_context = ohci_free_iso_context, |
@@ -2503,6 +2538,10 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
2503 | #endif | 2538 | #endif |
2504 | ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI; | 2539 | ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI; |
2505 | 2540 | ||
2541 | ohci->iso_cycle_timer_quirk = dev->vendor == PCI_VENDOR_ID_AL || | ||
2542 | dev->vendor == PCI_VENDOR_ID_NEC || | ||
2543 | dev->vendor == PCI_VENDOR_ID_VIA; | ||
2544 | |||
2506 | ar_context_init(&ohci->ar_request_ctx, ohci, | 2545 | ar_context_init(&ohci->ar_request_ctx, ohci, |
2507 | OHCI1394_AsReqRcvContextControlSet); | 2546 | OHCI1394_AsReqRcvContextControlSet); |
2508 | 2547 | ||
@@ -2662,7 +2701,7 @@ static int pci_resume(struct pci_dev *dev) | |||
2662 | } | 2701 | } |
2663 | #endif | 2702 | #endif |
2664 | 2703 | ||
2665 | static struct pci_device_id pci_table[] = { | 2704 | static const struct pci_device_id pci_table[] = { |
2666 | { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) }, | 2705 | { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) }, |
2667 | { } | 2706 | { } |
2668 | }; | 2707 | }; |
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index d485cdd8cbac..7e33b0b1704c 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c | |||
@@ -1014,7 +1014,8 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) | |||
1014 | return 0; | 1014 | return 0; |
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory) | 1017 | static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, |
1018 | const u32 *directory) | ||
1018 | { | 1019 | { |
1019 | struct fw_csr_iterator ci; | 1020 | struct fw_csr_iterator ci; |
1020 | int key, value; | 1021 | int key, value; |
@@ -1027,7 +1028,7 @@ static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory) | |||
1027 | return 0; | 1028 | return 0; |
1028 | } | 1029 | } |
1029 | 1030 | ||
1030 | static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory, | 1031 | static int sbp2_scan_unit_dir(struct sbp2_target *tgt, const u32 *directory, |
1031 | u32 *model, u32 *firmware_revision) | 1032 | u32 *model, u32 *firmware_revision) |
1032 | { | 1033 | { |
1033 | struct fw_csr_iterator ci; | 1034 | struct fw_csr_iterator ci; |
diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index 6223bf01efe9..4253b7ab0097 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c | |||
@@ -239,47 +239,18 @@ static const struct fw_address_region fcp_region = { | |||
239 | }; | 239 | }; |
240 | 240 | ||
241 | /* Adjust the template string if models with longer names appear. */ | 241 | /* Adjust the template string if models with longer names appear. */ |
242 | #define MAX_MODEL_NAME_LEN ((int)DIV_ROUND_UP(sizeof("FireDTV ????"), 4)) | 242 | #define MAX_MODEL_NAME_LEN sizeof("FireDTV ????") |
243 | |||
244 | static size_t model_name(u32 *directory, __be32 *buffer) | ||
245 | { | ||
246 | struct fw_csr_iterator ci; | ||
247 | int i, length, key, value, last_key = 0; | ||
248 | u32 *block = NULL; | ||
249 | |||
250 | fw_csr_iterator_init(&ci, directory); | ||
251 | while (fw_csr_iterator_next(&ci, &key, &value)) { | ||
252 | if (last_key == CSR_MODEL && | ||
253 | key == (CSR_DESCRIPTOR | CSR_LEAF)) | ||
254 | block = ci.p - 1 + value; | ||
255 | last_key = key; | ||
256 | } | ||
257 | |||
258 | if (block == NULL) | ||
259 | return 0; | ||
260 | |||
261 | length = min((int)(block[0] >> 16) - 2, MAX_MODEL_NAME_LEN); | ||
262 | if (length <= 0) | ||
263 | return 0; | ||
264 | |||
265 | /* fast-forward to text string */ | ||
266 | block += 3; | ||
267 | |||
268 | for (i = 0; i < length; i++) | ||
269 | buffer[i] = cpu_to_be32(block[i]); | ||
270 | |||
271 | return length * 4; | ||
272 | } | ||
273 | 243 | ||
274 | static int node_probe(struct device *dev) | 244 | static int node_probe(struct device *dev) |
275 | { | 245 | { |
276 | struct firedtv *fdtv; | 246 | struct firedtv *fdtv; |
277 | __be32 name[MAX_MODEL_NAME_LEN]; | 247 | char name[MAX_MODEL_NAME_LEN]; |
278 | int name_len, err; | 248 | int name_len, err; |
279 | 249 | ||
280 | name_len = model_name(fw_unit(dev)->directory, name); | 250 | name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL, |
251 | name, sizeof(name)); | ||
281 | 252 | ||
282 | fdtv = fdtv_alloc(dev, &backend, (char *)name, name_len); | 253 | fdtv = fdtv_alloc(dev, &backend, name, name_len >= 0 ? name_len : 0); |
283 | if (!fdtv) | 254 | if (!fdtv) |
284 | return -ENOMEM; | 255 | return -ENOMEM; |
285 | 256 | ||
diff --git a/include/linux/firewire.h b/include/linux/firewire.h index a0e67150a729..4bd94bf5e739 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h | |||
@@ -65,12 +65,13 @@ | |||
65 | #define CSR_DIRECTORY_ID 0x20 | 65 | #define CSR_DIRECTORY_ID 0x20 |
66 | 66 | ||
67 | struct fw_csr_iterator { | 67 | struct fw_csr_iterator { |
68 | u32 *p; | 68 | const u32 *p; |
69 | u32 *end; | 69 | const u32 *end; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p); | 72 | void fw_csr_iterator_init(struct fw_csr_iterator *ci, const u32 *p); |
73 | int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value); | 73 | int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value); |
74 | int fw_csr_string(const u32 *directory, int key, char *buf, size_t size); | ||
74 | 75 | ||
75 | extern struct bus_type fw_bus_type; | 76 | extern struct bus_type fw_bus_type; |
76 | 77 | ||
@@ -162,7 +163,7 @@ struct fw_device { | |||
162 | struct mutex client_list_mutex; | 163 | struct mutex client_list_mutex; |
163 | struct list_head client_list; | 164 | struct list_head client_list; |
164 | 165 | ||
165 | u32 *config_rom; | 166 | const u32 *config_rom; |
166 | size_t config_rom_length; | 167 | size_t config_rom_length; |
167 | int config_rom_retries; | 168 | int config_rom_retries; |
168 | unsigned is_local:1; | 169 | unsigned is_local:1; |
@@ -204,7 +205,7 @@ int fw_device_enable_phys_dma(struct fw_device *device); | |||
204 | */ | 205 | */ |
205 | struct fw_unit { | 206 | struct fw_unit { |
206 | struct device device; | 207 | struct device device; |
207 | u32 *directory; | 208 | const u32 *directory; |
208 | struct fw_attribute_group attribute_group; | 209 | struct fw_attribute_group attribute_group; |
209 | }; | 210 | }; |
210 | 211 | ||