]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/firewire/fw-ohci.c
firewire: Implement proper transaction cancelation.
[mirror_ubuntu-jammy-kernel.git] / drivers / firewire / fw-ohci.c
index 6eff7996c1a7b328efce6265c34f0f485af48749..e6fa3496183e7c5e96eb24a7f7d2deb41d68892d 100644 (file)
@@ -55,17 +55,23 @@ struct descriptor {
        __le16 transfer_status;
 } __attribute__((aligned(16)));
 
-struct ar_context {
-       struct fw_ohci *ohci;
-       struct descriptor descriptor;
-       __le32 buffer[512];
-       dma_addr_t descriptor_bus;
-       dma_addr_t buffer_bus;
+#define control_set(regs)      (regs)
+#define control_clear(regs)    ((regs) + 4)
+#define command_ptr(regs)      ((regs) + 12)
+#define context_match(regs)    ((regs) + 16)
 
-       u32 command_ptr;
-       u32 control_set;
-       u32 control_clear;
+struct ar_buffer {
+       struct descriptor descriptor;
+       struct ar_buffer *next;
+       __le32 data[0];
+};
 
+struct ar_context {
+       struct fw_ohci *ohci;
+       struct ar_buffer *current_buffer;
+       struct ar_buffer *last_buffer;
+       void *pointer;
+       u32 regs;
        struct tasklet_struct tasklet;
 };
 
@@ -73,6 +79,7 @@ struct at_context {
        struct fw_ohci *ohci;
        dma_addr_t descriptor_bus;
        dma_addr_t buffer_bus;
+       struct fw_packet *current_packet;
 
        struct list_head list;
 
@@ -82,9 +89,7 @@ struct at_context {
                struct descriptor last;
        } d;
 
-       u32 command_ptr;
-       u32 control_set;
-       u32 control_clear;
+       u32 regs;
 
        struct tasklet_struct tasklet;
 };
@@ -99,10 +104,7 @@ struct at_context {
 struct iso_context {
        struct fw_iso_context base;
        struct tasklet_struct tasklet;
-       u32 control_set;
-       u32 control_clear;
-       u32 command_ptr;
-       u32 context_match;
+       u32 regs;
 
        struct descriptor *buffer;
        dma_addr_t buffer_bus;
@@ -121,6 +123,7 @@ struct fw_ohci {
        dma_addr_t self_id_bus;
        __le32 *self_id_cpu;
        struct tasklet_struct bus_reset_tasklet;
+       int node_id;
        int generation;
        int request_generation;
 
@@ -168,9 +171,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 #define OHCI_LOOP_COUNT                        500
 #define OHCI1394_PCI_HCI_Control       0x40
 #define SELF_ID_BUF_SIZE               0x800
-
-/* FIXME: Move this to linux/pci_ids.h */
-#define PCI_CLASS_SERIAL_FIREWIRE_OHCI 0x0c0010
+#define OHCI_TCODE_PHY_PACKET          0x0e
 
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
@@ -213,35 +214,97 @@ ohci_update_phy_reg(struct fw_card *card, int addr,
        return 0;
 }
 
-static void ar_context_run(struct ar_context *ctx)
+static int ar_context_add_page(struct ar_context *ctx)
 {
-       reg_write(ctx->ohci, ctx->command_ptr, ctx->descriptor_bus | 1);
-       reg_write(ctx->ohci, ctx->control_set, CONTEXT_RUN);
+       struct device *dev = ctx->ohci->card.device;
+       struct ar_buffer *ab;
+       dma_addr_t ab_bus;
+       size_t offset;
+
+       ab = (struct ar_buffer *) __get_free_page(GFP_ATOMIC);
+       if (ab == NULL)
+               return -ENOMEM;
+
+       ab_bus = dma_map_single(dev, ab, PAGE_SIZE, DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(ab_bus)) {
+               free_page((unsigned long) ab);
+               return -ENOMEM;
+       }
+
+       memset(&ab->descriptor, 0, sizeof ab->descriptor);
+       ab->descriptor.control        = cpu_to_le16(descriptor_input_more |
+                                                   descriptor_status |
+                                                   descriptor_branch_always);
+       offset = offsetof(struct ar_buffer, data);
+       ab->descriptor.req_count      = cpu_to_le16(PAGE_SIZE - offset);
+       ab->descriptor.data_address   = cpu_to_le32(ab_bus + offset);
+       ab->descriptor.res_count      = cpu_to_le16(PAGE_SIZE - offset);
+       ab->descriptor.branch_address = 0;
+
+       dma_sync_single_for_device(dev, ab_bus, PAGE_SIZE, DMA_BIDIRECTIONAL);
+
+       ctx->last_buffer->descriptor.branch_address = ab_bus | 1;
+       ctx->last_buffer->next = ab;
+       ctx->last_buffer = ab;
+
+       reg_write(ctx->ohci, control_set(ctx->regs), CONTEXT_WAKE);
        flush_writes(ctx->ohci);
+
+       return 0;
 }
 
-static void ar_context_tasklet(unsigned long data)
+static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
 {
-       struct ar_context *ctx = (struct ar_context *)data;
        struct fw_ohci *ohci = ctx->ohci;
-       u32 status;
-       int length, speed, ack, timestamp, tcode;
+       struct fw_packet p;
+       u32 status, length, tcode;
+
+       p.header[0] = le32_to_cpu(buffer[0]);
+       p.header[1] = le32_to_cpu(buffer[1]);
+       p.header[2] = le32_to_cpu(buffer[2]);
+
+       tcode = (p.header[0] >> 4) & 0x0f;
+       switch (tcode) {
+       case TCODE_WRITE_QUADLET_REQUEST:
+       case TCODE_READ_QUADLET_RESPONSE:
+               p.header[3] = (__force __u32) buffer[3];
+               p.header_length = 16;
+               p.payload_length = 0;
+               break;
+
+       case TCODE_READ_BLOCK_REQUEST :
+               p.header[3] = le32_to_cpu(buffer[3]);
+               p.header_length = 16;
+               p.payload_length = 0;
+               break;
+
+       case TCODE_WRITE_BLOCK_REQUEST:
+       case TCODE_READ_BLOCK_RESPONSE:
+       case TCODE_LOCK_REQUEST:
+       case TCODE_LOCK_RESPONSE:
+               p.header[3] = le32_to_cpu(buffer[3]);
+               p.header_length = 16;
+               p.payload_length = p.header[3] >> 16;
+               break;
+
+       case TCODE_WRITE_RESPONSE:
+       case TCODE_READ_QUADLET_REQUEST:
+       case OHCI_TCODE_PHY_PACKET:
+               p.header_length = 12;
+               p.payload_length = 0;
+               break;
+       }
+
+       p.payload = (void *) buffer + p.header_length;
 
        /* FIXME: What to do about evt_* errors? */
-       length    = le16_to_cpu(ctx->descriptor.req_count) -
-               le16_to_cpu(ctx->descriptor.res_count) - 4;
-       status    = le32_to_cpu(ctx->buffer[length / 4]);
-       ack       = ((status >> 16) & 0x1f) - 16;
-       speed     = (status >> 21) & 0x7;
-       timestamp = status & 0xffff;
-
-       ctx->buffer[0] = le32_to_cpu(ctx->buffer[0]);
-       ctx->buffer[1] = le32_to_cpu(ctx->buffer[1]);
-       ctx->buffer[2] = le32_to_cpu(ctx->buffer[2]);
-
-       tcode = (ctx->buffer[0] >> 4) & 0x0f;
-       if (TCODE_IS_BLOCK_PACKET(tcode))
-               ctx->buffer[3] = le32_to_cpu(ctx->buffer[3]);
+       length = (p.header_length + p.payload_length + 3) / 4;
+       status = le32_to_cpu(buffer[length]);
+
+       p.ack        = ((status >> 16) & 0x1f) - 16;
+       p.speed      = (status >> 21) & 0x7;
+       p.timestamp  = status & 0xffff;
+       p.generation = ohci->request_generation;
 
        /* The OHCI bus reset handler synthesizes a phy packet with
         * the new generation number when a bus reset happens (see
@@ -251,71 +314,83 @@ static void ar_context_tasklet(unsigned long data)
         * we use the unique tlabel for finding the matching
         * request. */
 
-       if (ack + 16 == 0x09)
-               ohci->request_generation = (ctx->buffer[2] >> 16) & 0xff;
+       if (p.ack + 16 == 0x09)
+               ohci->request_generation = (buffer[2] >> 16) & 0xff;
        else if (ctx == &ohci->ar_request_ctx)
-               fw_core_handle_request(&ohci->card, speed, ack, timestamp,
-                                      ohci->request_generation,
-                                      length, ctx->buffer);
+               fw_core_handle_request(&ohci->card, &p);
        else
-               fw_core_handle_response(&ohci->card, speed, ack, timestamp,
-                                       length, ctx->buffer);
+               fw_core_handle_response(&ohci->card, &p);
 
-       ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus);
-       ctx->descriptor.req_count    = cpu_to_le16(sizeof ctx->buffer);
-       ctx->descriptor.res_count    = cpu_to_le16(sizeof ctx->buffer);
-
-       dma_sync_single_for_device(ohci->card.device, ctx->descriptor_bus,
-                                  sizeof ctx->descriptor_bus, DMA_TO_DEVICE);
-
-       /* FIXME: We stop and restart the ar context here, what if we
-        * stop while a receive is in progress? Maybe we could just
-        * loop the context back to itself and use it in buffer fill
-        * mode as intended... */
-
-       reg_write(ctx->ohci, ctx->control_clear, CONTEXT_RUN);
-       ar_context_run(ctx);
+       return buffer + length + 1;
 }
 
-static int
-ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 control_set)
+static void ar_context_tasklet(unsigned long data)
 {
-       ctx->descriptor_bus =
-               dma_map_single(ohci->card.device, &ctx->descriptor,
-                              sizeof ctx->descriptor, DMA_TO_DEVICE);
-       if (ctx->descriptor_bus == 0)
-               return -ENOMEM;
-
-       if (ctx->descriptor_bus & 0xf)
-               fw_notify("descriptor not 16-byte aligned: 0x%08lx\n",
-                         (unsigned long)ctx->descriptor_bus);
-
-       ctx->buffer_bus =
-               dma_map_single(ohci->card.device, ctx->buffer,
-                              sizeof ctx->buffer, DMA_FROM_DEVICE);
+       struct ar_context *ctx = (struct ar_context *)data;
+       struct fw_ohci *ohci = ctx->ohci;
+       struct ar_buffer *ab;
+       struct descriptor *d;
+       void *buffer, *end;
+
+       ab = ctx->current_buffer;
+       d = &ab->descriptor;
+
+       if (d->res_count == 0) {
+               size_t size, rest, offset;
+
+               /* This descriptor is finished and we may have a
+                * packet split across this and the next buffer. We
+                * reuse the page for reassembling the split packet. */
+
+               offset = offsetof(struct ar_buffer, data);
+               dma_unmap_single(ohci->card.device,
+                                ab->descriptor.data_address - offset,
+                                PAGE_SIZE, DMA_BIDIRECTIONAL);
+
+               buffer = ab;
+               ab = ab->next;
+               d = &ab->descriptor;
+               size = buffer + PAGE_SIZE - ctx->pointer;
+               rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
+               memmove(buffer, ctx->pointer, size);
+               memcpy(buffer + size, ab->data, rest);
+               ctx->current_buffer = ab;
+               ctx->pointer = (void *) ab->data + rest;
+               end = buffer + size + rest;
+
+               while (buffer < end)
+                       buffer = handle_ar_packet(ctx, buffer);
+
+               free_page((unsigned long)buffer);
+               ar_context_add_page(ctx);
+       } else {
+               buffer = ctx->pointer;
+               ctx->pointer = end =
+                       (void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count);
 
-       if (ctx->buffer_bus == 0) {
-               dma_unmap_single(ohci->card.device, ctx->descriptor_bus,
-                                sizeof ctx->descriptor, DMA_TO_DEVICE);
-               return -ENOMEM;
+               while (buffer < end)
+                       buffer = handle_ar_packet(ctx, buffer);
        }
+}
 
-       memset(&ctx->descriptor, 0, sizeof ctx->descriptor);
-       ctx->descriptor.control      = cpu_to_le16(descriptor_input_more |
-                                                  descriptor_status |
-                                                  descriptor_branch_always);
-       ctx->descriptor.req_count    = cpu_to_le16(sizeof ctx->buffer);
-       ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus);
-       ctx->descriptor.res_count    = cpu_to_le16(sizeof ctx->buffer);
-
-       ctx->control_set   = control_set;
-       ctx->control_clear = control_set + 4;
-       ctx->command_ptr   = control_set + 12;
-       ctx->ohci          = ohci;
+static int
+ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs)
+{
+       struct ar_buffer ab;
 
+       ctx->regs        = regs;
+       ctx->ohci        = ohci;
+       ctx->last_buffer = &ab;
        tasklet_init(&ctx->tasklet, ar_context_tasklet, (unsigned long)ctx);
 
-       ar_context_run(ctx);
+       ar_context_add_page(ctx);
+       ar_context_add_page(ctx);
+       ctx->current_buffer = ab.next;
+       ctx->pointer = ctx->current_buffer->data;
+
+       reg_write(ctx->ohci, command_ptr(ctx->regs), ab.descriptor.branch_address);
+       reg_write(ctx->ohci, control_set(ctx->regs), CONTEXT_RUN);
+       flush_writes(ctx->ohci);
 
        return 0;
 }
@@ -326,15 +401,15 @@ do_packet_callbacks(struct fw_ohci *ohci, struct list_head *list)
        struct fw_packet *p, *next;
 
        list_for_each_entry_safe(p, next, list, link)
-               p->callback(p, &ohci->card, p->status);
+               p->callback(p, &ohci->card, p->ack);
 }
 
 static void
 complete_transmission(struct fw_packet *packet,
-                     int status, struct list_head *list)
+                     int ack, struct list_head *list)
 {
        list_move_tail(&packet->link, list);
-       packet->status = status;
+       packet->ack = ack;
 }
 
 /* This function prepares the first packet in the context queue for
@@ -357,7 +432,7 @@ at_context_setup_packet(struct at_context *ctx, struct list_head *list)
                                                     packet->payload_length,
                                                     DMA_TO_DEVICE);
                if (packet->payload_bus == 0) {
-                       complete_transmission(packet, -ENOMEM, list);
+                       complete_transmission(packet, RCODE_SEND_ERROR, list);
                        return;
                }
 
@@ -411,15 +486,16 @@ at_context_setup_packet(struct at_context *ctx, struct list_head *list)
 
        /* FIXME: Document how the locking works. */
        if (ohci->generation == packet->generation) {
-               reg_write(ctx->ohci, ctx->command_ptr,
+               reg_write(ctx->ohci, command_ptr(ctx->regs),
                          ctx->descriptor_bus | z);
-               reg_write(ctx->ohci, ctx->control_set,
+               reg_write(ctx->ohci, control_set(ctx->regs),
                          CONTEXT_RUN | CONTEXT_WAKE);
+               ctx->current_packet = packet;
        } else {
                /* We dont return error codes from this function; all
                 * transmission errors are reported through the
                 * callback. */
-               complete_transmission(packet, -ESTALE, list);
+               complete_transmission(packet, RCODE_GENERATION, list);
        }
 }
 
@@ -427,9 +503,9 @@ static void at_context_stop(struct at_context *ctx)
 {
        u32 reg;
 
-       reg_write(ctx->ohci, ctx->control_clear, CONTEXT_RUN);
+       reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN);
 
-       reg = reg_read(ctx->ohci, ctx->control_set);
+       reg = reg_read(ctx->ohci, control_set(ctx->regs));
        if (reg & CONTEXT_ACTIVE)
                fw_notify("Tried to stop context, but it is still active "
                          "(0x%08x).\n", reg);
@@ -450,6 +526,12 @@ static void at_context_tasklet(unsigned long data)
 
        at_context_stop(ctx);
 
+       /* If the head of the list isn't the packet that just got
+        * transmitted, the packet got cancelled before we finished
+        * transmitting it. */
+       if (ctx->current_packet != packet)
+               goto skip_to_next;
+
        if (packet->payload_length > 0) {
                dma_unmap_single(ohci->card.device, packet->payload_bus,
                                 packet->payload_length, DMA_TO_DEVICE);
@@ -465,31 +547,32 @@ static void at_context_tasklet(unsigned long data)
                switch (evt) {
                case OHCI1394_evt_timeout:
                        /* Async response transmit timed out. */
-                       complete_transmission(packet, -ETIMEDOUT, &list);
+                       complete_transmission(packet, RCODE_CANCELLED, &list);
                        break;
 
                case OHCI1394_evt_flushed:
                        /* The packet was flushed should give same
                         * error as when we try to use a stale
                         * generation count. */
-                       complete_transmission(packet, -ESTALE, &list);
+                       complete_transmission(packet,
+                                             RCODE_GENERATION, &list);
                        break;
 
                case OHCI1394_evt_missing_ack:
-                       /* This would be a higher level software
-                        * error, it is using a valid (current)
-                        * generation count, but the node is not on
-                        * the bus. */
-                       complete_transmission(packet, -ENODEV, &list);
+                       /* Using a valid (current) generation count,
+                        * but the node is not on the bus or not
+                        * sending acks. */
+                       complete_transmission(packet, RCODE_NO_ACK, &list);
                        break;
 
                default:
-                       complete_transmission(packet, -EIO, &list);
+                       complete_transmission(packet, RCODE_SEND_ERROR, &list);
                        break;
                }
        } else
                complete_transmission(packet, evt - 16, &list);
 
+ skip_to_next:
        /* If more packets are queued, set up the next one. */
        if (!list_empty(&ctx->list))
                at_context_setup_packet(ctx, &list);
@@ -500,7 +583,7 @@ static void at_context_tasklet(unsigned long data)
 }
 
 static int
