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-12 23:21:12 -0500 |
commit | d51e86c18a479f1dbcef3aa20e58ad04d1233016 (patch) | |
tree | c6dd3b79a4276908451d8daa8587347a03ca7f1c | |
parent | 48622b7bde008387218a416586e9d072b385f1ae (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>
(cherry picked from 61c7f775ca25ccfc0e51486103a724fb1a3a08f2 commit)
-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 f7c3dbaf5802..0ea37b1bccb2 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -1349,6 +1349,33 @@ static void nodemgr_update_pdrv(struct node_entry *ne) | |||
1349 | } | 1349 | } |
1350 | 1350 | ||
1351 | 1351 | ||
1352 | /* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3. This | ||
1353 | * seems like an optional service but in the end it is practically mandatory | ||
1354 | * as a consequence of these clauses. | ||
1355 | * | ||
1356 | * Note that we cannot do a broadcast write to all nodes at once because some | ||
1357 | * pre-1394a devices would hang. */ | ||
1358 | static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) | ||
1359 | { | ||
1360 | const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL); | ||
1361 | quadlet_t bc_remote, bc_local; | ||
1362 | int ret; | ||
1363 | |||
1364 | if (!ne->host->is_irm || ne->generation != generation || | ||
1365 | ne->nodeid == ne->host->node_id) | ||
1366 | return; | ||
1367 | |||
1368 | bc_local = cpu_to_be32(ne->host->csr.broadcast_channel); | ||
1369 | |||
1370 | /* Check if the register is implemented and 1394a compliant. */ | ||
1371 | ret = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote, | ||
1372 | sizeof(bc_remote)); | ||
1373 | if (!ret && bc_remote & cpu_to_be32(0x80000000) && | ||
1374 | bc_remote != bc_local) | ||
1375 | hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local)); | ||
1376 | } | ||
1377 | |||
1378 | |||
1352 | static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) | 1379 | static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) |
1353 | { | 1380 | { |
1354 | struct device *dev; | 1381 | struct device *dev; |
@@ -1360,6 +1387,8 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge | |||
1360 | if (!dev) | 1387 | if (!dev) |
1361 | return; | 1388 | return; |
1362 | 1389 | ||
1390 | nodemgr_irm_write_bc(ne, generation); | ||
1391 | |||
1363 | /* If "needs_probe", then this is either a new or changed node we | 1392 | /* If "needs_probe", then this is either a new or changed node we |
1364 | * rescan totally. If the generation matches for an existing node | 1393 | * rescan totally. If the generation matches for an existing node |
1365 | * (one that existed prior to the bus reset) we send update calls | 1394 | * (one that existed prior to the bus reset) we send update calls |
@@ -1431,9 +1460,7 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host) | |||
1431 | return ret; | 1460 | return ret; |
1432 | } | 1461 | } |
1433 | 1462 | ||
1434 | /* Because we are a 1394a-2000 compliant IRM, we need to inform all the other | 1463 | /* Perform a few high-level IRM responsibilities. */ |
1435 | * nodes of the broadcast channel. (Really we're only setting the validity | ||
1436 | * bit). Other IRM responsibilities go in here as well. */ | ||
1437 | static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) | 1464 | static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) |
1438 | { | 1465 | { |
1439 | quadlet_t bc; | 1466 | quadlet_t bc; |
@@ -1442,13 +1469,8 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) | |||
1442 | if (!host->is_irm || host->irm_id == (nodeid_t)-1) | 1469 | if (!host->is_irm || host->irm_id == (nodeid_t)-1) |
1443 | return 1; | 1470 | return 1; |
1444 | 1471 | ||
1445 | host->csr.broadcast_channel |= 0x40000000; /* set validity bit */ | 1472 | /* We are a 1394a-2000 compliant IRM. Set the validity bit. */ |
1446 | 1473 | host->csr.broadcast_channel |= 0x40000000; | |
1447 | bc = cpu_to_be32(host->csr.broadcast_channel); | ||
1448 | |||
1449 | hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host), | ||
1450 | (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), | ||
1451 | &bc, sizeof(quadlet_t)); | ||
1452 | 1474 | ||
1453 | /* If there is no bus manager then we should set the root node's | 1475 | /* If there is no bus manager then we should set the root node's |
1454 | * force_root bit to promote bus stability per the 1394 | 1476 | * force_root bit to promote bus stability per the 1394 |