Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=473d28c730e2de888c24b226cfe4183868eacde2
Commit:     473d28c730e2de888c24b226cfe4183868eacde2
Parent:     7c6e647da00883ec2208171d51537f23498dd669
Author:     Kristian Høgsberg <[EMAIL PROTECTED]>
AuthorDate: Wed Mar 7 12:12:55 2007 -0500
Committer:  Stefan Richter <[EMAIL PROTECTED]>
CommitDate: Fri Mar 9 22:03:14 2007 +0100

    firewire: Implement topology map and fix a couple of loopback bugs.
    
    Signed-off-by: Kristian Høgsberg <[EMAIL PROTECTED]>
    Signed-off-by: Stefan Richter <[EMAIL PROTECTED]>
---
 drivers/firewire/fw-card.c        |    2 +-
 drivers/firewire/fw-ohci.c        |   11 ++++++-
 drivers/firewire/fw-topology.c    |   28 +++++++++++++++-----
 drivers/firewire/fw-topology.h    |    3 ++
 drivers/firewire/fw-transaction.c |   52 ++++++++++++++++++++++++++++++++++---
 drivers/firewire/fw-transaction.h |    5 ++-
 6 files changed, 85 insertions(+), 16 deletions(-)

diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index b1deb52..d929eb6 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -30,7 +30,7 @@
  * polynomial, but we need the ITU-T (or CCITT) polynomial (0x1021).
  * The implementation below works on an array of host-endian u32
  * words, assuming they'll be transmited msb first. */
-static u16
+u16
 crc16_itu_t(const u32 *buffer, size_t length)
 {
        int shift, i;
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 9e8a8f9..a9e1346 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -813,8 +813,10 @@ handle_local_request(struct context *ctx, struct fw_packet 
*packet)
        u64 offset;
        u32 csr;
 
-       packet->ack = ACK_PENDING;
-       packet->callback(packet, &ctx->ohci->card, packet->ack);
+       if (ctx == &ctx->ohci->at_request_ctx) {
+               packet->ack = ACK_PENDING;
+               packet->callback(packet, &ctx->ohci->card, packet->ack);
+       }
 
        offset =
                ((unsigned long long)
@@ -839,6 +841,11 @@ handle_local_request(struct context *ctx, struct fw_packet 
*packet)
                        fw_core_handle_response(&ctx->ohci->card, packet);
                break;
        }
+
+       if (ctx == &ctx->ohci->at_response_ctx) {
+               packet->ack = ACK_COMPLETE;
+               packet->callback(packet, &ctx->ohci->card, packet->ack);
+       }
 }
 
 static void
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 36c9be7..7923463 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -163,11 +163,12 @@ static void update_hop_count(struct fw_node *node)
  * internally consistent.  On succcess this funtions returns the
  * fw_node corresponding to the local card otherwise NULL.
  */
-static struct fw_node *build_tree(struct fw_card *card)
+static struct fw_node *build_tree(struct fw_card *card,
+                                 u32 *sid, int self_id_count)
 {
        struct fw_node *node, *child, *local_node;
        struct list_head stack, *h;
-       u32 *sid, *next_sid, *end, q;
+       u32 *next_sid, *end, q;
        int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
        int gap_count, topology_type;
 
@@ -175,8 +176,7 @@ static struct fw_node *build_tree(struct fw_card *card)
        node = NULL;
        INIT_LIST_HEAD(&stack);
        stack_depth = 0;
-       sid = card->self_ids;
-       end = sid + card->self_id_count;
+       end = sid + self_id_count;
        phy_id = 0;
        card->irm_node = NULL;
        gap_count = self_id_gap_count(*sid);
@@ -460,6 +460,20 @@ update_tree(struct fw_card *card, struct fw_node *root)
        }
 }
 
