summaryrefslogtreecommitdiff
path: root/drivers/firewire/fw-ohci.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-01-26 00:38:04 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 22:02:46 +0100
commite636fe2576be552252a5b63e9287915e810b37d8 (patch)
tree35aadb0e66dc316863fe1570d1a2827f10b4786d /drivers/firewire/fw-ohci.c
parent2639a6fb268e1f2a7700fe3d31cbca9b39aa3ad9 (diff)
firewire: Loop requests to the host controller back into the stack.
Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-ohci.c')
-rw-r--r--drivers/firewire/fw-ohci.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 8dc872aedce..5156329a865 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -121,6 +121,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;
@@ -538,29 +539,45 @@ at_context_init(struct at_context *ctx, struct fw_ohci *ohci, u32 control_set)
return 0;
}
+#define header_get_destination(q) (((q) >> 16) & 0xffff)
+
static void
at_context_transmit(struct at_context *ctx, struct fw_packet *packet)
{
LIST_HEAD(list);
unsigned long flags;
- int was_empty;
+ int local;
spin_lock_irqsave(&ctx->ohci->lock, flags);
- was_empty = list_empty(&ctx->list);
- list_add_tail(&packet->link, &ctx->list);
- if (was_empty)
- at_context_setup_packet(ctx, &list);
+ if (header_get_destination(packet->header[0]) == ctx->ohci->node_id &&
+ ctx->ohci->generation == packet->generation) {
+ local = 1;
+ } else {
+ list_add_tail(&packet->link, &ctx->list);
+ if (ctx->list.next == &packet->link)
+ at_context_setup_packet(ctx, &list);
+ local = 0;
+ }
spin_unlock_irqrestore(&ctx->ohci->lock, flags);
do_packet_callbacks(ctx->ohci, &list);
+
+ if (local) {
+ packet->ack = ACK_PENDING;
+ packet->callback(packet, &ctx->ohci->card, packet->ack);
+ if (ctx == &ctx->ohci->at_request_ctx)
+ fw_core_handle_request(&ctx->ohci->card, packet);
+ else
+ fw_core_handle_response(&ctx->ohci->card, 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;
@@ -569,7 +586,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
@@ -638,7 +655,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);
}