-at_context_init(struct at_context *ctx, struct fw_ohci *ohci, u32 control_set)
+at_context_init(struct at_context *ctx, struct fw_ohci *ohci, u32 regs)
 {
        INIT_LIST_HEAD(&ctx->list);
 
@@ -510,28 +593,140 @@ at_context_init(struct at_context *ctx, struct fw_ohci *ohci, u32 control_set)
        if (ctx->descriptor_bus == 0)
                return -ENOMEM;
 
-       ctx->control_set   = control_set;
-       ctx->control_clear = control_set + 4;
-       ctx->command_ptr   = control_set + 12;
-       ctx->ohci          = ohci;
+       ctx->regs = regs;
+       ctx->ohci = ohci;
 
        tasklet_init(&ctx->tasklet, at_context_tasklet, (unsigned long)ctx);
 
        return 0;
 }
 
+#define header_get_destination(q)      (((q) >> 16) & 0xffff)
+#define header_get_tcode(q)            (((q) >> 4) & 0x0f)
+#define header_get_offset_high(q)      (((q) >> 0) & 0xffff)
+#define header_get_data_length(q)      (((q) >> 16) & 0xffff)
+#define header_get_extended_tcode(q)   (((q) >> 0) & 0xffff)
+
+static void
+handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr)
+{
+       struct fw_packet response;
+       int tcode, length, i;
+
+       tcode = header_get_tcode(packet->header[0]);
+       if (TCODE_IS_BLOCK_PACKET(tcode))
+               length = header_get_data_length(packet->header[3]);
+       else
+               length = 4;
+
+       i = csr - CSR_CONFIG_ROM;
+       if (i + length > CONFIG_ROM_SIZE) {
+               fw_fill_response(&response, packet->header,
+                                RCODE_ADDRESS_ERROR, NULL, 0);
+       } else if (!TCODE_IS_READ_REQUEST(tcode)) {
+               fw_fill_response(&response, packet->header,
+                                RCODE_TYPE_ERROR, NULL, 0);
+       } else {
+               fw_fill_response(&response, packet->header, RCODE_COMPLETE,
+                                (void *) ohci->config_rom + i, length);
+       }
+
+       fw_core_handle_response(&ohci->card, &response);
+}
+
+static void
+handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr)
+{
+       struct fw_packet response;
+       int tcode, length, ext_tcode, sel;
+       __be32 *payload, lock_old;
+       u32 lock_arg, lock_data;
+
+       tcode = header_get_tcode(packet->header[0]);
+       length = header_get_data_length(packet->header[3]);
+       payload = packet->payload;
+       ext_tcode = header_get_extended_tcode(packet->header[3]);
+
+       if (tcode == TCODE_LOCK_REQUEST &&
+           ext_tcode == EXTCODE_COMPARE_SWAP && length == 8) {
+               lock_arg = be32_to_cpu(payload[0]);
+               lock_data = be32_to_cpu(payload[1]);
+       } else if (tcode == TCODE_READ_QUADLET_REQUEST) {
+               lock_arg = 0;
+               lock_data = 0;
+       } else {
+               fw_fill_response(&response, packet->header,
+                                RCODE_TYPE_ERROR, NULL, 0);
+               goto out;
+       }
+
+       sel = (csr - CSR_BUS_MANAGER_ID) / 4;
+       reg_write(ohci, OHCI1394_CSRData, lock_data);
+       reg_write(ohci, OHCI1394_CSRCompareData, lock_arg);
+       reg_write(ohci, OHCI1394_CSRControl, sel);
+
+       if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000)
+               lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData));
+       else
+               fw_notify("swap not done yet\n");
+
+       fw_fill_response(&response, packet->header,
+                        RCODE_COMPLETE, &lock_old, sizeof lock_old);
+ out:
+       fw_core_handle_response(&ohci->card, &response);
+}
+
+static void
+handle_local_request(struct at_context *ctx, struct fw_packet *packet)
+{
+       u64 offset;
+       u32 csr;
+
+       packet->ack = ACK_PENDING;
+       packet->callback(packet, &ctx->ohci->card, packet->ack);
+
+       offset =
+               ((unsigned long long)
+                header_get_offset_high(packet->header[1]) << 32) |
+               packet->header[2];
+       csr = offset - CSR_REGISTER_BASE;
+
+       /* Handle config rom reads. */
+       if (csr >= CSR_CONFIG_ROM && csr < CSR_CONFIG_ROM_END)
+               handle_local_rom(ctx->ohci, packet, csr);
+       else switch (csr) {
+       case CSR_BUS_MANAGER_ID:
+       case CSR_BANDWIDTH_AVAILABLE:
+       case CSR_CHANNELS_AVAILABLE_HI:
+       case CSR_CHANNELS_AVAILABLE_LO:
+               handle_local_lock(ctx->ohci, packet, csr);
+               break;
+       default:
+               if (ctx == &ctx->ohci->at_request_ctx)
+                       fw_core_handle_request(&ctx->ohci->card, packet);
+               else
+                       fw_core_handle_response(&ctx->ohci->card, packet);
+               break;
+       }
+}
+
 static void
 at_context_transmit(struct at_context *ctx, struct fw_packet *packet)
 {
        LIST_HEAD(list);
        unsigned long flags;
-       int was_empty;
 
        spin_lock_irqsave(&ctx->ohci->lock, flags);
 
-       was_empty = list_empty(&ctx->list);
+       if (header_get_destination(packet->header[0]) == ctx->ohci->node_id &&
+           ctx->ohci->generation == packet->generation) {
+               spin_unlock_irqrestore(&ctx->ohci->lock, flags);
+               handle_local_request(ctx, packet);
+               return;
+       }
+
        list_add_tail(&packet->link, &ctx->list);
-       if (was_empty)
+       if (ctx->list.next == &packet->link)
                at_context_setup_packet(ctx, &list);
 
        spin_unlock_irqrestore(&ctx->ohci->lock, flags);
@@ -542,7 +737,7 @@ at_context_transmit(struct at_context *ctx, struct fw_packet *packet)
 static void bus_reset_tasklet(unsigned long data)
 {
        struct fw_ohci *ohci = (struct fw_ohci *)data;
-       int self_id_count, i, j, reg, node_id;
+       int self_id_count, i, j, reg;
        int generation, new_generation;
        unsigned long flags;
 
@@ -551,7 +746,7 @@ static void bus_reset_tasklet(unsigned long data)
                fw_error("node ID not valid, new bus reset in progress\n");
                return;
        }
-       node_id = reg & 0xffff;
+       ohci->node_id = reg & 0xffff;
 
        /* The count in the SelfIDCount register is the number of
         * bytes in the self ID receive buffer.  Since we also receive
@@ -620,7 +815,7 @@ static void bus_reset_tasklet(unsigned long data)
 
        spin_unlock_irqrestore(&ohci->lock, flags);
 
-       fw_core_handle_bus_reset(&ohci->card, node_id, generation,
+       fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
                                 self_id_count, ohci->self_id_buffer);
 }
 
@@ -826,15 +1021,38 @@ static void ohci_send_response(struct fw_card *card, struct fw_packet *packet)
        at_context_transmit(&ohci->at_response_ctx, packet);
 }
 
+static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+{
+       struct fw_ohci *ohci = fw_ohci(card);
+       LIST_HEAD(list);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ohci->lock, flags);
+
+       if (packet->ack == 0) {
+               fw_notify("cancelling packet %p (header[0]=%08x)\n",
+                         packet, packet->header[0]);
+
+               complete_transmission(packet, RCODE_CANCELLED, &list);
+       }
+
+       spin_unlock_irqrestore(&ohci->lock, flags);
+
+       do_packet_callbacks(ohci, &list);
+
+       /* Return success if we actually cancelled something. */
+       return list_empty(&list) ? -ENOENT : 0;
+}
+
 static int
 ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
 {
        struct fw_ohci *ohci = fw_ohci(card);
        unsigned long flags;
-       int retval = 0;
+       int n, retval = 0;
 
-       /* FIXME: make sure this bitmask is cleared when we clear the
-        * busReset interrupt bit. */
+       /* FIXME:  Make sure this bitmask is cleared when we clear the busReset
+        * interrupt bit.  Clear physReqResourceAllBuses on bus reset. */
 
        spin_lock_irqsave(&ohci->lock, flags);
 
@@ -843,17 +1061,18 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
                goto out;
        }
 
