diff options
author | Kristian Høgsberg <krh@redhat.com> | 2007-01-26 00:38:04 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-03-09 16:02:46 -0500 |
commit | e636fe2576be552252a5b63e9287915e810b37d8 (patch) | |
tree | 35aadb0e66dc316863fe1570d1a2827f10b4786d /drivers/firewire/fw-ohci.c | |
parent | 2639a6fb268e1f2a7700fe3d31cbca9b39aa3ad9 (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.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 8dc872aedce7..5156329a8655 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -121,6 +121,7 @@ struct fw_ohci { | |||
121 | dma_addr_t self_id_bus; | 121 | dma_addr_t self_id_bus; |
122 | __le32 *self_id_cpu; | 122 | __le32 *self_id_cpu; |
123 | struct tasklet_struct bus_reset_tasklet; | 123 | struct tasklet_struct bus_reset_tasklet; |
124 | int node_id; | ||
124 | int generation; | 125 | int generation; |
125 | int request_generation; | 126 | int request_generation; |
126 | 127 | ||
@@ -538,29 +539,45 @@ at_context_init(struct at_context *ctx, struct fw_ohci *ohci, u32 control_set) | |||
538 | return 0; | 539 | return 0; |
539 | } | 540 | } |
540 | 541 | ||
542 | #define header_get_destination(q) (((q) >> 16) & 0xffff) | ||
543 | |||
541 | static void | 544 | static void |
542 | at_context_transmit(struct at_context *ctx, struct fw_packet *packet) | 545 | at_context_transmit(struct at_context *ctx, struct fw_packet *packet) |
543 | { | 546 | { |
544 | LIST_HEAD(list); | 547 | LIST_HEAD(list); |
545 | unsigned long flags; | 548 | unsigned long flags; |
546 | int was_empty; | 549 | int local; |
547 | 550 | ||
548 | spin_lock_irqsave(&ctx->ohci->lock, flags); | 551 | spin_lock_irqsave(&ctx->ohci->lock, flags); |
549 | 552 | ||
550 | was_empty = list_empty(&ctx->list); | 553 | if (header_get_destination(packet->header[0]) == ctx->ohci->node_id && |
551 | list_add_tail(&packet->link, &ctx->list); | 554 | ctx->ohci->generation == packet->generation) { |
552 | if (was_empty) | 555 | local = 1; |
553 | at_context_setup_packet(ctx, &list); | 556 | } else { |
557 | list_add_tail(&packet->link, &ctx->list); | ||
558 | if (ctx->list.next == &packet->link) | ||
559 | at_context_setup_packet(ctx, &list); | ||
560 | local = 0; | ||
561 | } | ||
554 | 562 | ||
555 | spin_unlock_irqrestore(&ctx->ohci->lock, flags); | 563 | spin_unlock_irqrestore(&ctx->ohci->lock, flags); |
556 | 564 | ||
557 | do_packet_callbacks(ctx->ohci, &list); | 565 | do_packet_callbacks(ctx->ohci, &list); |
566 | |||
567 | if (local) { | ||
568 | packet->ack = ACK_PENDING; | ||
569 | packet->callback(packet, &ctx->ohci->card, packet->ack); | ||
570 | if (ctx == &ctx->ohci->at_request_ctx) | ||
571 | fw_core_handle_request(&ctx->ohci->card, packet); | ||
572 | else | ||
573 | fw_core_handle_response(&ctx->ohci->card, packet); | ||
574 | } | ||
558 | } | 575 | } |
559 | 576 | ||
560 | static void bus_reset_tasklet(unsigned long data) | 577 | static void bus_reset_tasklet(unsigned long data) |
561 | { | 578 | { |
562 | struct fw_ohci *ohci = (struct fw_ohci *)data; | 579 | struct fw_ohci *ohci = (struct fw_ohci *)data; |
563 | int self_id_count, i, j, reg, node_id; | 580 | int self_id_count, i, j, reg; |
564 | int generation, new_generation; | 581 | int generation, new_generation; |
565 | unsigned long flags; | 582 | unsigned long flags; |
566 | 583 | ||
@@ -569,7 +586,7 @@ static void bus_reset_tasklet(unsigned long data) | |||
569 | fw_error("node ID not valid, new bus reset in progress\n"); | 586 | fw_error("node ID not valid, new bus reset in progress\n"); |
570 | return; | 587 | return; |
571 | } | 588 | } |
572 | node_id = reg & 0xffff; | 589 | ohci->node_id = reg & 0xffff; |
573 | 590 | ||
574 | /* The count in the SelfIDCount register is the number of | 591 | /* The count in the SelfIDCount register is the number of |
575 | * bytes in the self ID receive buffer. Since we also receive | 592 | * bytes in the self ID receive buffer. Since we also receive |
@@ -638,7 +655,7 @@ static void bus_reset_tasklet(unsigned long data) | |||
638 | 655 | ||
639 | spin_unlock_irqrestore(&ohci->lock, flags); | 656 | spin_unlock_irqrestore(&ohci->lock, flags); |
640 | 657 | ||
641 | fw_core_handle_bus_reset(&ohci->card, node_id, generation, | 658 | fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation, |
642 | self_id_count, ohci->self_id_buffer); | 659 | self_id_count, ohci->self_id_buffer); |
643 | } | 660 | } |
644 | 661 | ||