+static void
+update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count)
+{
+       int node_count;
+       u32 crc;
+
+       card->topology_map[1]++;
+       node_count = (card->root_node->node_id & 0x3f) + 1;
+       card->topology_map[2] = (node_count << 16) | self_id_count;
+       crc = crc16_itu_t(card->topology_map + 1, self_id_count + 2);
+       card->topology_map[0] = ((self_id_count + 2) << 16) | crc;
+       memcpy(&card->topology_map[3], self_ids, self_id_count * 4);
+}
+
 void
 fw_core_handle_bus_reset(struct fw_card *card,
                         int node_id, int generation,
@@ -479,13 +493,13 @@ fw_core_handle_bus_reset(struct fw_card *card,
                card->bm_retries = 0;
 
        card->node_id = node_id;
-       card->self_id_count = self_id_count;
        card->generation = generation;
-       memcpy(card->self_ids, self_ids, self_id_count * 4);
        card->reset_jiffies = jiffies;
        schedule_delayed_work(&card->work, 0);
 
-       local_node = build_tree(card);
+       local_node = build_tree(card, self_ids, self_id_count);
+
+       update_topology_map(card, self_ids, self_id_count);
 
        card->color++;
 
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index f2a575e..913bfe1 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -88,4 +88,7 @@ fw_node_put(struct fw_node *node)
 void
 fw_destroy_nodes(struct fw_card *card);
 
+u16
+crc16_itu_t(const u32 *buffer, size_t length);
+
 #endif /* __fw_topology_h */
diff --git a/drivers/firewire/fw-transaction.c 
b/drivers/firewire/fw-transaction.c
index 3052698..38b286e 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -140,7 +140,7 @@ transmit_complete_callback(struct fw_packet *packet,
 
 static void
 fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
-               int node_id, int generation, int speed,
+               int node_id, int source_id, int generation, int speed,
                unsigned long long offset, void *payload, size_t length)
 {
        int ext_tcode;
@@ -157,7 +157,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int 
tlabel,
                header_tcode(tcode) |
                header_destination(node_id);
        packet->header[1] =
-               header_offset_high(offset >> 32) | header_source(0);
+               header_offset_high(offset >> 32) | header_source(source_id);
        packet->header[2] =
                offset;
 
@@ -241,7 +241,7 @@ fw_send_request(struct fw_card *card, struct fw_transaction 
*t,
                fw_transaction_callback_t callback, void *callback_data)
 {
        unsigned long flags;
-       int tlabel;
+       int tlabel, source;
 
        /* Bump the flush timer up 100ms first of all so we
         * don't race with a flush timer callback. */
@@ -253,6 +253,7 @@ fw_send_request(struct fw_card *card, struct fw_transaction 
*t,
 
        spin_lock_irqsave(&card->lock, flags);
 
+       source = card->node_id;
        tlabel = card->current_tlabel;
        if (card->tlabel_mask & (1 << tlabel)) {
                spin_unlock_irqrestore(&card->lock, flags);
@@ -274,7 +275,8 @@ fw_send_request(struct fw_card *card, struct fw_transaction 
*t,
        t->callback_data = callback_data;
 
        fw_fill_request(&t->packet, tcode, t->tlabel,
-                       node_id, generation, speed, offset, payload, length);
+                       node_id, source, generation,
+                       speed, offset, payload, length);
        t->packet.callback = transmit_complete_callback;
 
        card->driver->send_request(card, &t->packet);
@@ -716,6 +718,44 @@ fw_core_handle_response(struct fw_card *card, struct 
fw_packet *p)
 }
 EXPORT_SYMBOL(fw_core_handle_response);
 
+const struct fw_address_region topology_map_region =
+       { .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, };
+
+static void
+handle_topology_map(struct fw_card *card, struct fw_request *request,
+                   int tcode, int destination, int source,
+                   int generation, int speed,
+                   unsigned long long offset,
+                   void *payload, size_t length, void *callback_data)
+{
+       int i, start, end;
+       u32 *map;
+
+       if (!TCODE_IS_READ_REQUEST(tcode)) {
+               fw_send_response(card, request, RCODE_TYPE_ERROR);
+               return;
+       }
+
+       if ((offset & 3) > 0 || (length & 3) > 0) {
+               fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+               return;
+       }
+
+       start = (offset - topology_map_region.start) / 4;
+       end = start + length / 4;
+       map = payload;
+
+       for (i = 0; i < length / 4; i++)
+               map[i] = cpu_to_be32(card->topology_map[start + i]);
+
+       fw_send_response(card, request, RCODE_COMPLETE);
+}
+
+static struct fw_address_handler topology_map = {
+       .length                 = 0x400,
+       .address_callback       = handle_topology_map,
+};
+
 MODULE_AUTHOR("Kristian Hoegsberg <[EMAIL PROTECTED]>");
 MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
 MODULE_LICENSE("GPL");
@@ -767,6 +807,10 @@ static int __init fw_core_init(void)
                return fw_cdev_major;
        }
 
+       retval = fw_core_add_address_handler(&topology_map,
+                                            &topology_map_region);
+       BUG_ON(retval < 0);
+
        /* Add the vendor textual descriptor. */
        retval = fw_core_add_descriptor(&vendor_id_descriptor);
        BUG_ON(retval < 0);
diff --git a/drivers/firewire/fw-transaction.h 
b/drivers/firewire/fw-transaction.h
index e7301b8..a661afb 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -285,9 +285,10 @@ struct fw_card {
        int link_speed;
        int config_rom_generation;
 
-       /* We need to store up to 4 self ID for a maximum of 63 devices. */
+       /* We need to store up to 4 self ID for a maximum of 63
+        * devices plus 3 words for the topology map header. */
        int self_id_count;
-       u32 self_ids[252];
+       u32 topology_map[252 + 3];
 
        spinlock_t lock; /* Take this lock when handling the lists in
                          * this struct. */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to