in net.c [827:902]
static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
{
struct fwnet_device *dev = ptask->dev;
struct sk_buff *skb = ptask->skb;
unsigned long flags;
bool free;
spin_lock_irqsave(&dev->lock, flags);
ptask->outstanding_pkts--;
/* Check whether we or the networking TX soft-IRQ is last user. */
free = (ptask->outstanding_pkts == 0 && ptask->enqueued);
if (free)
dec_queued_datagrams(dev);
if (ptask->outstanding_pkts == 0) {
dev->netdev->stats.tx_packets++;
dev->netdev->stats.tx_bytes += skb->len;
}
spin_unlock_irqrestore(&dev->lock, flags);
if (ptask->outstanding_pkts > 0) {
u16 dg_size;
u16 fg_off;
u16 datagram_label;
u16 lf;
/* Update the ptask to point to the next fragment and send it */
lf = fwnet_get_hdr_lf(&ptask->hdr);
switch (lf) {
case RFC2374_HDR_LASTFRAG:
case RFC2374_HDR_UNFRAG:
default:
dev_err(&dev->netdev->dev,
"outstanding packet %x lf %x, header %x,%x\n",
ptask->outstanding_pkts, lf, ptask->hdr.w0,
ptask->hdr.w1);
BUG();
case RFC2374_HDR_FIRSTFRAG:
/* Set frag type here for future interior fragments */
dg_size = fwnet_get_hdr_dg_size(&ptask->hdr);
fg_off = ptask->max_payload - RFC2374_FRAG_HDR_SIZE;
datagram_label = fwnet_get_hdr_dgl(&ptask->hdr);
break;
case RFC2374_HDR_INTFRAG:
dg_size = fwnet_get_hdr_dg_size(&ptask->hdr);
fg_off = fwnet_get_hdr_fg_off(&ptask->hdr)
+ ptask->max_payload - RFC2374_FRAG_HDR_SIZE;
datagram_label = fwnet_get_hdr_dgl(&ptask->hdr);
break;
}
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);
} else {
fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_LASTFRAG,
dg_size, fg_off, datagram_label);
ptask->max_payload = skb->len + RFC2374_FRAG_HDR_SIZE;
}
fwnet_send_packet(ptask);
}
if (free)
fwnet_free_ptask(ptask);
}