diff options
| -rw-r--r-- | drivers/firewire/fw-device.c | 41 |
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 | */ |
| 410 | static int read_bus_info_block(struct fw_device *device, int generation) | 413 | static 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 | ||
| 529 | static void fw_unit_release(struct device *dev) | 542 | static void fw_unit_release(struct device *dev) |
