summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2025-10-18 12:55:30 +0900
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>2025-10-18 12:58:55 +0900
commit55b4e903a156bc81e15fbe3af9be0664f7a3b3ca (patch)
tree24a25c34e290791a98d6d53e16c20b1089035704
parent665ad59b891a98e7bbd50720cc30289c5c253272 (diff)
firewire: core: determine transaction speed after detecting quirks
Current implementation determines the maximum transaction speed supported by the target device after reading bus information block of configuration ROM. The read operations for root directory block are then performed at the determined speed. However, some devices have quirks that cause issues when transactions are performed at the determined speed. In the first place, all devices are required to support the lowest speed (S100) and must respond successfully to any read request within the configuration ROM space. Therefore it is safe to postpone speed determination until the entire configuration ROM has been read. This commit moves the speed determination after reading root directory. Link: https://lore.kernel.org/r/20251018035532.287124-3-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
-rw-r--r--drivers/firewire/core-device.c53
1 files changed, 25 insertions, 28 deletions
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index c698d4ced7d7..6a5740ed4934 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -680,32 +680,6 @@ static int read_config_rom(struct fw_device *device, int generation)
// Just prevent from torn writing/reading.
WRITE_ONCE(device->quirks, quirks);
- speed = device->node->max_speed;
-
- /*
- * Determine the speed of
- * - devices with link speed less than PHY speed,
- * - devices with 1394b PHY (unless only connected to 1394a PHYs),
- * - all devices if there are 1394b repeaters.
- * Note, we cannot use the bus info block's link_spd as starting point
- * because some buggy firmwares set it lower than necessary and because
- * 1394-1995 nodes do not have the field.
- */
- if ((rom[2] & 0x7) < speed || speed == SCODE_BETA || card->beta_repeaters_present) {
- u32 dummy;
-
- /* for S1600 and S3200 */
- if (speed == SCODE_BETA)
- speed = card->link_speed;
-
- while (speed > SCODE_100) {
- if (read_rom(device, generation, speed, 0, &dummy) ==
- RCODE_COMPLETE)
- break;
- --speed;
- }
- }
-
/*
* Now parse the config rom. The config rom is a recursive
* directory structure so we parse it using a stack of
@@ -782,13 +756,36 @@ static int read_config_rom(struct fw_device *device, int generation)
length = i;
}
- device->max_speed = speed;
-
quirks |= detect_quirks_by_root_directory(rom + ROOT_DIR_OFFSET, length - ROOT_DIR_OFFSET);
// Just prevent from torn writing/reading.
WRITE_ONCE(device->quirks, quirks);
+ speed = device->node->max_speed;
+
+ // Determine the speed of
+ // - devices with link speed less than PHY speed,
+ // - devices with 1394b PHY (unless only connected to 1394a PHYs),
+ // - all devices if there are 1394b repeaters.
+ // Note, we cannot use the bus info block's link_spd as starting point because some buggy
+ // firmwares set it lower than necessary and because 1394-1995 nodes do not have the field.
+ if ((rom[2] & 0x7) < speed || speed == SCODE_BETA || card->beta_repeaters_present) {
+ u32 dummy;
+
+ // for S1600 and S3200.
+ if (speed == SCODE_BETA)
+ speed = card->link_speed;
+
+ while (speed > SCODE_100) {
+ if (read_rom(device, generation, speed, 0, &dummy) ==
+ RCODE_COMPLETE)
+ break;
+ --speed;
+ }
+ }
+
+ device->max_speed = speed;
+
old_rom = device->config_rom;
new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
if (new_rom == NULL) {