aboutsummaryrefslogtreecommitdiff
path: root/drivers/firewire
diff options
context:
space:
mode:
authorStephan Gatzka <stephan.gatzka@gmail.com>2012-11-28 20:04:32 +0100
committerBen Hutchings <ben@decadent.org.uk>2013-01-03 03:33:24 +0000
commitc14e119fb971506913bbbb8709c85f7716f97c3f (patch)
treebcb708cc23959eb56a1586b837c421d7e5bf9fb9 /drivers/firewire
parent51e8eac1d5138ab32debce67202b975c08920029 (diff)
firewire: net: Fix handling of fragmented multicast/broadcast packets.
commit 9d2373420900a39f5212a3b289331aa3535b1000 upstream. This patch fixes both the transmit and receive portion of sending fragmented mutlicast and broadcast packets. The transmit section was broken because the offset for INTFRAG and LASTFRAG packets were just miscalculated by IEEE1394_GASP_HDR_SIZE (which was reserved with skb_push() in fwnet_send_packet). The receive section was broken because in fwnet_incoming_packet is a call to fwnet_peer_find_by_node_id(). Called with generation == -1 it will not find a peer and the partial datagrams are associated to a peer. [Stefan R: The fix to use context->card->generation is not perfect. It relies on the IR tasklet which processes packets from the prior bus generation to run before the self-ID-complete worklet which sets the current card generation. Alas, there is no simple way of a race-free implementation. Let's do it this way for now.] Signed-off-by: Stephan Gatzka <stephan.gatzka@gmail.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/net.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index a20f45b1e7e..7c869b73a57 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -860,8 +860,8 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) {
buf_ptr += 2;
length -= IEEE1394_GASP_HDR_SIZE;
- fwnet_incoming_packet(dev, buf_ptr, length,
- source_node_id, -1, true);
+ fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
+ context->card->generation, true);
}
packet.payload_length = dev->rcv_buffer_size;
@@ -956,7 +956,12 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
break;
}
- skb_pull(skb, ptask->max_payload);
+ if (ptask->dest_node == IEEE1394_ALL_NODES) {
+ skb_pull(skb,
+ ptask->max_payload + IEEE1394_GASP_HDR_SIZE);
+ } else {
+ skb_pull(skb, ptask->max_payload);
+ }
if (ptask->outstanding_pkts > 1) {
fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG,
dg_size, fg_off, datagram_label);
@@ -1059,7 +1064,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
smp_rmb();
node_id = dev->card->node_id;
- p = skb_push(ptask->skb, 8);
+ p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE);
put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p);
put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24
| RFC2734_SW_VERSION, &p[4]);