aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r--drivers/ieee1394/eth1394.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 5f026b5d7857..7c13fb3c167b 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -1565,7 +1565,7 @@ static void ether1394_complete_cb(void *__ptask)
1565/* Transmit a packet (called by kernel) */ 1565/* Transmit a packet (called by kernel) */
1566static int ether1394_tx(struct sk_buff *skb, struct net_device *dev) 1566static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
1567{ 1567{
1568 struct eth1394hdr *eth; 1568 struct eth1394hdr hdr_buf;
1569 struct eth1394_priv *priv = netdev_priv(dev); 1569 struct eth1394_priv *priv = netdev_priv(dev);
1570 __be16 proto; 1570 __be16 proto;
1571 unsigned long flags; 1571 unsigned long flags;
@@ -1595,16 +1595,17 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
1595 if (!skb) 1595 if (!skb)
1596 goto fail; 1596 goto fail;
1597 1597
1598 /* Get rid of the fake eth1394 header, but save a pointer */ 1598 /* Get rid of the fake eth1394 header, but first make a copy.
1599 eth = (struct eth1394hdr *)skb->data; 1599 * We might need to rebuild the header on tx failure. */
1600 memcpy(&hdr_buf, skb->data, sizeof(hdr_buf));
1600 skb_pull(skb, ETH1394_HLEN); 1601 skb_pull(skb, ETH1394_HLEN);
1601 1602
1602 proto = eth->h_proto; 1603 proto = hdr_buf.h_proto;
1603 dg_size = skb->len; 1604 dg_size = skb->len;
1604 1605
1605 /* Set the transmission type for the packet. ARP packets and IP 1606 /* Set the transmission type for the packet. ARP packets and IP
1606 * broadcast packets are sent via GASP. */ 1607 * broadcast packets are sent via GASP. */
1607 if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 || 1608 if (memcmp(hdr_buf.h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
1608 proto == htons(ETH_P_ARP) || 1609 proto == htons(ETH_P_ARP) ||
1609 (proto == htons(ETH_P_IP) && 1610 (proto == htons(ETH_P_IP) &&
1610 IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) { 1611 IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
@@ -1616,7 +1617,7 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
1616 if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) 1617 if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
1617 priv->bc_dgl++; 1618 priv->bc_dgl++;
1618 } else { 1619 } else {
1619 __be64 guid = get_unaligned((u64 *)eth->h_dest); 1620 __be64 guid = get_unaligned((u64 *)hdr_buf.h_dest);
1620 1621
1621 node = eth1394_find_node_guid(&priv->ip_node_list, 1622 node = eth1394_find_node_guid(&priv->ip_node_list,
1622 be64_to_cpu(guid)); 1623 be64_to_cpu(guid));
@@ -1673,6 +1674,14 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
1673 if (dest_node == (LOCAL_BUS | ALL_NODES)) 1674 if (dest_node == (LOCAL_BUS | ALL_NODES))
1674 goto fail; 1675 goto fail;
1675 1676
1677 /* At this point we want to restore the packet. When we return
1678 * here with NETDEV_TX_BUSY we will get another entrance in this
1679 * routine with the same skb and we need it to look the same.
1680 * So we pull 4 more bytes, then build the header again. */
1681 skb_pull(skb, 4);
1682 ether1394_header(skb, dev, ntohs(hdr_buf.h_proto),
1683 hdr_buf.h_dest, NULL, 0);
1684
1676 /* Most failures of ether1394_send_packet are recoverable. */ 1685 /* Most failures of ether1394_send_packet are recoverable. */
1677 netif_stop_queue(dev); 1686 netif_stop_queue(dev);
1678 priv->wake_node = dest_node; 1687 priv->wake_node = dest_node;