aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/core-device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/core-device.c')
-rw-r--r--drivers/firewire/core-device.c303
1 files changed, 173 insertions, 130 deletions
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 9d0dfcbe2c1c..4b8523f00dce 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>
@@ -32,7 +33,7 @@
32#include <linux/module.h> 33#include <linux/module.h>
33#include <linux/mutex.h> 34#include <linux/mutex.h>
34#include <linux/rwsem.h> 35#include <linux/rwsem.h>
35#include <linux/semaphore.h> 36#include <linux/slab.h>
36#include <linux/spinlock.h> 37#include <linux/spinlock.h>
37#include <linux/string.h> 38#include <linux/string.h>
38#include <linux/workqueue.h> 39#include <linux/workqueue.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,97 +60,141 @@ 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
62static bool is_fw_unit(struct device *dev); 63static const u32 *search_leaf(const u32 *directory, int search_key)
63
64static int match_unit_directory(u32 *directory, u32 match_flags,
65 const struct ieee1394_device_id *id)
66{ 64{
67 struct fw_csr_iterator ci; 65 struct fw_csr_iterator ci;
68 int key, value, match; 66 int last_key = 0, key, value;
69 67
70 match = 0;
71 fw_csr_iterator_init(&ci, directory); 68 fw_csr_iterator_init(&ci, directory);
72 while (fw_csr_iterator_next(&ci, &key, &value)) { 69 while (fw_csr_iterator_next(&ci, &key, &value)) {
73 if (key == CSR_VENDOR && value == id->vendor_id) 70 if (last_key == search_key &&
74 match |= IEEE1394_MATCH_VENDOR_ID; 71 key == (CSR_DESCRIPTOR | CSR_LEAF))
75 if (key == CSR_MODEL && value == id->model_id) 72 return ci.p - 1 + value;
76 match |= IEEE1394_MATCH_MODEL_ID; 73
77 if (key == CSR_SPECIFIER_ID && value == id->specifier_id) 74 last_key = key;
78 match |= IEEE1394_MATCH_SPECIFIER_ID;
79 if (key == CSR_VERSION && value == id->version)
80 match |= IEEE1394_MATCH_VERSION;
81 } 75 }
82 76
83 return (match & match_flags) == match_flags; 77 return NULL;
84} 78}
85 79
86static int fw_unit_match(struct device *dev, struct device_driver *drv) 80static int textual_leaf_to_string(const u32 *block, char *buf, size_t size)
87{ 81{
88 struct fw_unit *unit = fw_unit(dev); 82 unsigned int quadlets, i;
89 struct fw_device *device; 83 char c;
90 const struct ieee1394_device_id *id;
91
92 /* We only allow binding to fw_units. */
93 if (!is_fw_unit(dev))
94 return 0;
95 84
96 device = fw_parent_device(unit); 85 if (!size || !buf)
97 id = container_of(drv, struct fw_driver, driver)->id_table; 86 return -EINVAL;
98 87
99 for (; id->match_flags != 0; id++) { 88 quadlets = min(block[0] >> 16, 256U);
100 if (match_unit_directory(unit->directory, id->match_flags, id)) 89 if (quadlets < 2)
101 return 1; 90 return -ENODATA;
102 91
103 /* Also check vendor ID in the root directory. */ 92 if (block[1] != 0 || block[2] != 0)
104 if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && 93 /* unknown language/character set */
105 match_unit_directory(&device->config_rom[5], 94 return -ENODATA;
106 IEEE1394_MATCH_VENDOR_ID, id) && 95
107 match_unit_directory(unit->directory, id->match_flags 96 block += 3;
108 & ~IEEE1394_MATCH_VENDOR_ID, id)) 97 quadlets -= 2;
109 return 1; 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;
110 } 103 }
104 buf[i] = '\0';
111 105
112 return 0; 106 return i;
113} 107}
114 108
115static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) 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)
116{ 121{
117 struct fw_device *device = fw_parent_device(unit); 122 const u32 *leaf = search_leaf(directory, key);
118 struct fw_csr_iterator ci; 123 if (!leaf)
124 return -ENOENT;
125
126 return textual_leaf_to_string(leaf, buf, size);
127}
128EXPORT_SYMBOL(fw_csr_string);
119 129
130static void get_ids(const u32 *directory, int *id)
131{
132 struct fw_csr_iterator ci;
120 int key, value; 133 int key, value;
121 int vendor = 0;
122 int model = 0;
123 int specifier_id = 0;
124 int version = 0;
125 134
126 fw_csr_iterator_init(&ci, &device->config_rom[5]); 135 fw_csr_iterator_init(&ci, directory);
127 while (fw_csr_iterator_next(&ci, &key, &value)) { 136 while (fw_csr_iterator_next(&ci, &key, &value)) {
128 switch (key) { 137 switch (key) {
129 case CSR_VENDOR: 138 case CSR_VENDOR: id[0] = value; break;
130 vendor = value; 139 case CSR_MODEL: id[1] = value; break;
131 break; 140 case CSR_SPECIFIER_ID: id[2] = value; break;
132 case CSR_MODEL: 141 case CSR_VERSION: id[3] = value; break;
133 model = value;
134 break;
135 } 142 }
136 } 143 }
144}
137 145
138 fw_csr_iterator_init(&ci, unit->directory); 146static void get_modalias_ids(struct fw_unit *unit, int *id)
139 while (fw_csr_iterator_next(&ci, &key, &value)) { 147{
140 switch (key) { 148 get_ids(&fw_parent_device(unit)->config_rom[5], id);
141 case CSR_SPECIFIER_ID: 149 get_ids(unit->directory, id);
142 specifier_id = value; 150}
143 break; 151
144 case CSR_VERSION: 152static bool match_ids(const struct ieee1394_device_id *id_table, int *id)
145 version = value; 153{
146 break; 154 int match = 0;
147 } 155
148 } 156 if (id[0] == id_table->vendor_id)
157 match |= IEEE1394_MATCH_VENDOR_ID;
158 if (id[1] == id_table->model_id)
159 match |= IEEE1394_MATCH_MODEL_ID;
160 if (id[2] == id_table->specifier_id)
161 match |= IEEE1394_MATCH_SPECIFIER_ID;
162 if (id[3] == id_table->version)
163 match |= IEEE1394_MATCH_VERSION;
164
165 return (match & id_table->match_flags) == id_table->match_flags;
166}
167
168static bool is_fw_unit(struct device *dev);
169
170static int fw_unit_match(struct device *dev, struct device_driver *drv)
171{
172 const struct ieee1394_device_id *id_table =
173 container_of(drv, struct fw_driver, driver)->id_table;
174 int id[] = {0, 0, 0, 0};
175
176 /* We only allow binding to fw_units. */
177 if (!is_fw_unit(dev))
178 return 0;
179
180 get_modalias_ids(fw_unit(dev), id);
181
182 for (; id_table->match_flags != 0; id_table++)
183 if (match_ids(id_table, id))
184 return 1;
185
186 return 0;
187}
188
189static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
190{
191 int id[] = {0, 0, 0, 0};
192
193 get_modalias_ids(unit, id);
149 194
150 return snprintf(buffer, buffer_size, 195 return snprintf(buffer, buffer_size,
151 "ieee1394:ven%08Xmo%08Xsp%08Xver%08X", 196 "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
152 vendor, model, specifier_id, version); 197 id[0], id[1], id[2], id[3]);
153} 198}
154 199
155static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) 200static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -195,7 +240,7 @@ static ssize_t show_immediate(struct device *dev,
195 struct config_rom_attribute *attr = 240 struct config_rom_attribute *attr =
196 container_of(dattr, struct config_rom_attribute, attr); 241 container_of(dattr, struct config_rom_attribute, attr);
197 struct fw_csr_iterator ci; 242 struct fw_csr_iterator ci;
198 u32 *dir; 243 const u32 *dir;
199 int key, value, ret = -ENOENT; 244 int key, value, ret = -ENOENT;
200 245
201 down_read(&fw_device_rwsem); 246 down_read(&fw_device_rwsem);
@@ -226,10 +271,10 @@ static ssize_t show_text_leaf(struct device *dev,
226{ 271{
227 struct config_rom_attribute *attr = 272 struct config_rom_attribute *attr =
228 container_of(dattr, struct config_rom_attribute, attr); 273 container_of(dattr, struct config_rom_attribute, attr);
229 struct fw_csr_iterator ci; 274 const u32 *dir;
230 u32 *dir, *block = NULL, *p, *end; 275 size_t bufsize;
231 int length, key, value, last_key = 0, ret = -ENOENT; 276 char dummy_buf[2];
232 char *b; 277 int ret;
233 278
234 down_read(&fw_device_rwsem); 279 down_read(&fw_device_rwsem);
235 280
@@ -238,40 +283,23 @@ static ssize_t show_text_leaf(struct device *dev,
238 else 283 else
239 dir = fw_device(dev)->config_rom + 5; 284 dir = fw_device(dev)->config_rom + 5;
240 285
241 fw_csr_iterator_init(&ci, dir); 286 if (buf) {
242 while (fw_csr_iterator_next(&ci, &key, &value)) { 287 bufsize = PAGE_SIZE - 1;
243 if (attr->key == last_key && 288 } else {
244 key == (CSR_DESCRIPTOR | CSR_LEAF)) 289 buf = dummy_buf;
245 block = ci.p - 1 + value; 290 bufsize = 1;
246 last_key = key;
247 } 291 }
248 292
249 if (block == NULL) 293 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 294
260 if (buf == NULL) { 295 if (ret >= 0) {
261 ret = length * 4; 296 /* Strip trailing whitespace and add newline. */
262 goto out; 297 while (ret > 0 && isspace(buf[ret - 1]))
298 ret--;
299 strcpy(buf + ret, "\n");
300 ret++;
263 } 301 }
264 302
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); 303 up_read(&fw_device_rwsem);
276 304
277 return ret; 305 return ret;
@@ -371,7 +399,7 @@ static ssize_t guid_show(struct device *dev,
371 return ret; 399 return ret;
372} 400}
373 401
374static int units_sprintf(char *buf, u32 *directory) 402static int units_sprintf(char *buf, const u32 *directory)
375{ 403{
376 struct fw_csr_iterator ci; 404 struct fw_csr_iterator ci;
377 int key, value; 405 int key, value;
@@ -441,28 +469,29 @@ static int read_rom(struct fw_device *device,
441 return rcode; 469 return rcode;
442} 470}
443 471
444#define READ_BIB_ROM_SIZE 256 472#define MAX_CONFIG_ROM_SIZE 256
445#define READ_BIB_STACK_SIZE 16
446 473
447/* 474/*
448 * Read the bus info block, perform a speed probe, and read all of the rest of 475 * 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 476 * 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. 477 * 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 478 * 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. 479 * are reading the ROM may have changed the ROM during the reset.
453 */ 480 */
454static int read_bus_info_block(struct fw_device *device, int generation) 481static int read_config_rom(struct fw_device *device, int generation)
455{ 482{
456 u32 *rom, *stack, *old_rom, *new_rom; 483 const u32 *old_rom, *new_rom;
484 u32 *rom, *stack;
457 u32 sp, key; 485 u32 sp, key;
458 int i, end, length, ret = -1; 486 int i, end, length, ret = -1;
459 487
460 rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE + 488 rom = kmalloc(sizeof(*rom) * MAX_CONFIG_ROM_SIZE +
461 sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL); 489 sizeof(*stack) * MAX_CONFIG_ROM_SIZE, GFP_KERNEL);
462 if (rom == NULL) 490 if (rom == NULL)
463 return -ENOMEM; 491 return -ENOMEM;
464 492
465 stack = &rom[READ_BIB_ROM_SIZE]; 493 stack = &rom[MAX_CONFIG_ROM_SIZE];
494 memset(rom, 0, sizeof(*rom) * MAX_CONFIG_ROM_SIZE);
466 495
467 device->max_speed = SCODE_100; 496 device->max_speed = SCODE_100;
468 497
@@ -529,40 +558,54 @@ static int read_bus_info_block(struct fw_device *device, int generation)
529 */ 558 */
530 key = stack[--sp]; 559 key = stack[--sp];
531 i = key & 0xffffff; 560 i = key & 0xffffff;
532 if (i >= READ_BIB_ROM_SIZE) 561 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; 562 goto out;
538 563
539 /* Read header quadlet for the block to get the length. */ 564 /* Read header quadlet for the block to get the length. */
540 if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE) 565 if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
541 goto out; 566 goto out;
542 end = i + (rom[i] >> 16) + 1; 567 end = i + (rom[i] >> 16) + 1;
543 i++; 568 if (end > MAX_CONFIG_ROM_SIZE) {
544 if (end > READ_BIB_ROM_SIZE)
545 /* 569 /*
546 * This block extends outside standard config 570 * This block extends outside the config ROM which is
547 * area (and the array we're reading it 571 * a firmware bug. Ignore this whole block, i.e.
548 * into). That's broken, so ignore this 572 * simply set a fake block length of 0.
549 * device.
550 */ 573 */
551 goto out; 574 fw_error("skipped invalid ROM block %x at %llx\n",
575 rom[i],
576 i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
577 rom[i] = 0;
578 end = i;
579 }
580 i++;
552 581
553 /* 582 /*
554 * Now read in the block. If this is a directory 583 * Now read in the block. If this is a directory
555 * block, check the entries as we read them to see if 584 * block, check the entries as we read them to see if
556 * it references another block, and push it in that case. 585 * it references another block, and push it in that case.
557 */ 586 */
558 while (i < end) { 587 for (; i < end; i++) {
559 if (read_rom(device, generation, i, &rom[i]) != 588 if (read_rom(device, generation, i, &rom[i]) !=
560 RCODE_COMPLETE) 589 RCODE_COMPLETE)
561 goto out; 590 goto out;
562 if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && 591
563 sp < READ_BIB_STACK_SIZE) 592 if ((key >> 30) != 3 || (rom[i] >> 30) < 2)
564 stack[sp++] = i + rom[i]; 593 continue;
565 i++; 594 /*
595 * Offset points outside the ROM. May be a firmware
596 * bug or an Extended ROM entry (IEEE 1212-2001 clause
597 * 7.7.18). Simply overwrite this pointer here by a
598 * fake immediate entry so that later iterators over
599 * the ROM don't have to check offsets all the time.
600 */
601 if (i + (rom[i] & 0xffffff) >= MAX_CONFIG_ROM_SIZE) {
602 fw_error("skipped unsupported ROM entry %x at %llx\n",
603 rom[i],
604 i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
605 rom[i] = 0;
606 continue;
607 }
608 stack[sp++] = i + rom[i];
566 } 609 }
567 if (length < i) 610 if (length < i)
568 length = i; 611 length = i;
@@ -762,9 +805,9 @@ static int update_unit(struct device *dev, void *data)
762 struct fw_driver *driver = (struct fw_driver *)dev->driver; 805 struct fw_driver *driver = (struct fw_driver *)dev->driver;
763 806
764 if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { 807 if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) {
765 down(&dev->sem); 808 device_lock(dev);
766 driver->update(unit); 809 driver->update(unit);
767 up(&dev->sem); 810 device_unlock(dev);
768 } 811 }
769 812
770 return 0; 813 return 0;
@@ -905,7 +948,7 @@ static void fw_device_init(struct work_struct *work)
905 * device. 948 * device.
906 */ 949 */
907 950
908 if (read_bus_info_block(device, device->generation) < 0) { 951 if (read_config_rom(device, device->generation) < 0) {
909 if (device->config_rom_retries < MAX_RETRIES && 952 if (device->config_rom_retries < MAX_RETRIES &&
910 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 953 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
911 device->config_rom_retries++; 954 device->config_rom_retries++;
@@ -1022,7 +1065,7 @@ enum {
1022}; 1065};
1023 1066
1024/* Reread and compare bus info block and header of root directory */ 1067/* Reread and compare bus info block and header of root directory */
1025static int reread_bus_info_block(struct fw_device *device, int generation) 1068static int reread_config_rom(struct fw_device *device, int generation)
1026{ 1069{
1027 u32 q; 1070 u32 q;
1028 int i; 1071 int i;
@@ -1048,7 +1091,7 @@ static void fw_device_refresh(struct work_struct *work)
1048 struct fw_card *card = device->card; 1091 struct fw_card *card = device->card;
1049 int node_id = device->node_id; 1092 int node_id = device->node_id;
1050 1093
1051 switch (reread_bus_info_block(device, device->generation)) { 1094 switch (reread_config_rom(device, device->generation)) {
1052 case REREAD_BIB_ERROR: 1095 case REREAD_BIB_ERROR:
1053 if (device->config_rom_retries < MAX_RETRIES / 2 && 1096 if (device->config_rom_retries < MAX_RETRIES / 2 &&
1054 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 1097 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
@@ -1082,7 +1125,7 @@ static void fw_device_refresh(struct work_struct *work)
1082 */ 1125 */
1083 device_for_each_child(&device->device, NULL, shutdown_unit); 1126 device_for_each_child(&device->device, NULL, shutdown_unit);
1084 1127
1085 if (read_bus_info_block(device, device->generation) < 0) { 1128 if (read_config_rom(device, device->generation) < 0) {
1086 if (device->config_rom_retries < MAX_RETRIES && 1129 if (device->config_rom_retries < MAX_RETRIES &&
1087 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 1130 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
1088 device->config_rom_retries++; 1131 device->config_rom_retries++;