]> err.no Git - linux-2.6/commitdiff
firewire: don't respond to broadcast write requests
authorStefan Richter <stefanr@s5r6.in-berlin.de>
Sun, 25 May 2008 09:06:55 +0000 (11:06 +0200)
committerStefan Richter <stefanr@s5r6.in-berlin.de>
Mon, 14 Jul 2008 11:06:03 +0000 (13:06 +0200)
Contrary to a comment in the source, request->ack of a broadcast write
request can be ACK_PENDING.  Hence the existing check is insufficient.

Debug dmesg before:
AR spd 0 tl 00, ffc0 -> ffff, ack_pending , QW req, fffff0000234 = ffffffff
AT spd 0 tl 00, ffff -> ffc0, ack_complete, W resp
And the requesting node (linux1394) reports an unsolicited response.

Debug dmesg after:
AR spd 0 tl 00, ffc0 -> ffff, ack_pending , QW req, fffff0000234 = ffffffff

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
drivers/firewire/fw-transaction.c

index 2f11ed1acf018d092d4a9ce9d58f473aaddf6f4c..40db8075227259c849007a92b4ea9c045745d9b2 100644 (file)
@@ -55,6 +55,9 @@
 #define HEADER_GET_DATA_LENGTH(q)      (((q) >> 16) & 0xffff)
 #define HEADER_GET_EXTENDED_TCODE(q)   (((q) >> 0) & 0xffff)
 
+#define HEADER_DESTINATION_IS_BROADCAST(q) \
+       (((q) & HEADER_DESTINATION(0x3f)) == HEADER_DESTINATION(0x3f))
+
 #define PHY_CONFIG_GAP_COUNT(gap_count)        (((gap_count) << 16) | (1 << 22))
 #define PHY_CONFIG_ROOT_ID(node_id)    ((((node_id) & 0x3f) << 24) | (1 << 23))
 #define PHY_IDENTIFIER(id)             ((id) << 30)
@@ -624,12 +627,9 @@ allocate_request(struct fw_packet *p)
 void
 fw_send_response(struct fw_card *card, struct fw_request *request, int rcode)
 {
-       /*
-        * Broadcast packets are reported as ACK_COMPLETE, so this
-        * check is sufficient to ensure we don't send response to
-        * broadcast packets or posted writes.
-        */
-       if (request->ack != ACK_PENDING) {
+       /* unified transaction or broadcast transaction: don't respond */
+       if (request->ack != ACK_PENDING ||
+           HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) {
                kfree(request);
                return;
        }