diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-01-09 20:49:37 +0100 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-01-09 23:22:32 +0100 |
commit | 6230582320b721e6cf2581d048cb688dca97f504 (patch) | |
tree | 2babcf29c086cf77b8df9fbe54303214b1be01ad /drivers/firewire/fw-device.c | |
parent | 73d59314e6ed268d6f322ae1bdd723b23fa5a4ed (diff) | |
download | blackbird-op-linux-6230582320b721e6cf2581d048cb688dca97f504.tar.gz blackbird-op-linux-6230582320b721e6cf2581d048cb688dca97f504.zip |
firewire: core: fix sleep in atomic context due to driver core change
Due to commit 2831fe6f9cc4e16c103504ee09a47a084297c0f3, "driver core:
create a private portion of struct device", device_initialize() can no
longer be called from atomic contexts.
We now defer it until after config ROM probing. This requires changes
to the bus manager code because this may use a device before it was
probed.
Reported-by: Jay Fenlason <fenlason@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-device.c')
-rw-r--r-- | drivers/firewire/fw-device.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index c173be383725..2af5a8d1e012 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -159,7 +159,8 @@ static void fw_device_release(struct device *dev) /* * Take the card lock so we don't set this to NULL while a - * FW_NODE_UPDATED callback is being handled. + * FW_NODE_UPDATED callback is being handled or while the + * bus manager work looks at this node. */ spin_lock_irqsave(&card->lock, flags); device->node->data = NULL; @@ -695,12 +696,13 @@ static void fw_device_init(struct work_struct *work) return; } - err = -ENOMEM; + device_initialize(&device->device); fw_device_get(device); down_write(&fw_device_rwsem); - if (idr_pre_get(&fw_device_idr, GFP_KERNEL)) - err = idr_get_new(&fw_device_idr, device, &minor); + err = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? + idr_get_new(&fw_device_idr, device, &minor) : + -ENOMEM; up_write(&fw_device_rwsem); if (err < 0) @@ -911,13 +913,14 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) /* * Do minimal intialization of the device here, the - * rest will happen in fw_device_init(). We need the - * card and node so we can read the config rom and we - * need to do device_initialize() now so - * device_for_each_child() in FW_NODE_UPDATED is - * doesn't freak out. + * rest will happen in fw_device_init(). + * + * Attention: A lot of things, even fw_device_get(), + * cannot be done before fw_device_init() finished! + * You can basically just check device->state and + * schedule work until then, but only while holding + * card->lock. */ - device_initialize(&device->device); atomic_set(&device->state, FW_DEVICE_INITIALIZING); device->card = fw_card_get(card); device->node = fw_node_get(node); |