Commit 395c6846 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
  firewire: Kconfig help update
  ieee1394: sbp2: let nodemgr retry node updates during bus reset series
  ieee1394: don't drop nodes during bus reset series
  ieee1394: regression in 2.6.25: updates should happen before probes
parents ddd13dc6 30b0aa7c
...@@ -12,8 +12,8 @@ config FIREWIRE ...@@ -12,8 +12,8 @@ config FIREWIRE
This is the "Juju" FireWire stack, a new alternative implementation This is the "Juju" FireWire stack, a new alternative implementation
designed for robustness and simplicity. You can build either this designed for robustness and simplicity. You can build either this
stack, or the old stack (the ieee1394 driver, ohci1394 etc.) or both. stack, or the old stack (the ieee1394 driver, ohci1394 etc.) or both.
Please read http://wiki.linux1394.org/JujuMigration before you Please read http://ieee1394.wiki.kernel.org/index.php/Juju_Migration
enable the new stack. before you enable the new stack.
To compile this driver as a module, say M here: the module will be To compile this driver as a module, say M here: the module will be
called firewire-core. called firewire-core.
......
...@@ -844,7 +844,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr ...@@ -844,7 +844,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
ne->host = host; ne->host = host;
ne->nodeid = nodeid; ne->nodeid = nodeid;
ne->generation = generation; ne->generation = generation;
ne->needs_probe = 1; ne->needs_probe = true;
ne->guid = guid; ne->guid = guid;
ne->guid_vendor_id = (guid >> 40) & 0xffffff; ne->guid_vendor_id = (guid >> 40) & 0xffffff;
...@@ -1144,7 +1144,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent ...@@ -1144,7 +1144,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
struct csr1212_keyval *kv, *vendor_name_kv = NULL; struct csr1212_keyval *kv, *vendor_name_kv = NULL;
u8 last_key_id = 0; u8 last_key_id = 0;
ne->needs_probe = 0; ne->needs_probe = false;
csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) { csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) {
switch (kv->key.id) { switch (kv->key.id) {
...@@ -1295,7 +1295,7 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, ...@@ -1295,7 +1295,7 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
nodemgr_update_bus_options(ne); nodemgr_update_bus_options(ne);
/* Mark the node as new, so it gets re-probed */ /* Mark the node as new, so it gets re-probed */
ne->needs_probe = 1; ne->needs_probe = true;
} else { } else {
/* old cache is valid, so update its generation */ /* old cache is valid, so update its generation */
struct nodemgr_csr_info *ci = ne->csr->private; struct nodemgr_csr_info *ci = ne->csr->private;
...@@ -1566,56 +1566,59 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge ...@@ -1566,56 +1566,59 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
struct probe_param { struct probe_param {
struct host_info *hi; struct host_info *hi;
int generation; int generation;
bool probe_now;
}; };
static int __nodemgr_node_probe(struct device *dev, void *data) static int node_probe(struct device *dev, void *data)
{ {
struct probe_param *param = (struct probe_param *)data; struct probe_param *p = data;
struct node_entry *ne; struct node_entry *ne;
if (p->generation != get_hpsb_generation(p->hi->host))
return -EAGAIN;
ne = container_of(dev, struct node_entry, node_dev); ne = container_of(dev, struct node_entry, node_dev);
if (!ne->needs_probe) if (ne->needs_probe == p->probe_now)
nodemgr_probe_ne(param->hi, ne, param->generation); nodemgr_probe_ne(p->hi, ne, p->generation);
if (ne->needs_probe)
nodemgr_probe_ne(param->hi, ne, param->generation);
return 0; return 0;
} }
static void nodemgr_node_probe(struct host_info *hi, int generation) static void nodemgr_node_probe(struct host_info *hi, int generation)
{ {
struct hpsb_host *host = hi->host; struct probe_param p;
struct probe_param param;
param.hi = hi; p.hi = hi;
param.generation = generation; p.generation = generation;
/* Do some processing of the nodes we've probed. This pulls them /*
* Do some processing of the nodes we've probed. This pulls them
* into the sysfs layer if needed, and can result in processing of * into the sysfs layer if needed, and can result in processing of
* unit-directories, or just updating the node and it's * unit-directories, or just updating the node and it's
* unit-directories. * unit-directories.
* *
* Run updates before probes. Usually, updates are time-critical * Run updates before probes. Usually, updates are time-critical
* while probes are time-consuming. (Well, those probes need some * while probes are time-consuming.
* improvement...) */
class_for_each_device(&nodemgr_ne_class, NULL, &param,
__nodemgr_node_probe);
/* If we had a bus reset while we were scanning the bus, it is
* possible that we did not probe all nodes. In that case, we
* skip the clean up for now, since we could remove nodes that
* were still on the bus. Another bus scan is pending which will
* do the clean up eventually.
* *
* Meanwhile, another bus reset may have happened. In this case we
* skip everything here and let the next bus scan handle it.
* Otherwise we may prematurely remove nodes which are still there.
*/
p.probe_now = false;
if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
return;
p.probe_now = true;
if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
return;
/*
* Now let's tell the bus to rescan our devices. This may seem * Now let's tell the bus to rescan our devices. This may seem
* like overhead, but the driver-model core will only scan a * like overhead, but the driver-model core will only scan a
* device for a driver when either the device is added, or when a * device for a driver when either the device is added, or when a
* new driver is added. A bus reset is a good reason to rescan * new driver is added. A bus reset is a good reason to rescan
* devices that were there before. For example, an sbp2 device * devices that were there before. For example, an sbp2 device
* may become available for login, if the host that held it was * may become available for login, if the host that held it was
* just removed. */ * just removed.
*/
if (generation == get_hpsb_generation(host)) if (bus_rescan_devices(&ieee1394_bus_type) != 0)
if (bus_rescan_devices(&ieee1394_bus_type))
HPSB_DEBUG("bus_rescan_devices had an error"); HPSB_DEBUG("bus_rescan_devices had an error");
} }
......
...@@ -97,7 +97,7 @@ struct node_entry { ...@@ -97,7 +97,7 @@ struct node_entry {
struct hpsb_host *host; /* Host this node is attached to */ struct hpsb_host *host; /* Host this node is attached to */
nodeid_t nodeid; /* NodeID */ nodeid_t nodeid; /* NodeID */
struct bus_options busopt; /* Bus Options */ struct bus_options busopt; /* Bus Options */
int needs_probe; bool needs_probe;
unsigned int generation; /* Synced with hpsb generation */ unsigned int generation; /* Synced with hpsb generation */
/* The following is read from the config rom */ /* The following is read from the config rom */
......
...@@ -731,15 +731,26 @@ static int sbp2_update(struct unit_directory *ud) ...@@ -731,15 +731,26 @@ static int sbp2_update(struct unit_directory *ud)
{ {
struct sbp2_lu *lu = ud->device.driver_data; struct sbp2_lu *lu = ud->device.driver_data;
if (sbp2_reconnect_device(lu)) { if (sbp2_reconnect_device(lu) != 0) {
/* Reconnect has failed. Perhaps we didn't reconnect fast /*
* enough. Try a regular login, but first log out just in * Reconnect failed. If another bus reset happened,
* case of any weirdness. */ * let nodemgr proceed and call sbp2_update again later
* (or sbp2_remove if this node went away).
*/
if (!hpsb_node_entry_valid(lu->ne))
return 0;
/*
* Or the target rejected the reconnect because we weren't
* fast enough. Try a regular login, but first log out
* just in case of any weirdness.
*/
sbp2_logout_device(lu); sbp2_logout_device(lu);
if (sbp2_login_device(lu)) { if (sbp2_login_device(lu) != 0) {
/* Login failed too, just fail, and the backend if (!hpsb_node_entry_valid(lu->ne))
* will call our sbp2_remove for us */ return 0;
/* Maybe another initiator won the login. */
SBP2_ERR("Failed to reconnect to sbp2 device!"); SBP2_ERR("Failed to reconnect to sbp2 device!");
return -EBUSY; return -EBUSY;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment