diff options
Diffstat (limited to 'drivers/firewire/fw-ohci.c')
-rw-r--r-- | drivers/firewire/fw-ohci.c | 63 |
1 files changed, 49 insertions, 14 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 251416f..ab9c01e 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) if (ab == NULL) return -ENOMEM; + ab->next = NULL; memset(&ab->descriptor, 0, sizeof(ab->descriptor)); ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | DESCRIPTOR_STATUS | @@ -496,6 +497,21 @@ static int ar_context_add_page(struct ar_context *ctx) return 0; } +static void ar_context_release(struct ar_context *ctx) +{ + struct ar_buffer *ab, *ab_next; + size_t offset; + dma_addr_t ab_bus; + + for (ab = ctx->current_buffer; ab; ab = ab_next) { + ab_next = ab->next; + offset = offsetof(struct ar_buffer, data); + ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset; + dma_free_coherent(ctx->ohci->card.device, PAGE_SIZE, + ab, ab_bus); + } +} + #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) #define cond_le32_to_cpu(v) \ (ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v)) @@ -958,6 +974,7 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet) packet->ack = RCODE_SEND_ERROR; return -1; } + packet->payload_bus = payload_bus; d[2].req_count = cpu_to_le16(packet->payload_length); d[2].data_address = cpu_to_le32(payload_bus); @@ -1009,7 +1026,6 @@ static int handle_at_packet(struct context *context, struct driver_data *driver_data; struct fw_packet *packet; struct fw_ohci *ohci = context->ohci; - dma_addr_t payload_bus; int evt; if (last->transfer_status == 0) @@ -1022,9 +1038,8 @@ static int handle_at_packet(struct context *context, /* This packet was cancelled, just continue. */ return 1; - payload_bus = le32_to_cpu(last->data_address); - if (payload_bus != 0) - dma_unmap_single(ohci->card.device, payload_bus, + if (packet->payload_bus) + dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); evt = le16_to_cpu(last->transfer_status) & 0x1f; @@ -1681,6 +1696,10 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) if (packet->ack != 0) goto out; + if (packet->payload_bus) + dma_unmap_single(ohci->card.device, packet->payload_bus, + packet->payload_length, DMA_TO_DEVICE); + log_ar_at_event('T', packet->speed, packet->header, 0x20); driver_data->packet = NULL; packet->ack = RCODE_CANCELLED; @@ -2349,8 +2368,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) ohci = kzalloc(sizeof(*ohci), GFP_KERNEL); if (ohci == NULL) { - fw_error("Could not malloc fw_ohci data.\n"); - return -ENOMEM; + err = -ENOMEM; + goto fail; } fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); @@ -2359,7 +2378,7 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) err = pci_enable_device(dev); if (err) { - fw_error("Failed to enable OHCI hardware.\n"); + fw_error("Failed to enable OHCI hardware\n"); goto fail_free; } @@ -2427,9 +2446,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) ohci->ir_context_list = kzalloc(size, GFP_KERNEL); if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) { - fw_error("Out of memory for it/ir contexts.\n"); err = -ENOMEM; - goto fail_registers; + goto fail_contexts; } /* self-id dma buffer allocation */ @@ -2438,9 +2456,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) &ohci->self_id_bus, GFP_KERNEL); if (ohci->self_id_cpu == NULL) { - fw_error("Out of memory for self ID buffer.\n"); err = -ENOMEM; - goto fail_registers; + goto fail_contexts; } bus_options = reg_read(ohci, OHCI1394_BusOptions); @@ -2454,15 +2471,19 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) goto fail_self_id; fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", - dev->dev.bus_id, version >> 16, version & 0xff); + dev_name(&dev->dev), version >> 16, version & 0xff); return 0; fail_self_id: dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE, ohci->self_id_cpu, ohci->self_id_bus); - fail_registers: - kfree(ohci->it_context_list); + fail_contexts: kfree(ohci->ir_context_list); + kfree(ohci->it_context_list); + context_release(&ohci->at_response_ctx); + context_release(&ohci->at_request_ctx); + ar_context_release(&ohci->ar_response_ctx); + ar_context_release(&ohci->ar_request_ctx); pci_iounmap(dev, ohci->registers); fail_iomem: pci_release_region(dev, 0); @@ -2471,6 +2492,9 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) fail_free: kfree(&ohci->card); ohci_pmac_off(dev); + fail: + if (err == -ENOMEM) + fw_error("Out of memory\n"); return err; } @@ -2491,8 +2515,19 @@ static void pci_remove(struct pci_dev *dev) software_reset(ohci); free_irq(dev->irq, ohci); + + if (ohci->next_config_rom && ohci->next_config_rom != ohci->config_rom) + dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, + ohci->next_config_rom, ohci->next_config_rom_bus); + if (ohci->config_rom) + dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, + ohci->config_rom, ohci->config_rom_bus); dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE, ohci->self_id_cpu, ohci->self_id_bus); + ar_context_release(&ohci->ar_request_ctx); + ar_context_release(&ohci->ar_response_ctx); + context_release(&ohci->at_request_ctx); + context_release(&ohci->at_response_ctx); kfree(ohci->it_context_list); kfree(ohci->ir_context_list); pci_iounmap(dev, ohci->registers); |