aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2009-09-06 18:50:29 +0200
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-09-12 14:48:40 +0200
commitb171e204b32b69e241af994d6e9be559e33535c1 (patch)
tree0ba90b20dfed4e721a573e2dfe9e4584e8a80737 /drivers/firewire
parent18668ff9a3232d5f942a2f7abc1ad67d2760dcdf (diff)
downloadkernel_samsung_tuna-b171e204b32b69e241af994d6e9be559e33535c1.zip
kernel_samsung_tuna-b171e204b32b69e241af994d6e9be559e33535c1.tar.gz
kernel_samsung_tuna-b171e204b32b69e241af994d6e9be559e33535c1.tar.bz2
firewire: core: fix race with parallel PCI device probe
The config ROM buffer received from generate_config_rom is a globally shared static buffer. Extend the card_mutex protection in fw_add_card until after the config ROM was copied into the card driver's buffer. Otherwise, parallelized card driver probes may end up with ROM contents that were meant for a different card. firewire-ohci's card->driver->enable hook is safe to be called within the card_mutex. Furthermore, it is safe to reorder card_list update versus card enable, which simplifies the code a little. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/core-card.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index f74edae..e4864e8 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -444,16 +444,13 @@ int fw_card_add(struct fw_card *card,
card->guid = guid;
mutex_lock(&card_mutex);
- config_rom = generate_config_rom(card, &length);
- list_add_tail(&card->link, &card_list);
- mutex_unlock(&card_mutex);
+ config_rom = generate_config_rom(card, &length);
ret = card->driver->enable(card, config_rom, length);
- if (ret < 0) {
- mutex_lock(&card_mutex);
- list_del(&card->link);
- mutex_unlock(&card_mutex);
- }
+ if (ret == 0)
+ list_add_tail(&card->link, &card_list);
+
+ mutex_unlock(&card_mutex);
return ret;
}