diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-01-09 14:49:37 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-01-09 17:22:32 -0500 |
commit | 6230582320b721e6cf2581d048cb688dca97f504 (patch) | |
tree | 2babcf29c086cf77b8df9fbe54303214b1be01ad /drivers/firewire/fw-device.c | |
parent | 73d59314e6ed268d6f322ae1bdd723b23fa5a4ed (diff) |
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) | |||
159 | 159 | ||
160 | /* | 160 | /* |
161 | * Take the card lock so we don't set this to NULL while a | 161 | * Take the card lock so we don't set this to NULL while a |
162 | * FW_NODE_UPDATED callback is being handled. | 162 | * FW_NODE_UPDATED callback is being handled or while the |
163 | * bus manager work looks at this node. | ||
163 | */ | 164 | */ |
164 | spin_lock_irqsave(&card->lock, flags); | 165 | spin_lock_irqsave(&card->lock, flags); |
165 | device->node->data = NULL; | 166 | device->node->data = NULL; |
@@ -695,12 +696,13 @@ static void fw_device_init(struct work_struct *work) | |||
695 | return; | 696 | return; |
696 | } | 697 | } |
697 | 698 | ||
698 | err = -ENOMEM; | 699 | device_initialize(&device->device); |
699 | 700 | ||
700 | fw_device_get(device); | 701 | fw_device_get(device); |
701 | down_write(&fw_device_rwsem); | 702 | down_write(&fw_device_rwsem); |
702 | if (idr_pre_get(&fw_device_idr, GFP_KERNEL)) | 703 | err = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? |
703 | err = idr_get_new(&fw_device_idr, device, &minor); | 704 | idr_get_new(&fw_device_idr, device, &minor) : |
705 | -ENOMEM; | ||
704 | up_write(&fw_device_rwsem); | 706 | up_write(&fw_device_rwsem); |
705 | 707 | ||
706 | if (err < 0) | 708 | if (err < 0) |
@@ -911,13 +913,14 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) | |||
911 | 913 | ||
912 | /* | 914 | /* |
913 | * Do minimal intialization of the device here, the | 915 | * Do minimal intialization of the device here, the |
914 | * rest will happen in fw_device_init(). We need the | 916 | * rest will happen in fw_device_init(). |
915 | * card and node so we can read the config rom and we | 917 | * |
916 | * need to do device_initialize() now so | 918 | * Attention: A lot of things, even fw_device_get(), |
917 | * device_for_each_child() in FW_NODE_UPDATED is | 919 | * cannot be done before fw_device_init() finished! |
918 | * doesn't freak out. | 920 | * You can basically just check device->state and |
921 | * schedule work until then, but only while holding | ||
922 | * card->lock. | ||
919 | */ | 923 | */ |
920 | device_initialize(&device->device); | ||
921 | atomic_set(&device->state, FW_DEVICE_INITIALIZING); | 924 | atomic_set(&device->state, FW_DEVICE_INITIALIZING); |
922 | device->card = fw_card_get(card); | 925 | device->card = fw_card_get(card); |
923 | device->node = fw_node_get(node); | 926 | device->node = fw_node_get(node); |