diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-04 17:21:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-04 17:21:39 -0400 |
commit | 8db72a7d7268630e04ec285fbd3e90733b2eddf9 (patch) | |
tree | bb41f5ce688f9595b5734b02c48ef53d2cc067bd | |
parent | 8a3d8ed027b563d2875cd3df816fb4a888a8551e (diff) | |
parent | 2e053a27d9d5ad5e0831e002cbf8043836fb2060 (diff) |
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
firewire: Fix for broken configrom updates in quick succession
-rw-r--r-- | drivers/firewire/ohci.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index f903d7b6f34a..23d1468ad253 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -2199,7 +2199,6 @@ static int ohci_set_config_rom(struct fw_card *card, | |||
2199 | { | 2199 | { |
2200 | struct fw_ohci *ohci; | 2200 | struct fw_ohci *ohci; |
2201 | unsigned long flags; | 2201 | unsigned long flags; |
2202 | int ret = -EBUSY; | ||
2203 | __be32 *next_config_rom; | 2202 | __be32 *next_config_rom; |
2204 | dma_addr_t uninitialized_var(next_config_rom_bus); | 2203 | dma_addr_t uninitialized_var(next_config_rom_bus); |
2205 | 2204 | ||
@@ -2240,22 +2239,37 @@ static int ohci_set_config_rom(struct fw_card *card, | |||
2240 | 2239 | ||
2241 | spin_lock_irqsave(&ohci->lock, flags); | 2240 | spin_lock_irqsave(&ohci->lock, flags); |
2242 | 2241 | ||
2242 | /* | ||
2243 | * If there is not an already pending config_rom update, | ||
2244 | * push our new allocation into the ohci->next_config_rom | ||
2245 | * and then mark the local variable as null so that we | ||
2246 | * won't deallocate the new buffer. | ||
2247 | * | ||
2248 | * OTOH, if there is a pending config_rom update, just | ||
2249 | * use that buffer with the new config_rom data, and | ||
2250 | * let this routine free the unused DMA allocation. | ||
2251 | */ | ||
2252 | |||
2243 | if (ohci->next_config_rom == NULL) { | 2253 | if (ohci->next_config_rom == NULL) { |
2244 | ohci->next_config_rom = next_config_rom; | 2254 | ohci->next_config_rom = next_config_rom; |
2245 | ohci->next_config_rom_bus = next_config_rom_bus; | 2255 | ohci->next_config_rom_bus = next_config_rom_bus; |
2256 | next_config_rom = NULL; | ||
2257 | } | ||
2246 | 2258 | ||
2247 | copy_config_rom(ohci->next_config_rom, config_rom, length); | 2259 | copy_config_rom(ohci->next_config_rom, config_rom, length); |
2248 | 2260 | ||
2249 | ohci->next_header = config_rom[0]; | 2261 | ohci->next_header = config_rom[0]; |
2250 | ohci->next_config_rom[0] = 0; | 2262 | ohci->next_config_rom[0] = 0; |
2251 | 2263 | ||
2252 | reg_write(ohci, OHCI1394_ConfigROMmap, | 2264 | reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); |
2253 | ohci->next_config_rom_bus); | ||
2254 | ret = 0; | ||
2255 | } | ||
2256 | 2265 | ||
2257 | spin_unlock_irqrestore(&ohci->lock, flags); | 2266 | spin_unlock_irqrestore(&ohci->lock, flags); |
2258 | 2267 | ||
2268 | /* If we didn't use the DMA allocation, delete it. */ | ||
2269 | if (next_config_rom != NULL) | ||
2270 | dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, | ||
2271 | next_config_rom, next_config_rom_bus); | ||
2272 | |||
2259 | /* | 2273 | /* |
2260 | * Now initiate a bus reset to have the changes take | 2274 | * Now initiate a bus reset to have the changes take |
2261 | * effect. We clean up the old config rom memory and DMA | 2275 | * effect. We clean up the old config rom memory and DMA |
@@ -2263,13 +2277,10 @@ static int ohci_set_config_rom(struct fw_card *card, | |||
2263 | * controller could need to access it before the bus reset | 2277 | * controller could need to access it before the bus reset |
2264 | * takes effect. | 2278 | * takes effect. |
2265 | */ | 2279 | */ |
2266 | if (ret == 0) | ||
2267 | fw_schedule_bus_reset(&ohci->card, true, true); | ||
2268 | else | ||
2269 | dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, | ||
2270 | next_config_rom, next_config_rom_bus); | ||
2271 | 2280 | ||
2272 | return ret; | 2281 | fw_schedule_bus_reset(&ohci->card, true, true); |
2282 | |||
2283 | return 0; | ||
2273 | } | 2284 | } |
2274 | 2285 | ||
2275 | static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) | 2286 | static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) |