diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2005-12-05 16:28:59 -0500 |
---|---|---|
committer | Jody McIntyre <scjody@modernduck.com> | 2005-12-05 16:28:59 -0500 |
commit | 61c7f775ca25ccfc0e51486103a724fb1a3a08f2 (patch) | |
tree | 90bbd7f117a3831f3bb38ca9bc512de039062f2f /drivers/ieee1394 | |
parent | c4fc108a8275f5eb77c9859725643a6870d20ef6 (diff) |
ieee1394: write broadcast_channel only to select nodes (fixes device recognition)
Some old 1394-1995 SBP-2 bridges would hang if they received a broadcast write
request to BROADCAST_CHANNEL before the config ROM was read. Affected devices
include Datafab MD2-FW2 2.5" HDD and SmartDisk VST FWCDRW-V8 portable CD writer.
The write request is now directed to specific nodes instead of being broadcast
to all nodes at once, and it is only performed if a previous read request at
this register succeeded.
Fixes an old interoperability problem which was perceived as a 2.6.14-specific
regression: http://marc.theaimsgroup.com/?t=113190586800003
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Jody McIntyre <scjody@modernduck.com>
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/nodemgr.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index f4b6025fde61..01ab2bfa8d9d 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -1346,6 +1346,33 @@ static void nodemgr_update_pdrv(struct node_entry *ne) | |||
1346 | } | 1346 | } |
1347 | 1347 | ||
1348 | 1348 | ||
1349 | /* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3. This | ||
1350 | * seems like an optional service but in the end it is practically mandatory | ||
1351 | * as a consequence of these clauses. | ||
1352 | * | ||
1353 | * Note that we cannot do a broadcast write to all nodes at once because some | ||
1354 | * pre-1394a devices would hang. */ | ||
1355 | static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) | ||
1356 | { | ||
1357 | const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL); | ||
1358 | quadlet_t bc_remote, bc_local; | ||
1359 | int ret; | ||
1360 | |||
1361 | if (!ne->host->is_irm || ne->generation != generation || | ||
1362 | ne->nodeid == ne->host->node_id) | ||
1363 | return; | ||
1364 | |||
1365 | bc_local = cpu_to_be32(ne->host->csr.broadcast_channel); | ||
1366 | |||
1367 | /* Check if the register is implemented and 1394a compliant. */ | ||
1368 | ret = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote, | ||
1369 | sizeof(bc_remote)); | ||
1370 | if (!ret && bc_remote & cpu_to_be32(0x80000000) && | ||
1371 | bc_remote != bc_local) | ||
1372 | hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local)); | ||
1373 | } | ||
1374 | |||
1375 | |||
1349 | static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) | 1376 | static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) |
1350 | { | 1377 | { |
1351 | struct device *dev; | 1378 | struct device *dev; |
@@ -1357,6 +1384,8 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge | |||
1357 | if (!dev) | 1384 | if (!dev) |
1358 | return; | 1385 | return; |
1359 | 1386 | ||
1387 | nodemgr_irm_write_bc(ne, generation); | ||
1388 | |||
1360 | /* If "needs_probe", then this is either a new or changed node we | 1389 | /* If "needs_probe", then this is either a new or changed node we |
1361 | * rescan totally. If the generation matches for an existing node | 1390 | * rescan totally. If the generation matches for an existing node |
1362 | * (one that existed prior to the bus reset) we send update calls | 1391 | * (one that existed prior to the bus reset) we send update calls |
@@ -1429,9 +1458,7 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host) | |||
1429 | return ret; | 1458 | return ret; |
1430 | } | 1459 | } |
1431 | 1460 | ||
1432 | /* Because we are a 1394a-2000 compliant IRM, we need to inform all the other | 1461 | /* Perform a few high-level IRM responsibilities. */ |
1433 | * nodes of the broadcast channel. (Really we're only setting the validity | ||
1434 | * bit). Other IRM responsibilities go in here as well. */ | ||
1435 | static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) | 1462 | static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) |
1436 | { | 1463 | { |
1437 | quadlet_t bc; | 1464 | quadlet_t bc; |
@@ -1440,13 +1467,8 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) | |||
1440 | if (!host->is_irm || host->irm_id == (nodeid_t)-1) | 1467 | if (!host->is_irm || host->irm_id == (nodeid_t)-1) |
1441 | return 1; | 1468 | return 1; |
1442 | 1469 | ||
1443 | host->csr.broadcast_channel |= 0x40000000; /* set validity bit */ | 1470 | /* We are a 1394a-2000 compliant IRM. Set the validity bit. */ |
1444 | 1471 | host->csr.broadcast_channel |= 0x40000000; | |
1445 | bc = cpu_to_be32(host->csr.broadcast_channel); | ||
1446 | |||
1447 | hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host), | ||
1448 | (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), | ||
1449 | &bc, sizeof(quadlet_t)); | ||
1450 | 1472 | ||
1451 | /* If there is no bus manager then we should set the root node's | 1473 | /* If there is no bus manager then we should set the root node's |
1452 | * force_root bit to promote bus stability per the 1394 | 1474 | * force_root bit to promote bus stability per the 1394 |