aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2007-06-10 15:31:36 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-07-09 18:07:43 -0400
commitf1397490017e337446c6a8b0562b584679a604a6 (patch)
tree073c65b0fe78e02b529285ec1bffe5a5c7612e69
parent24d40125f1f59a6de9d9e6e046676bd60532596c (diff)
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>
-rw-r--r--drivers/firewire/fw-cdev.c2
-rw-r--r--drivers/firewire/fw-device.c38
-rw-r--r--drivers/firewire/fw-device.h1
-rw-r--r--drivers/firewire/fw-sbp2.c7
-rw-r--r--drivers/firewire/fw-topology.h13
5 files changed, 45 insertions, 16 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index dbb76427d529..75388641a7d3 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -397,7 +397,7 @@ static int ioctl_send_request(struct client *client, void *buffer)
397 request->tcode & 0x1f, 397 request->tcode & 0x1f,
398 device->node->node_id, 398 device->node->node_id,
399 request->generation, 399 request->generation,
400 device->node->max_speed, 400 device->max_speed,
401 request->offset, 401 request->offset,
402 response->response.data, request->length, 402 response->response.data, request->length,
403 complete_transaction, response); 403 complete_transaction, response);
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index c1ce465d9710..2b6586341635 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -401,8 +401,7 @@ static int read_rom(struct fw_device *device, int index, u32 * data)
401 401
402 offset = 0xfffff0000400ULL + index * 4; 402 offset = 0xfffff0000400ULL + index * 4;
403 fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST, 403 fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
404 device->node_id, 404 device->node_id, device->generation, device->max_speed,
405 device->generation, SCODE_100,
406 offset, NULL, 4, complete_transaction, &callback_data); 405 offset, NULL, 4, complete_transaction, &callback_data);
407 406
408 wait_for_completion(&callback_data.done); 407 wait_for_completion(&callback_data.done);
@@ -418,6 +417,8 @@ static int read_bus_info_block(struct fw_device *device)
418 u32 stack[16], sp, key; 417 u32 stack[16], sp, key;
419 int i, end, length; 418 int i, end, length;
420 419
420 device->max_speed = SCODE_100;
421
421 /* First read the bus info block. */ 422 /* First read the bus info block. */
422 for (i = 0; i < 5; i++) { 423 for (i = 0; i < 5; i++) {
423 if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) 424 if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
@@ -434,6 +435,33 @@ static int read_bus_info_block(struct fw_device *device)
434 return -1; 435 return -1;
435 } 436 }
436 437
438 device->max_speed = device->node->max_speed;
439
440 /*
441 * Determine the speed of
442 * - devices with link speed less than PHY speed,
443 * - devices with 1394b PHY (unless only connected to 1394a PHYs),
444 * - all devices if there are 1394b repeaters.
445 * Note, we cannot use the bus info block's link_spd as starting point
446 * because some buggy firmwares set it lower than necessary and because
447 * 1394-1995 nodes do not have the field.
448 */
449 if ((rom[2] & 0x7) < device->max_speed ||
450 device->max_speed == SCODE_BETA ||
451 device->card->beta_repeaters_present) {
452 u32 dummy;
453
454 /* for S1600 and S3200 */
455 if (device->max_speed == SCODE_BETA)
456 device->max_speed = device->card->link_speed;
457
458 while (device->max_speed > SCODE_100) {
459 if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
460 break;
461 device->max_speed--;
462 }
463 }
464
437 /* 465 /*
438 * Now parse the config rom. The config rom is a recursive 466 * Now parse the config rom. The config rom is a recursive
439 * directory structure so we parse it using a stack of 467 * directory structure so we parse it using a stack of
@@ -680,8 +708,10 @@ static void fw_device_init(struct work_struct *work)
680 FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) 708 FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
681 fw_device_shutdown(&device->work.work); 709 fw_device_shutdown(&device->work.work);
682 else 710 else
683 fw_notify("created new fw device %s (%d config rom retries)\n", 711 fw_notify("created new fw device %s "
684 device->device.bus_id, device->config_rom_retries); 712 "(%d config rom retries, S%d00)\n",
713 device->device.bus_id, device->config_rom_retries,
714 1 << device->max_speed);
685 715
686 /* 716 /*
687 * Reschedule the IRM work if we just finished reading the 717 * Reschedule the IRM work if we just finished reading the
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index af1723eae4ba..d13e6a69707f 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -40,6 +40,7 @@ struct fw_device {
40 struct fw_node *node; 40 struct fw_node *node;
41 int node_id; 41 int node_id;
42 int generation; 42 int generation;
43 unsigned max_speed;
43 struct fw_card *card; 44 struct fw_card *card;
44 struct device device; 45 struct device device;
45 struct list_head link; 46 struct list_head link;
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 16e942f72e48..851c2da060d2 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -346,8 +346,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
346 spin_unlock_irqrestore(&device->card->lock, flags); 346 spin_unlock_irqrestore(&device->card->lock, flags);
347 347
348 fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, 348 fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
349 node_id, generation, 349 node_id, generation, device->max_speed, offset,
350 device->node->max_speed, offset,
351 &orb->pointer, sizeof(orb->pointer), 350 &orb->pointer, sizeof(orb->pointer),
352 complete_transaction, orb); 351 complete_transaction, orb);
353} 352}
@@ -1018,8 +1017,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
1018 * if we set this to max_speed + 7, we get the right value. 1017 * if we set this to max_speed + 7, we get the right value.
1019 */ 1018 */
1020 orb->request.misc = 1019 orb->request.misc =
1021 COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) | 1020 COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
1022 COMMAND_ORB_SPEED(device->node->max_speed) | 1021 COMMAND_ORB_SPEED(device->max_speed) |
1023 COMMAND_ORB_NOTIFY; 1022 COMMAND_ORB_NOTIFY;
1024 1023
1025 if (cmd->sc_data_direction == DMA_FROM_DEVICE) 1024 if (cmd->sc_data_direction == DMA_FROM_DEVICE)
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index aced9f7db358..da61ec09183e 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -29,19 +29,18 @@ enum {
29 29
30struct fw_port { 30struct fw_port {
31 struct fw_node *node; 31 struct fw_node *node;
32 unsigned speed : 3; /* S100, S200, ... S3200 */
33}; 32};
34 33
35struct fw_node { 34struct fw_node {
36 u16 node_id; 35 u16 node_id;
37 u8 color; 36 u8 color;
38 u8 port_count; 37 u8 port_count;
39 unsigned link_on : 1; 38 u8 link_on : 1;
40 unsigned initiated_reset : 1; 39 u8 initiated_reset : 1;
41 unsigned b_path : 1; 40 u8 b_path : 1;
42 u8 phy_speed : 3; /* As in the self ID packet. */ 41 u8 phy_speed : 2; /* As in the self ID packet. */
43 u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on 42 u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
44 * the path from the local node to this node. */ 43 * local node to this node. */
45 u8 max_depth : 4; /* Maximum depth to any leaf node */ 44 u8 max_depth : 4; /* Maximum depth to any leaf node */
46 u8 max_hops : 4; /* Max hops in this sub tree */ 45 u8 max_hops : 4; /* Max hops in this sub tree */
47 atomic_t ref_count; 46 atomic_t ref_count;