-       if (node_id < 32) {
-               reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 1 << node_id);
-       } else {
-               reg_write(ohci, OHCI1394_PhyReqFilterHiSet,
-                         1 << (node_id - 32));
-       }
-       flush_writes(ohci);
+       /* NOTE, if the node ID contains a non-local bus ID, physical DMA is
+        * enabled for _all_ nodes on remote buses. */
 
-       spin_unlock_irqrestore(&ohci->lock, flags);
+       n = (node_id & 0xffc0) == LOCAL_BUS ? node_id & 0x3f : 63;
+       if (n < 32)
+               reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 1 << n);
+       else
+               reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 1 << (n - 32));
 
+       flush_writes(ohci);
  out:
+       spin_unlock_irqrestore(&ohci->lock, flags);
        return retval;
 }
 
@@ -963,9 +1182,8 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
         * element so that head == tail means buffer full. */
 
        memset(ctx->head_descriptor, 0, sizeof *ctx->head_descriptor);
-       ctx->head_descriptor->control          =
-               cpu_to_le16(descriptor_output_last);
-       ctx->head_descriptor->transfer_status  = cpu_to_le16(0x8011);
+       ctx->head_descriptor->control = cpu_to_le16(descriptor_output_last);
+       ctx->head_descriptor->transfer_status = cpu_to_le16(0x8011);
        ctx->head_descriptor++;
 
        return &ctx->base;
@@ -1153,12 +1371,13 @@ static const struct fw_card_driver ohci_driver = {
        .set_config_rom         = ohci_set_config_rom,
        .send_request           = ohci_send_request,
        .send_response          = ohci_send_response,
+       .cancel_packet          = ohci_cancel_packet,
        .enable_phys_dma        = ohci_enable_phys_dma,
 
        .allocate_iso_context   = ohci_allocate_iso_context,
        .free_iso_context       = ohci_free_iso_context,
        .queue_iso              = ohci_queue_iso,
-       .send_iso               = ohci_send_iso
+       .send_iso               = ohci_send_iso,
 };
 
 static int software_reset(struct fw_ohci *ohci)