Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions drivers/net/ethernet/cadence/macb.h
Original file line number Diff line number Diff line change
Expand Up @@ -996,13 +996,16 @@ struct macb_dma_desc_ptp {
* of the frame
* @mapping: DMA address of the skb's fragment buffer
* @size: size of the DMA mapped buffer
* @skb_len: skb->len as handed over by the stack, before padding and
* software FCS, only set for the last buffer of the frame
* @mapped_as_page: true when buffer was mapped with skb_frag_dma_map(),
* false when buffer was mapped with dma_map_single()
*/
struct macb_tx_skb {
struct sk_buff *skb;
dma_addr_t mapping;
size_t size;
unsigned int skb_len;
bool mapped_as_page;
};

Expand Down
24 changes: 17 additions & 7 deletions drivers/net/ethernet/cadence/macb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1355,8 +1355,8 @@ static void macb_tx_error_task(struct work_struct *work)
bp->dev->stats.tx_packets++;
queue->stats.tx_packets++;
packets++;
bp->dev->stats.tx_bytes += skb->len;
queue->stats.tx_bytes += skb->len;
bp->dev->stats.tx_bytes += tx_skb->skb_len;
queue->stats.tx_bytes += tx_skb->skb_len;
bytes += skb->len;
}
} else {
Expand Down Expand Up @@ -1483,8 +1483,8 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
skb->data);
bp->dev->stats.tx_packets++;
queue->stats.tx_packets++;
bp->dev->stats.tx_bytes += skb->len;
queue->stats.tx_bytes += skb->len;
bp->dev->stats.tx_bytes += tx_skb->skb_len;
queue->stats.tx_bytes += tx_skb->skb_len;
packets++;
bytes += skb->len;
}
Expand Down Expand Up @@ -2262,7 +2262,8 @@ static void macb_poll_controller(struct net_device *dev)
static unsigned int macb_tx_map(struct macb *bp,
struct macb_queue *queue,
struct sk_buff *skb,
unsigned int hdrlen)
unsigned int hdrlen,
unsigned int skb_len)
{
dma_addr_t mapping;
unsigned int len, entry, i, tx_head = queue->tx_head;
Expand Down Expand Up @@ -2351,6 +2352,7 @@ static unsigned int macb_tx_map(struct macb *bp,

/* This is the last buffer of the frame: save socket buffer */
tx_skb->skb = skb;
tx_skb->skb_len = skb_len;

/* Update TX ring: update buffer descriptors in reverse order
* to avoid race condition
Expand Down Expand Up @@ -2474,6 +2476,13 @@ static inline int macb_clear_csum(struct sk_buff *skb)
if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;

/* The hardware lacks the RFC 768 substitution of 0xffff for a
* UDP checksum that computes to zero, complete UDP in software.
*/
if (skb->csum_offset == offsetof(struct udphdr, check) &&
!ptp_one_step_sync(skb))
return skb_checksum_help(skb);

/* make sure we can modify the header */
if (unlikely(skb_cow_head(skb, 0)))
return -1;
Expand Down Expand Up @@ -2543,7 +2552,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct macb *bp = netdev_priv(dev);
struct macb_queue *queue = &bp->queues[queue_index];
unsigned int desc_cnt, nr_frags, frag_size, f;
unsigned int hdrlen;
unsigned int hdrlen, skb_len;
unsigned long flags;
bool is_lso;
netdev_tx_t ret = NETDEV_TX_OK;
Expand All @@ -2553,6 +2562,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
return ret;
}

skb_len = skb->len;
if (macb_pad_and_fcs(&skb, dev)) {
dev_kfree_skb_any(skb);
return ret;
Expand Down Expand Up @@ -2618,7 +2628,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
}

/* Map socket buffer for DMA transfer */
if (!macb_tx_map(bp, queue, skb, hdrlen)) {
if (!macb_tx_map(bp, queue, skb, hdrlen, skb_len)) {
dev_kfree_skb_any(skb);
goto unlock;
}
Expand Down
Loading