ieee1394: resume remote ports when starting a host (fixes device recognition) After initializing an IEEE 1394 host, broadcast a resume packet. This makes remote nodes visible which suspended their ports while the host was down. Such nodes had to be unplugged and replugged in order to be recognized. Motorola DCT6200 cable reciever was affected, probably other devices too. http://marc.theaimsgroup.com/?t=113202715800001 Signed-off-by: Stefan Richter --- This patch applies to Linux 2.6.14.x as well as to Jody's for-mm branch. Probably applies to older kernels as well. Patch update: Code concentrated in a helper function, sending of packet moved past the CMC root check and reset because the bus generation could change immediately after the resume packet was sent, no_waiter is now set. Note: I will follow up with a separate patch which introduces macro definitions for the constants used in nodemgr_send_resume_packet(). Also, a whitespace fix of hosts.h is in order. hosts.h | 1 + nodemgr.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff -uprN --ignore-all-space -X linux/Documentation/dontdiff linux-2.6.14.3/drivers/ieee1394.orig/hosts.h linux-2.6.14.3/drivers/ieee1394/hosts.h --- linux-2.6.14.3/drivers/ieee1394.orig/hosts.h 2005-11-24 23:10:21.000000000 +0100 +++ linux-2.6.14.3/drivers/ieee1394/hosts.h 2005-11-30 21:10:56.000000000 +0100 @@ -41,6 +41,7 @@ struct hpsb_host { /* this nodes state */ unsigned in_bus_reset:1; unsigned is_shutdown:1; + unsigned resume_packet_sent:1; /* this nodes' duties on the bus */ unsigned is_root:1; diff -uprN --ignore-all-space -X linux/Documentation/dontdiff linux-2.6.14.3/drivers/ieee1394.orig/nodemgr.c linux-2.6.14.3/drivers/ieee1394/nodemgr.c --- linux-2.6.14.3/drivers/ieee1394.orig/nodemgr.c 2005-11-24 23:10:21.000000000 +0100 +++ linux-2.6.14.3/drivers/ieee1394/nodemgr.c 2005-11-30 21:27:48.000000000 +0100 @@ -1413,6 +1413,24 @@ static void nodemgr_node_probe(struct ho return; } +static int nodemgr_send_resume_packet(struct hpsb_host *host) +{ + struct hpsb_packet *packet; + int ret = 1; + + packet = hpsb_make_phypacket(host, + 0x003c0000 | NODEID_TO_NODE(host->node_id) << 24); + if (packet) { + packet->no_waiter = 1; + packet->generation = get_hpsb_generation(host); + ret = hpsb_send_packet(packet); + } + if (ret) + HPSB_WARN("fw-host%d: Failed to broadcast resume packet", + host->id); + return ret; +} + /* Because we are a 1394a-2000 compliant IRM, we need to inform all the other * nodes of the broadcast channel. (Really we're only setting the validity * bit). Other IRM responsibilities go in here as well. */ @@ -1463,6 +1481,13 @@ static int nodemgr_do_irm_duties(struct } } + /* Some devices suspend their ports while being connected to an inactive + * host adapter, i.e. if connected before the low-level driver is + * loaded. They become visible either when physically unplugged and + * replugged, or when receiving a resume packet. Send one once. */ + if (!host->resume_packet_sent && !nodemgr_send_resume_packet(host)) + host->resume_packet_sent = 1; + return 1; }