diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-18 19:31:56 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-18 19:31:56 -0500 |
| commit | 23cb3ada1b011f708ff881b66b2cfb6c11068fa5 (patch) | |
| tree | c2413fe7180f480b4ecdfd91bdfc0f23ff7df8a5 | |
| parent | 27f4e0834746196f219e3e030ca71ffd3b176483 (diff) | |
| parent | 16e842a62a8ffcc2e51def6ef9fd6e0926539bc5 (diff) | |
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394
| -rw-r--r-- | drivers/ieee1394/hosts.h | 1 | ||||
| -rw-r--r-- | drivers/ieee1394/nodemgr.c | 67 |
2 files changed, 58 insertions, 10 deletions
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 38f42112dff0..ae9b02cc013f 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h | |||
| @@ -41,6 +41,7 @@ struct hpsb_host { | |||
| 41 | /* this nodes state */ | 41 | /* this nodes state */ |
| 42 | unsigned in_bus_reset:1; | 42 | unsigned in_bus_reset:1; |
| 43 | unsigned is_shutdown:1; | 43 | unsigned is_shutdown:1; |
| 44 | unsigned resume_packet_sent:1; | ||
| 44 | 45 | ||
| 45 | /* this nodes' duties on the bus */ | 46 | /* this nodes' duties on the bus */ |
| 46 | unsigned is_root:1; | 47 | unsigned is_root:1; |
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 7fff5a1d2ea4..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 |
| @@ -1413,9 +1442,25 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) | |||
| 1413 | return; | 1442 | return; |
| 1414 | } | 1443 | } |
| 1415 | 1444 | ||
| 1416 | /* Because we are a 1394a-2000 compliant IRM, we need to inform all the other | 1445 | static int nodemgr_send_resume_packet(struct hpsb_host *host) |
| 1417 | * nodes of the broadcast channel. (Really we're only setting the validity | 1446 | { |
| 1418 | * bit). Other IRM responsibilities go in here as well. */ | 1447 | struct hpsb_packet *packet; |
| 1448 | int ret = 1; | ||
| 1449 | |||
| 1450 | packet = hpsb_make_phypacket(host, | ||
| 1451 | 0x003c0000 | NODEID_TO_NODE(host->node_id) << 24); | ||
| 1452 | if (packet) { | ||
| 1453 | packet->no_waiter = 1; | ||
| 1454 | packet->generation = get_hpsb_generation(host); | ||
| 1455 | ret = hpsb_send_packet(packet); | ||
| 1456 | } | ||
| 1457 | if (ret) | ||
| 1458 | HPSB_WARN("fw-host%d: Failed to broadcast resume packet", | ||
| 1459 | host->id); | ||
| 1460 | return ret; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | /* Perform a few high-level IRM responsibilities. */ | ||
| 1419 | 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) |
| 1420 | { | 1465 | { |
| 1421 | quadlet_t bc; | 1466 | quadlet_t bc; |
| @@ -1424,13 +1469,8 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) | |||
| 1424 | if (!host->is_irm || host->irm_id == (nodeid_t)-1) | 1469 | if (!host->is_irm || host->irm_id == (nodeid_t)-1) |
| 1425 | return 1; | 1470 | return 1; |
| 1426 | 1471 | ||
| 1427 | host->csr.broadcast_channel |= 0x40000000; /* set validity bit */ | 1472 | /* We are a 1394a-2000 compliant IRM. Set the validity bit. */ |
| 1428 | 1473 | host->csr.broadcast_channel |= 0x40000000; | |
| 1429 | bc = cpu_to_be32(host->csr.broadcast_channel); | ||
| 1430 | |||
| 1431 | hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host), | ||
| 1432 | (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), | ||
| 1433 | &bc, sizeof(quadlet_t)); | ||
| 1434 | 1474 | ||
| 1435 | /* 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 |
| 1436 | * force_root bit to promote bus stability per the 1394 | 1476 | * force_root bit to promote bus stability per the 1394 |
| @@ -1463,6 +1503,13 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) | |||
| 1463 | } | 1503 | } |
| 1464 | } | 1504 | } |
| 1465 | 1505 | ||
| 1506 | /* Some devices suspend their ports while being connected to an inactive | ||
| 1507 | * host adapter, i.e. if connected before the low-level driver is | ||
| 1508 | * loaded. They become visible either when physically unplugged and | ||
| 1509 | * replugged, or when receiving a resume packet. Send one once. */ | ||
| 1510 | if (!host->resume_packet_sent && !nodemgr_send_resume_packet(host)) | ||
| 1511 | host->resume_packet_sent = 1; | ||
| 1512 | |||
| 1466 | return 1; | 1513 | return 1; |
| 1467 | } | 1514 | } |
| 1468 | 1515 | ||
