aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorStephan Gatzka <stephan.gatzka@gmail.com>2012-11-28 14:04:32 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2012-12-02 14:10:18 -0500
commit9d2373420900a39f5212a3b289331aa3535b1000 (patch)
tree1c32c42ffb39a7b3213ae7650c01517aa41909f0 /drivers/firewire
parentb0ea5f19d3d848008d87e455c8d9b6d9cae7101a (diff)
firewire: net: Fix handling of fragmented multicast/broadcast packets.
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> Cc: stable <stable@vger.kernel.org> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
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 08c674957af8..638e1f71284a 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -861,8 +861,8 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
861 if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) { 861 if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) {
862 buf_ptr += 2; 862 buf_ptr += 2;
863 length -= IEEE1394_GASP_HDR_SIZE; 863 length -= IEEE1394_GASP_HDR_SIZE;
864 fwnet_incoming_packet(dev, buf_ptr, length, 864 fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
865 source_node_id, -1, true); 865 context->card->generation, true);
866 } 866 }
867 867
868 packet.payload_length = dev->rcv_buffer_size; 868 packet.payload_length = dev->rcv_buffer_size;
@@ -958,7 +958,12 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
958 break; 958 break;
959 } 959 }
960 960
961 skb_pull(skb, ptask->max_payload); 961 if (ptask->dest_node == IEEE1394_ALL_NODES) {
962 skb_pull(skb,
963 ptask->max_payload + IEEE1394_GASP_HDR_SIZE);
964 } else {
965 skb_pull(skb, ptask->max_payload);
966 }
962 if (ptask->outstanding_pkts > 1) { 967 if (ptask->outstanding_pkts > 1) {
963 fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG, 968 fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG,
964 dg_size, fg_off, datagram_label); 969 dg_size, fg_off, datagram_label);
@@ -1062,7 +1067,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
1062 smp_rmb(); 1067 smp_rmb();
1063 node_id = dev->card->node_id; 1068 node_id = dev->card->node_id;
1064 1069
1065 p = skb_push(ptask->skb, 8); 1070 p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE);
1066 put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p); 1071 put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p);
1067 put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24 1072 put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24
1068 | RFC2734_SW_VERSION, &p[4]); 1073 | RFC2734_SW_VERSION, &p[4]);