firewire: support S100B...S400B and link slower than PHY
Use a speed probe to determine the speed over 1394b buses and of nodes
which report a link speed less than their PHY speed.
Log the effective maximum speed of newly created nodes in dmesg.
Also, read the config ROM (except bus info block) at the maximum speed
rather than S100. This isn't a real optimization though because we
still only use quadlet read requests for the entire ROM.
The patch also adds support for S1600 and S3200, although such hardware
does not exist yet.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index c1ce465..2b65863 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -401,8 +401,7 @@
offset = 0xfffff0000400ULL + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
- device->node_id,
- device->generation, SCODE_100,
+ device->node_id, device->generation, device->max_speed,
offset, NULL, 4, complete_transaction, &callback_data);
wait_for_completion(&callback_data.done);
@@ -418,6 +417,8 @@
u32 stack[16], sp, key;
int i, end, length;
+ device->max_speed = SCODE_100;
+
/* First read the bus info block. */
for (i = 0; i < 5; i++) {
if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
@@ -434,6 +435,33 @@
return -1;
}
+ device->max_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) < device->max_speed ||
+ device->max_speed == SCODE_BETA ||
+ device->card->beta_repeaters_present) {
+ u32 dummy;
+
+ /* for S1600 and S3200 */
+ if (device->max_speed == SCODE_BETA)
+ device->max_speed = device->card->link_speed;
+
+ while (device->max_speed > SCODE_100) {
+ if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
+ break;
+ device->max_speed--;
+ }
+ }
+
/*
* Now parse the config rom. The config rom is a recursive
* directory structure so we parse it using a stack of
@@ -680,8 +708,10 @@
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
fw_device_shutdown(&device->work.work);
else
- fw_notify("created new fw device %s (%d config rom retries)\n",
- device->device.bus_id, device->config_rom_retries);
+ fw_notify("created new fw device %s "
+ "(%d config rom retries, S%d00)\n",
+ device->device.bus_id, device->config_rom_retries,
+ 1 << device->max_speed);
/*
* Reschedule the IRM work if we just finished reading the