Commit 0a8fa933 authored by Ezequiel Garcia's avatar Ezequiel Garcia Committed by David S. Miller

net: mv643xx_eth: Factorize initial checksum and command preparation

Make the code more readable by moving the initial checksum setup
and the command/status preparation to its own function.
Signed-off-by: default avatarEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2adb719d
...@@ -661,6 +661,64 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb) ...@@ -661,6 +661,64 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
return 0; return 0;
} }
static inline __be16 sum16_as_be(__sum16 sum)
{
return (__force __be16)sum;
}
static int skb_tx_csum(struct mv643xx_eth_private *mp, struct sk_buff *skb,
u16 *l4i_chk, u32 *command, int length)
{
int ret;
u32 cmd = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
int hdr_len;
int tag_bytes;
BUG_ON(skb->protocol != htons(ETH_P_IP) &&
skb->protocol != htons(ETH_P_8021Q));
hdr_len = (void *)ip_hdr(skb) - (void *)skb->data;
tag_bytes = hdr_len - ETH_HLEN;
if (length - hdr_len > mp->shared->tx_csum_limit ||
unlikely(tag_bytes & ~12)) {
ret = skb_checksum_help(skb);
if (!ret)
goto no_csum;
return ret;
}
if (tag_bytes & 4)
cmd |= MAC_HDR_EXTRA_4_BYTES;
if (tag_bytes & 8)
cmd |= MAC_HDR_EXTRA_8_BYTES;
cmd |= GEN_TCP_UDP_CHECKSUM |
GEN_IP_V4_CHECKSUM |
ip_hdr(skb)->ihl << TX_IHL_SHIFT;
switch (ip_hdr(skb)->protocol) {
case IPPROTO_UDP:
cmd |= UDP_FRAME;
*l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check));
break;
case IPPROTO_TCP:
*l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check));
break;
default:
WARN(1, "protocol not supported");
}
} else {
no_csum:
/* Errata BTS #50, IHL must be 5 if no HW checksum */
cmd |= 5 << TX_IHL_SHIFT;
}
*command = cmd;
return 0;
}
static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb) static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
{ {
struct mv643xx_eth_private *mp = txq_to_mp(txq); struct mv643xx_eth_private *mp = txq_to_mp(txq);
...@@ -699,11 +757,6 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb) ...@@ -699,11 +757,6 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
} }
} }
static inline __be16 sum16_as_be(__sum16 sum)
{
return (__force __be16)sum;
}
static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
{ {
struct mv643xx_eth_private *mp = txq_to_mp(txq); struct mv643xx_eth_private *mp = txq_to_mp(txq);
...@@ -712,53 +765,17 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) ...@@ -712,53 +765,17 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
struct tx_desc *desc; struct tx_desc *desc;
u32 cmd_sts; u32 cmd_sts;
u16 l4i_chk; u16 l4i_chk;
int length; int length, ret;
cmd_sts = TX_FIRST_DESC | GEN_CRC | BUFFER_OWNED_BY_DMA; cmd_sts = 0;
l4i_chk = 0; l4i_chk = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) { ret = skb_tx_csum(mp, skb, &l4i_chk, &cmd_sts, skb->len);
int hdr_len; if (ret) {
int tag_bytes;
BUG_ON(skb->protocol != htons(ETH_P_IP) &&
skb->protocol != htons(ETH_P_8021Q));
hdr_len = (void *)ip_hdr(skb) - (void *)skb->data;
tag_bytes = hdr_len - ETH_HLEN;
if (skb->len - hdr_len > mp->shared->tx_csum_limit ||
unlikely(tag_bytes & ~12)) {
if (skb_checksum_help(skb) == 0)
goto no_csum;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return 1; return ret;
}
if (tag_bytes & 4)
cmd_sts |= MAC_HDR_EXTRA_4_BYTES;
if (tag_bytes & 8)
cmd_sts |= MAC_HDR_EXTRA_8_BYTES;
cmd_sts |= GEN_TCP_UDP_CHECKSUM |
GEN_IP_V4_CHECKSUM |
ip_hdr(skb)->ihl << TX_IHL_SHIFT;
switch (ip_hdr(skb)->protocol) {
case IPPROTO_UDP:
cmd_sts |= UDP_FRAME;
l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check));
break;
case IPPROTO_TCP:
l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check));
break;
default:
BUG();
}
} else {
no_csum:
/* Errata BTS #50, IHL must be 5 if no HW checksum */
cmd_sts |= 5 << TX_IHL_SHIFT;
} }
cmd_sts |= TX_FIRST_DESC | GEN_CRC | BUFFER_OWNED_BY_DMA;
tx_index = txq->tx_curr_desc++; tx_index = txq->tx_curr_desc++;
if (txq->tx_curr_desc == txq->tx_ring_size) if (txq->tx_curr_desc == txq->tx_ring_size)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment