aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2008-03-02 13:35:42 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2008-04-18 11:55:35 -0400
commit1dadff71d6356ebb804c3f4f1d3049247e16111c (patch)
tree103cab576092528c4820436028ac6cc3bfbc5652 /drivers
parentd34316a4bdcd4fef050da584401c7f4ed22482f2 (diff)
firewire: replace static ROM cache by allocated cache
read_bus_info_block() is repeatedly called by workqueue jobs. These will step on each others toes eventually if there are multiple workqueue threads, and we end up with corrupt config ROM images. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/firewire/fw-device.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index 870125a3638e..20ac9a5afc37 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -400,6 +400,9 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
400 return callback_data.rcode; 400 return callback_data.rcode;
401} 401}
402 402
403#define READ_BIB_ROM_SIZE 256
404#define READ_BIB_STACK_SIZE 16
405
403/* 406/*
404 * Read the bus info block, perform a speed probe, and read all of the rest of 407 * Read the bus info block, perform a speed probe, and read all of the rest of
405 * the config ROM. We do all this with a cached bus generation. If the bus 408 * the config ROM. We do all this with a cached bus generation. If the bus
@@ -409,16 +412,23 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
409 */ 412 */
410static int read_bus_info_block(struct fw_device *device, int generation) 413static int read_bus_info_block(struct fw_device *device, int generation)
411{ 414{
412 static u32 rom[256]; 415 u32 *rom, *stack;
413 u32 stack[16], sp, key; 416 u32 sp, key;
414 int i, end, length; 417 int i, end, length, ret = -1;
418
419 rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
420 sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
421 if (rom == NULL)
422 return -ENOMEM;
423
424 stack = &rom[READ_BIB_ROM_SIZE];
415 425
416 device->max_speed = SCODE_100; 426 device->max_speed = SCODE_100;
417 427
418 /* First read the bus info block. */ 428 /* First read the bus info block. */
419 for (i = 0; i < 5; i++) { 429 for (i = 0; i < 5; i++) {
420 if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE) 430 if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
421 return -1; 431 goto out;
422 /* 432 /*
423 * As per IEEE1212 7.2, during power-up, devices can 433 * As per IEEE1212 7.2, during power-up, devices can
424 * reply with a 0 for the first quadlet of the config 434 * reply with a 0 for the first quadlet of the config
@@ -428,7 +438,7 @@ static int read_bus_info_block(struct fw_device *device, int generation)
428 * retry mechanism will try again later. 438 * retry mechanism will try again later.
429 */ 439 */
430 if (i == 0 && rom[i] == 0) 440 if (i == 0 && rom[i] == 0)
431 return -1; 441 goto out;
432 } 442 }
433 443
434 device->max_speed = device->node->max_speed; 444 device->max_speed = device->node->max_speed;
@@ -478,26 +488,26 @@ static int read_bus_info_block(struct fw_device *device, int generation)
478 */ 488 */
479 key = stack[--sp]; 489 key = stack[--sp];
480 i = key & 0xffffff; 490 i = key & 0xffffff;
481 if (i >= ARRAY_SIZE(rom)) 491 if (i >= READ_BIB_ROM_SIZE)
482 /* 492 /*
483 * The reference points outside the standard 493 * The reference points outside the standard
484 * config rom area, something's fishy. 494 * config rom area, something's fishy.
485 */ 495 */
486 return -1; 496 goto out;
487 497
488 /* Read header quadlet for the block to get the length. */ 498 /* Read header quadlet for the block to get the length. */
489 if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE) 499 if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
490 return -1; 500 goto out;
491 end = i + (rom[i] >> 16) + 1; 501 end = i + (rom[i] >> 16) + 1;
492 i++; 502 i++;
493 if (end > ARRAY_SIZE(rom)) 503 if (end > READ_BIB_ROM_SIZE)
494 /* 504 /*
495 * This block extends outside standard config 505 * This block extends outside standard config
496 * area (and the array we're reading it 506 * area (and the array we're reading it
497 * into). That's broken, so ignore this 507 * into). That's broken, so ignore this
498 * device. 508 * device.
499 */ 509 */
500 return -1; 510 goto out;
501 511
502 /* 512 /*
503 * Now read in the block. If this is a directory 513 * Now read in the block. If this is a directory
@@ -507,9 +517,9 @@ static int read_bus_info_block(struct fw_device *device, int generation)
507 while (i < end) { 517 while (i < end) {
508 if (read_rom(device, generation, i, &rom[i]) != 518 if (read_rom(device, generation, i, &rom[i]) !=
509 RCODE_COMPLETE) 519 RCODE_COMPLETE)
510 return -1; 520 goto out;
511 if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && 521 if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
512 sp < ARRAY_SIZE(stack)) 522 sp < READ_BIB_STACK_SIZE)
513 stack[sp++] = i + rom[i]; 523 stack[sp++] = i + rom[i];
514 i++; 524 i++;
515 } 525 }
@@ -519,11 +529,14 @@ static int read_bus_info_block(struct fw_device *device, int generation)
519 529
520 device->config_rom = kmalloc(length * 4, GFP_KERNEL); 530 device->config_rom = kmalloc(length * 4, GFP_KERNEL);
521 if (device->config_rom == NULL) 531 if (device->config_rom == NULL)
522 return -1; 532 goto out;
523 memcpy(device->config_rom, rom, length * 4); 533 memcpy(device->config_rom, rom, length * 4);
524 device->config_rom_length = length; 534 device->config_rom_length = length;
535 ret = 0;
536 out:
537 kfree(rom);
525 538
526 return 0; 539 return ret;
527} 540}
528 541
529static void fw_unit_release(struct device *dev) 542static void fw_unit_release(struct device *dev)