diff options
author | Jay Fenlason <fenlason@redhat.com> | 2008-10-22 15:59:42 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-10-26 05:27:00 -0400 |
commit | a55709ba9d27053471f9fca8ee76b41ecefc14cd (patch) | |
tree | e338976917e3926a292c67fcadc59968504d7fcc /drivers/firewire | |
parent | 77e557191701afa55ae7320d42ad6458a2ad292e (diff) |
firewire: fw-ohci: don't leak dma memory on module removal
The transmit and receive context dma memory was not being freed on
module removal. Neither was the config rom memory. Fix that.
The ab->next assignment is pure paranoia.
Signed-off-by: Jay Fenlason <fenlason@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/fw-ohci.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 251416f2148f..5a5685f8f5f7 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -476,6 +476,7 @@ static int ar_context_add_page(struct ar_context *ctx) | |||
476 | if (ab == NULL) | 476 | if (ab == NULL) |
477 | return -ENOMEM; | 477 | return -ENOMEM; |
478 | 478 | ||
479 | ab->next = NULL; | ||
479 | memset(&ab->descriptor, 0, sizeof(ab->descriptor)); | 480 | memset(&ab->descriptor, 0, sizeof(ab->descriptor)); |
480 | ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | | 481 | ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | |
481 | DESCRIPTOR_STATUS | | 482 | DESCRIPTOR_STATUS | |
@@ -496,6 +497,21 @@ static int ar_context_add_page(struct ar_context *ctx) | |||
496 | return 0; | 497 | return 0; |
497 | } | 498 | } |
498 | 499 | ||
500 | static void ar_context_release(struct ar_context *ctx) | ||
501 | { | ||
502 | struct ar_buffer *ab, *ab_next; | ||
503 | size_t offset; | ||
504 | dma_addr_t ab_bus; | ||
505 | |||
506 | for (ab = ctx->current_buffer; ab; ab = ab_next) { | ||
507 | ab_next = ab->next; | ||
508 | offset = offsetof(struct ar_buffer, data); | ||
509 | ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset; | ||
510 | dma_free_coherent(ctx->ohci->card.device, PAGE_SIZE, | ||
511 | ab, ab_bus); | ||
512 | } | ||
513 | } | ||
514 | |||
499 | #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) | 515 | #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) |
500 | #define cond_le32_to_cpu(v) \ | 516 | #define cond_le32_to_cpu(v) \ |
501 | (ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v)) | 517 | (ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v)) |
@@ -2491,8 +2507,19 @@ static void pci_remove(struct pci_dev *dev) | |||
2491 | 2507 | ||
2492 | software_reset(ohci); | 2508 | software_reset(ohci); |
2493 | free_irq(dev->irq, ohci); | 2509 | free_irq(dev->irq, ohci); |
2510 | |||
2511 | if (ohci->next_config_rom && ohci->next_config_rom != ohci->config_rom) | ||
2512 | dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, | ||
2513 | ohci->next_config_rom, ohci->next_config_rom_bus); | ||
2514 | if (ohci->config_rom) | ||
2515 | dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, | ||
2516 | ohci->config_rom, ohci->config_rom_bus); | ||
2494 | dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE, | 2517 | dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE, |
2495 | ohci->self_id_cpu, ohci->self_id_bus); | 2518 | ohci->self_id_cpu, ohci->self_id_bus); |
2519 | ar_context_release(&ohci->ar_request_ctx); | ||
2520 | ar_context_release(&ohci->ar_response_ctx); | ||
2521 | context_release(&ohci->at_request_ctx); | ||
2522 | context_release(&ohci->at_response_ctx); | ||
2496 | kfree(ohci->it_context_list); | 2523 | kfree(ohci->it_context_list); |
2497 | kfree(ohci->ir_context_list); | 2524 | kfree(ohci->ir_context_list); |
2498 | pci_iounmap(dev, ohci->registers); | 2525 | pci_iounmap(dev, ohci->registers); |