Date: Sat, 8 Mar 2014 10:43:44 +0100 From: Stephan Gatzka Subject: [PATCH] Revive existing device even if its still running. Message-Id: <1394271824-8802-1-git-send-email-stephan.gatzka@gmail.com> Signed-off-by: Stephan Gatzka --- drivers/firewire/core-device.c | 52 ++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index de4aa40..e2b5f10 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -897,32 +897,34 @@ static int lookup_existing_device(struct device *dev, void *data) down_read(&fw_device_rwsem); /* serialize config_rom access */ spin_lock_irq(&card->lock); /* serialize node access */ - if (memcmp(old->config_rom, new->config_rom, 6 * 4) == 0 && - atomic_cmpxchg(&old->state, - FW_DEVICE_GONE, - FW_DEVICE_RUNNING) == FW_DEVICE_GONE) { - struct fw_node *current_node = new->node; - struct fw_node *obsolete_node = old->node; - - new->node = obsolete_node; - new->node->data = new; - old->node = current_node; - old->node->data = old; - - old->max_speed = new->max_speed; - old->node_id = current_node->node_id; - smp_wmb(); /* update node_id before generation */ - old->generation = card->generation; - old->config_rom_retries = 0; - fw_notice(card, "rediscovered device %s\n", dev_name(dev)); - - PREPARE_DELAYED_WORK(&old->work, fw_device_update); - fw_schedule_device_work(old, 0); - - if (current_node == card->root_node) - fw_schedule_bm_work(card, 0); + if (memcmp(old->config_rom, new->config_rom, 6 * 4) == 0) { + int previous_state = atomic_cmpxchg(&old->state, + FW_DEVICE_GONE, + FW_DEVICE_RUNNING); + if (previous_state == FW_DEVICE_GONE || previous_state == FW_DEVICE_RUNNING) { + struct fw_node *current_node = new->node; + struct fw_node *obsolete_node = old->node; + + new->node = obsolete_node; + new->node->data = new; + old->node = current_node; + old->node->data = old; + + old->max_speed = new->max_speed; + old->node_id = current_node->node_id; + smp_wmb(); /* update node_id before generation */ + old->generation = card->generation; + old->config_rom_retries = 0; + fw_notice(card, "rediscovered device %s\n", dev_name(dev)); + + PREPARE_DELAYED_WORK(&old->work, fw_device_update); + fw_schedule_device_work(old, 0); + + if (current_node == card->root_node) + fw_schedule_bm_work(card, 0); - match = 1; + match = 1; + } } spin_unlock_irq(&card->lock); Date: Sat, 08 Mar 2014 10:45:43 +0100 From: Stephan Gatzka To: linux1394-devel@lists.sourceforge.net Subject: Re: [PATCH] Revive existing device even if its still running. Message-ID: Hi all, that's the patch that helped me to overcome the most prevalent problems with the device stuff. As already noted, it looks like a work around. Regards, Stephan Date: Sun, 9 Mar 2014 03:25:15 +0100 From: Stefan Richter Subject: Re: [PATCH] Revive existing device even if its still running. Message-ID: <20140309032515.2369d781@stein> On Mar 08 Stephan Gatzka wrote: > that's the patch that helped me to overcome the most prevalent problems > with the device stuff. As already noted, it looks like a work around. It is not a workaround but a valid fix. Additional fixes will be required though: - As I noted on Friday, the comparison of GUIDs between a new fw_device and all existing card children needs to be made atomic with addition of the new device as card child, and must be serialized against removal of card children. - There is currently a small window during which a preexisting child of the card with same GUID as the new fw_device is not GONE or RUNNING but INITIALIZING. - If we revive a preexisting child of the card with same GUID as the new fw_device, we should not "update" but "refresh" it (i.e. check whether its Configuration ROM has changed in the meantime). - fw_workqueue needs to be non-reentrant; this has been fixed upstream by Tejun's patch now. I will merge your fix and implement fixes for the remaining three items as time permits. -- Stefan Richter -=====-====- --== -=--= http://arcgraph.de/sr/