diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/fw-device.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 872df2238609..de9066e69adf 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c | |||
@@ -390,12 +390,12 @@ complete_transaction(struct fw_card *card, int rcode, | |||
390 | complete(&callback_data->done); | 390 | complete(&callback_data->done); |
391 | } | 391 | } |
392 | 392 | ||
393 | static int read_rom(struct fw_device *device, int index, u32 * data) | 393 | static int |
394 | read_rom(struct fw_device *device, int generation, int index, u32 *data) | ||
394 | { | 395 | { |
395 | struct read_quadlet_callback_data callback_data; | 396 | struct read_quadlet_callback_data callback_data; |
396 | struct fw_transaction t; | 397 | struct fw_transaction t; |
397 | u64 offset; | 398 | u64 offset; |
398 | int generation = device->generation; | ||
399 | 399 | ||
400 | /* device->node_id, accessed below, must not be older than generation */ | 400 | /* device->node_id, accessed below, must not be older than generation */ |
401 | smp_rmb(); | 401 | smp_rmb(); |
@@ -414,7 +414,14 @@ static int read_rom(struct fw_device *device, int index, u32 * data) | |||
414 | return callback_data.rcode; | 414 | return callback_data.rcode; |
415 | } | 415 | } |
416 | 416 | ||
417 | static int read_bus_info_block(struct fw_device *device) | 417 | /* |
418 | * Read the bus info block, perform a speed probe, and read all of the rest of | ||
419 | * the config ROM. We do all this with a cached bus generation. If the bus | ||
420 | * generation changes under us, read_bus_info_block will fail and get retried. | ||
421 | * It's better to start all over in this case because the node from which we | ||
422 | * are reading the ROM may have changed the ROM during the reset. | ||
423 | */ | ||
424 | static int read_bus_info_block(struct fw_device *device, int generation) | ||
418 | { | 425 | { |
419 | static u32 rom[256]; | 426 | static u32 rom[256]; |
420 | u32 stack[16], sp, key; | 427 | u32 stack[16], sp, key; |
@@ -424,7 +431,7 @@ static int read_bus_info_block(struct fw_device *device) | |||
424 | 431 | ||
425 | /* First read the bus info block. */ | 432 | /* First read the bus info block. */ |
426 | for (i = 0; i < 5; i++) { | 433 | for (i = 0; i < 5; i++) { |
427 | if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) | 434 | if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE) |
428 | return -1; | 435 | return -1; |
429 | /* | 436 | /* |
430 | * As per IEEE1212 7.2, during power-up, devices can | 437 | * As per IEEE1212 7.2, during power-up, devices can |
@@ -459,7 +466,8 @@ static int read_bus_info_block(struct fw_device *device) | |||
459 | device->max_speed = device->card->link_speed; | 466 | device->max_speed = device->card->link_speed; |
460 | 467 | ||
461 | while (device->max_speed > SCODE_100) { | 468 | while (device->max_speed > SCODE_100) { |
462 | if (read_rom(device, 0, &dummy) == RCODE_COMPLETE) | 469 | if (read_rom(device, generation, 0, &dummy) == |
470 | RCODE_COMPLETE) | ||
463 | break; | 471 | break; |
464 | device->max_speed--; | 472 | device->max_speed--; |
465 | } | 473 | } |
@@ -492,7 +500,7 @@ static int read_bus_info_block(struct fw_device *device) | |||
492 | return -1; | 500 | return -1; |
493 | 501 | ||
494 | /* Read header quadlet for the block to get the length. */ | 502 | /* Read header quadlet for the block to get the length. */ |
495 | if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) | 503 | if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE) |
496 | return -1; | 504 | return -1; |
497 | end = i + (rom[i] >> 16) + 1; | 505 | end = i + (rom[i] >> 16) + 1; |
498 | i++; | 506 | i++; |
@@ -511,7 +519,8 @@ static int read_bus_info_block(struct fw_device *device) | |||
511 | * it references another block, and push it in that case. | 519 | * it references another block, and push it in that case. |
512 | */ | 520 | */ |
513 | while (i < end) { | 521 | while (i < end) { |
514 | if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) | 522 | if (read_rom(device, generation, i, &rom[i]) != |
523 | RCODE_COMPLETE) | ||
515 | return -1; | 524 | return -1; |
516 | if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && | 525 | if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && |
517 | sp < ARRAY_SIZE(stack)) | 526 | sp < ARRAY_SIZE(stack)) |
@@ -658,7 +667,7 @@ static void fw_device_init(struct work_struct *work) | |||
658 | * device. | 667 | * device. |
659 | */ | 668 | */ |
660 | 669 | ||
661 | if (read_bus_info_block(device) < 0) { | 670 | if (read_bus_info_block(device, device->generation) < 0) { |
662 | if (device->config_rom_retries < MAX_RETRIES) { | 671 | if (device->config_rom_retries < MAX_RETRIES) { |
663 | device->config_rom_retries++; | 672 | device->config_rom_retries++; |
664 | schedule_delayed_work(&device->work, RETRY_DELAY); | 673 | schedule_delayed_work(&device->work, RETRY_DELAY); |