diff options
| -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); |
