aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/core-device.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-03-03 11:08:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-03 11:08:44 -0500
commitc1dcb4bb1e3e16e9baee578d9bb040e5fba1063e (patch)
tree1bba995740aed8ef9a47111c1ee6ceeda84af836 /drivers/firewire/core-device.c
parent60f8a8d4c6c46bb080e8e65d30be31b172a39a78 (diff)
parent6fdb2ee243404c7cbf530387bf904ad1841ebf5b (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (23 commits) firewire: ohci: extend initialization log message firewire: ohci: fix IR/IT context mask mixup firewire: ohci: add module parameter to activate quirk fixes firewire: ohci: use an ID table for quirks detection firewire: ohci: reorder struct fw_ohci for better cache efficiency firewire: ohci: remove unused dualbuffer IR code firewire: core: combine a bit of repeated code firewire: core: change type of a data buffer firewire: cdev: increment ABI version number firewire: cdev: add more flexible cycle timer ioctl firewire: core: rename an internal function firewire: core: fix an information leak firewire: core: increase stack size of config ROM reader firewire: core: don't fail device creation in case of too large config ROM blocks firewire: core: fix "giving up on config rom" with Panasonic AG-DV2500 firewire: remove incomplete Bus_Time CSR support firewire: get_cycle_timer optimization and cleanup firewire: ohci: enable cycle timer fix on ALi and NEC controllers firewire: ohci: work around cycle timer bugs on VIA controllers firewire: make PCI device id constant ...
Diffstat (limited to 'drivers/firewire/core-device.c')
-rw-r--r--drivers/firewire/core-device.c198
1 files changed, 132 insertions, 66 deletions
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 9d0dfcbe2c1c..014cabd3afda 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -18,6 +18,7 @@
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */ 19 */
20 20
21#include <linux/bug.h>
21#include <linux/ctype.h> 22#include <linux/ctype.h>
22#include <linux/delay.h> 23#include <linux/delay.h>
23#include <linux/device.h> 24#include <linux/device.h>
@@ -43,7 +44,7 @@
43 44
44#include "core.h" 45#include "core.h"
45 46
46void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) 47void fw_csr_iterator_init(struct fw_csr_iterator *ci, const u32 *p)
47{ 48{
48 ci->p = p + 1; 49 ci->p = p + 1;
49 ci->end = ci->p + (p[0] >> 16); 50 ci->end = ci->p + (p[0] >> 16);
@@ -59,9 +60,76 @@ int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value)
59} 60}
60EXPORT_SYMBOL(fw_csr_iterator_next); 61EXPORT_SYMBOL(fw_csr_iterator_next);
61 62
63static const u32 *search_leaf(const u32 *directory, int search_key)
64{
65 struct fw_csr_iterator ci;
66 int last_key = 0, key, value;
67
68 fw_csr_iterator_init(&ci, directory);
69 while (fw_csr_iterator_next(&ci, &key, &value)) {
70 if (last_key == search_key &&
71 key == (CSR_DESCRIPTOR | CSR_LEAF))
72 return ci.p - 1 + value;
73
74 last_key = key;
75 }
76
77 return NULL;
78}
79
80static int textual_leaf_to_string(const u32 *block, char *buf, size_t size)
81{
82 unsigned int quadlets, i;
83 char c;
84
85 if (!size || !buf)
86 return -EINVAL;
87
88 quadlets = min(block[0] >> 16, 256U);
89 if (quadlets < 2)
90 return -ENODATA;
91
92 if (block[1] != 0 || block[2] != 0)
93 /* unknown language/character set */
94 return -ENODATA;
95
96 block += 3;
97 quadlets -= 2;
98 for (i = 0; i < quadlets * 4 && i < size - 1; i++) {
99 c = block[i / 4] >> (24 - 8 * (i % 4));
100 if (c == '\0')
101 break;
102 buf[i] = c;
103 }
104 buf[i] = '\0';
105
106 return i;
107}
108
109/**
110 * fw_csr_string - reads a string from the configuration ROM
111 * @directory: e.g. root directory or unit directory
112 * @key: the key of the preceding directory entry
113 * @buf: where to put the string
114 * @size: size of @buf, in bytes
115 *
116 * The string is taken from a minimal ASCII text descriptor leaf after
117 * the immediate entry with @key. The string is zero-terminated.
118 * Returns strlen(buf) or a negative error code.
119 */
120int fw_csr_string(const u32 *directory, int key, char *buf, size_t size)
121{
122 const u32 *leaf = search_leaf(directory, key);
123 if (!leaf)
124 return -ENOENT;
125
126 return textual_leaf_to_string(leaf, buf, size);
127}
128EXPORT_SYMBOL(fw_csr_string);
129
62static bool is_fw_unit(struct device *dev); 130static bool is_fw_unit(struct device *dev);
63 131
64static int match_unit_directory(u32 *directory, u32 match_flags, 132static int match_unit_directory(const u32 *directory, u32 match_flags,
65 const struct ieee1394_device_id *id) 133 const struct ieee1394_device_id *id)
66{ 134{
67 struct fw_csr_iterator ci; 135 struct fw_csr_iterator ci;
@@ -195,7 +263,7 @@ static ssize_t show_immediate(struct device *dev,
195 struct config_rom_attribute *attr = 263 struct config_rom_attribute *attr =
196 container_of(dattr, struct config_rom_attribute, attr); 264 container_of(dattr, struct config_rom_attribute, attr);
197 struct fw_csr_iterator ci; 265 struct fw_csr_iterator ci;
198 u32 *dir; 266 const u32 *dir;
199 int key, value, ret = -ENOENT; 267 int key, value, ret = -ENOENT;
200 268
201 down_read(&fw_device_rwsem); 269 down_read(&fw_device_rwsem);
@@ -226,10 +294,10 @@ static ssize_t show_text_leaf(struct device *dev,
226{ 294{
227 struct config_rom_attribute *attr = 295 struct config_rom_attribute *attr =
228 container_of(dattr, struct config_rom_attribute, attr); 296 container_of(dattr, struct config_rom_attribute, attr);
229 struct fw_csr_iterator ci; 297 const u32 *dir;
230 u32 *dir, *block = NULL, *p, *end; 298 size_t bufsize;
231 int length, key, value, last_key = 0, ret = -ENOENT; 299 char dummy_buf[2];
232 char *b; 300 int ret;
233 301
234 down_read(&fw_device_rwsem); 302 down_read(&fw_device_rwsem);
235 303
@@ -238,40 +306,23 @@ static ssize_t show_text_leaf(struct device *dev,
238 else 306 else
239 dir = fw_device(dev)->config_rom + 5; 307 dir = fw_device(dev)->config_rom + 5;
240 308
241 fw_csr_iterator_init(&ci, dir); 309 if (buf) {
242 while (fw_csr_iterator_next(&ci, &key, &value)) { 310 bufsize = PAGE_SIZE - 1;
243 if (attr->key == last_key && 311 } else {
244 key == (CSR_DESCRIPTOR | CSR_LEAF)) 312 buf = dummy_buf;
245 block = ci.p - 1 + value; 313 bufsize = 1;
246 last_key = key;
247 } 314 }
248 315
249 if (block == NULL) 316 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
256 if (block[1] != 0 || block[2] != 0)
257 /* Unknown encoding. */
258 goto out;
259 317
260 if (buf == NULL) { 318 if (ret >= 0) {
261 ret = length * 4; 319 /* Strip trailing whitespace and add newline. */
262 goto out; 320 while (ret > 0 && isspace(buf[ret - 1]))
321 ret--;
322 strcpy(buf + ret, "\n");
323 ret++;
263 } 324 }
264 325
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); 326 up_read(&fw_device_rwsem);
276 327
277 return ret; 328 return ret;
@@ -371,7 +422,7 @@ static ssize_t guid_show(struct device *dev,
371 return ret; 422 return ret;
372} 423}
373 424
374static int units_sprintf(char *buf, u32 *directory) 425static int units_sprintf(char *buf, const u32 *directory)
375{ 426{
376 struct fw_csr_iterator ci; 427 struct fw_csr_iterator ci;
377 int key, value; 428 int key, value;
@@ -441,28 +492,29 @@ static int read_rom(struct fw_device *device,
441 return rcode; 492 return rcode;
442} 493}
443 494
444#define READ_BIB_ROM_SIZE 256 495#define MAX_CONFIG_ROM_SIZE 256
445#define READ_BIB_STACK_SIZE 16
446 496
447/* 497/*
448 * Read the bus info block, perform a speed probe, and read all of the rest of 498 * Read the bus info block, perform a speed probe, and read all of the rest of
449 * the config ROM. We do all this with a cached bus generation. If the bus 499 * the config ROM. We do all this with a cached bus generation. If the bus
450 * generation changes under us, read_bus_info_block will fail and get retried. 500 * generation changes under us, read_config_rom will fail and get retried.
451 * It's better to start all over in this case because the node from which we 501 * It's better to start all over in this case because the node from which we
452 * are reading the ROM may have changed the ROM during the reset. 502 * are reading the ROM may have changed the ROM during the reset.
453 */ 503 */
454static int read_bus_info_block(struct fw_device *device, int generation) 504static int read_config_rom(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
460 rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE + 511 rom = kmalloc(sizeof(*rom) * MAX_CONFIG_ROM_SIZE +
461 sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL); 512 sizeof(*stack) * MAX_CONFIG_ROM_SIZE, GFP_KERNEL);
462 if (rom == NULL) 513 if (rom == NULL)
463 return -ENOMEM; 514 return -ENOMEM;
464 515
465 stack = &rom[READ_BIB_ROM_SIZE]; 516 stack = &rom[MAX_CONFIG_ROM_SIZE];
517 memset(rom, 0, sizeof(*rom) * MAX_CONFIG_ROM_SIZE);
466 518
467 device->max_speed = SCODE_100; 519 device->max_speed = SCODE_100;
468 520
@@ -529,40 +581,54 @@ static int read_bus_info_block(struct fw_device *device, int generation)
529 */ 581 */
530 key = stack[--sp]; 582 key = stack[--sp];
531 i = key & 0xffffff; 583 i = key & 0xffffff;
532 if (i >= READ_BIB_ROM_SIZE) 584 if (WARN_ON(i >= MAX_CONFIG_ROM_SIZE))
533 /*
534 * The reference points outside the standard
535 * config rom area, something's fishy.
536 */
537 goto out; 585 goto out;
538 586
539 /* Read header quadlet for the block to get the length. */ 587 /* Read header quadlet for the block to get the length. */
540 if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE) 588 if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
541 goto out; 589 goto out;
542 end = i + (rom[i] >> 16) + 1; 590 end = i + (rom[i] >> 16) + 1;
543 i++; 591 if (end > MAX_CONFIG_ROM_SIZE) {
544 if (end > READ_BIB_ROM_SIZE)
545 /* 592 /*
546 * This block extends outside standard config 593 * This block extends outside the config ROM which is
547 * area (and the array we're reading it 594 * a firmware bug. Ignore this whole block, i.e.
548 * into). That's broken, so ignore this 595 * simply set a fake block length of 0.
549 * device.
550 */ 596 */
551 goto out; 597 fw_error("skipped invalid ROM block %x at %llx\n",
598 rom[i],
599 i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
600 rom[i] = 0;
601 end = i;
602 }
603 i++;
552 604
553 /* 605 /*
554 * Now read in the block. If this is a directory 606 * Now read in the block. If this is a directory
555 * block, check the entries as we read them to see if 607 * block, check the entries as we read them to see if
556 * it references another block, and push it in that case. 608 * it references another block, and push it in that case.
557 */ 609 */
558 while (i < end) { 610 for (; i < end; i++) {
559 if (read_rom(device, generation, i, &rom[i]) != 611 if (read_rom(device, generation, i, &rom[i]) !=
560 RCODE_COMPLETE) 612 RCODE_COMPLETE)
561 goto out; 613 goto out;
562 if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && 614
563 sp < READ_BIB_STACK_SIZE) 615 if ((key >> 30) != 3 || (rom[i] >> 30) < 2)
564 stack[sp++] = i + rom[i]; 616 continue;
565 i++; 617 /*
618 * Offset points outside the ROM. May be a firmware
619 * bug or an Extended ROM entry (IEEE 1212-2001 clause
620 * 7.7.18). Simply overwrite this pointer here by a
621 * fake immediate entry so that later iterators over
622 * the ROM don't have to check offsets all the time.
623 */
624 if (i + (rom[i] & 0xffffff) >= MAX_CONFIG_ROM_SIZE) {
625 fw_error("skipped unsupported ROM entry %x at %llx\n",
626 rom[i],
627 i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
628 rom[i] = 0;
629 continue;
630 }
631 stack[sp++] = i + rom[i];
566 } 632 }
567 if (length < i) 633 if (length < i)
568 length = i; 634 length = i;
@@ -905,7 +971,7 @@ static void fw_device_init(struct work_struct *work)
905 * device. 971 * device.
906 */ 972 */
907 973
908 if (read_bus_info_block(device, device->generation) < 0) { 974 if (read_config_rom(device, device->generation) < 0) {
909 if (device->config_rom_retries < MAX_RETRIES && 975 if (device->config_rom_retries < MAX_RETRIES &&
910 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 976 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
911 device->config_rom_retries++; 977 device->config_rom_retries++;
@@ -1022,7 +1088,7 @@ enum {
1022}; 1088};
1023 1089
1024/* Reread and compare bus info block and header of root directory */ 1090/* Reread and compare bus info block and header of root directory */
1025static int reread_bus_info_block(struct fw_device *device, int generation) 1091static int reread_config_rom(struct fw_device *device, int generation)
1026{ 1092{
1027 u32 q; 1093 u32 q;
1028 int i; 1094 int i;
@@ -1048,7 +1114,7 @@ static void fw_device_refresh(struct work_struct *work)
1048 struct fw_card *card = device->card; 1114 struct fw_card *card = device->card;
1049 int node_id = device->node_id; 1115 int node_id = device->node_id;
1050 1116
1051 switch (reread_bus_info_block(device, device->generation)) { 1117 switch (reread_config_rom(device, device->generation)) {
1052 case REREAD_BIB_ERROR: 1118 case REREAD_BIB_ERROR:
1053 if (device->config_rom_retries < MAX_RETRIES / 2 && 1119 if (device->config_rom_retries < MAX_RETRIES / 2 &&
1054 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 1120 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
@@ -1082,7 +1148,7 @@ static void fw_device_refresh(struct work_struct *work)
1082 */ 1148 */
1083 device_for_each_child(&device->device, NULL, shutdown_unit); 1149 device_for_each_child(&device->device, NULL, shutdown_unit);
1084 1150
1085 if (read_bus_info_block(device, device->generation) < 0) { 1151 if (read_config_rom(device, device->generation) < 0) {
1086 if (device->config_rom_retries < MAX_RETRIES && 1152 if (device->config_rom_retries < MAX_RETRIES &&
1087 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 1153 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
1088 device->config_rom_retries++; 1154 device->config_rom_retries++;