]> err.no Git - linux-2.6/blobdiff - drivers/ieee1394/nodemgr.c
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[linux-2.6] / drivers / ieee1394 / nodemgr.c
index b23322523ef57b1cf147e4368239487e55ef15bc..0ea37b1bccb27c13d1ae81392fad02c48dbd8923 100644 (file)
@@ -64,10 +64,10 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
        struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
        int i, ret = 0;
 
-       for (i = 0; i < 3; i++) {
+       for (i = 1; ; i++) {
                ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
                                buffer, length);
-               if (!ret)
+               if (!ret || i == 3)
                        break;
 
                if (msleep_interruptible(334))
@@ -1292,7 +1292,7 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
 
                if (ud->device.driver &&
                    (!ud->device.driver->suspend ||
-                     ud->device.driver->suspend(&ud->device, PMSG_SUSPEND, 0)))
+                     ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
                        device_release_driver(&ud->device);
        }
        up_write(&ne->device.bus->subsys.rwsem);
@@ -1315,7 +1315,7 @@ static void nodemgr_resume_ne(struct node_entry *ne)
                        continue;
 
                if (ud->device.driver && ud->device.driver->resume)
-                       ud->device.driver->resume(&ud->device, 0);
+                       ud->device.driver->resume(&ud->device);
        }
        up_read(&ne->device.bus->subsys.rwsem);
 
@@ -1349,6 +1349,33 @@ static void nodemgr_update_pdrv(struct node_entry *ne)
 }
 
 
+/* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3.  This
+ * seems like an optional service but in the end it is practically mandatory
+ * as a consequence of these clauses.
+ *
+ * Note that we cannot do a broadcast write to all nodes at once because some
+ * pre-1394a devices would hang. */
+static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
+{
+       const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL);
+       quadlet_t bc_remote, bc_local;
+       int ret;
+
+       if (!ne->host->is_irm || ne->generation != generation ||
+           ne->nodeid == ne->host->node_id)
+               return;
+
+       bc_local = cpu_to_be32(ne->host->csr.broadcast_channel);
+
+       /* Check if the register is implemented and 1394a compliant. */
+       ret = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
+                       sizeof(bc_remote));
+       if (!ret && bc_remote & cpu_to_be32(0x80000000) &&
+           bc_remote != bc_local)
+               hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local));
+}
+
+
 static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
 {
        struct device *dev;
@@ -1360,6 +1387,8 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
        if (!dev)
                return;
 
+       nodemgr_irm_write_bc(ne, generation);
+
        /* If "needs_probe", then this is either a new or changed node we
         * rescan totally. If the generation matches for an existing node
         * (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)
        return;
 }
 
-/* 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. */
+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;
+}
+
+/* Perform a few high-level IRM responsibilities. */
 static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
 {
        quadlet_t bc;
@@ -1424,13 +1469,8 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
        if (!host->is_irm || host->irm_id == (nodeid_t)-1)
                return 1;
 
-       host->csr.broadcast_channel |= 0x40000000;  /* set validity bit */
-
-       bc = cpu_to_be32(host->csr.broadcast_channel);
-
-       hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host),
-                  (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
-                  &bc, sizeof(quadlet_t));
+       /* We are a 1394a-2000 compliant IRM. Set the validity bit. */
+       host->csr.broadcast_channel |= 0x40000000;
 
        /* If there is no bus manager then we should set the root node's
         * force_root bit to promote bus stability per the 1394
@@ -1438,9 +1478,13 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
        if (host->busmgr_id == 0xffff && host->node_count > 1)
        {
                u16 root_node = host->node_count - 1;
-               struct node_entry *ne = find_entry_by_nodeid(host, root_node | LOCAL_BUS);
 
-               if (ne && ne->busopt.cmc)
+               /* get cycle master capability flag from root node */
+               if (host->is_cycmst ||
+                   (!hpsb_read(host, LOCAL_BUS | root_node, get_hpsb_generation(host),
+                               (CSR_REGISTER_BASE + CSR_CONFIG_ROM + 2 * sizeof(quadlet_t)),
+                               &bc, sizeof(quadlet_t)) &&
+                    be32_to_cpu(bc) & 1 << CSR_CMC_SHIFT))
                        hpsb_send_phy_config(host, root_node, -1);
                else {
                        HPSB_DEBUG("The root node is not cycle master capable; "
@@ -1459,6 +1503,13 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
                }
        }
 
+       /* 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;
 }
 
@@ -1557,24 +1608,19 @@ static int nodemgr_host_thread(void *__hi)
                        }
                }
 
-               if (!nodemgr_check_irm_capability(host, reset_cycles)) {
+               if (!nodemgr_check_irm_capability(host, reset_cycles) ||
+                   !nodemgr_do_irm_duties(host, reset_cycles)) {
                        reset_cycles++;
                        up(&nodemgr_serialize);
                        continue;
                }
+               reset_cycles = 0;
 
                /* Scan our nodes to get the bus options and create node
                 * entries. This does not do the sysfs stuff, since that
                 * would trigger hotplug callbacks and such, which is a
                 * bad idea at this point. */
                nodemgr_node_scan(hi, generation);
-               if (!nodemgr_do_irm_duties(host, reset_cycles)) {
-                       reset_cycles++;
-                       up(&nodemgr_serialize);
-                       continue;
-               }
-
-               reset_cycles = 0;
 
                /* This actually does the full probe, with sysfs
                 * registration. */