Commit 401c0aab authored by Jay Cliburn's avatar Jay Cliburn Committed by Jeff Garzik

atl1: simplify tx packet descriptor

The transmit packet descriptor consists of four 32-bit words, with word 3
upper bits overloaded depending upon the condition of its bits 3 and 4.
The driver currently duplicates all word 2 and some word 3 register bit
definitions unnecessarily and also uses a set of nested structures in its
definition of the TPD without good cause. This patch adds a lengthy
comment describing the TPD, eliminates duplicate TPD bit definitions,
and simplifies the TPD structure itself. It also expands the TSO check
to correctly handle custom checksum versus TSO processing using the revised
TPD definitions. Finally, shorten some variable names in the transmit
processing path to reduce line lengths, rename some variables to better
describe their purpose (e.g., nseg versus m), and add a comment or two
to better describe what the code is doing.
Signed-off-by: default avatarJay Cliburn <jacliburn@bellsouth.net>
Acked-by: default avatarChris Snook <csnook@redhat.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent c67c9a2f
...@@ -1259,8 +1259,6 @@ static void atl1_intr_tx(struct atl1_adapter *adapter) ...@@ -1259,8 +1259,6 @@ static void atl1_intr_tx(struct atl1_adapter *adapter)
dev_kfree_skb_irq(buffer_info->skb); dev_kfree_skb_irq(buffer_info->skb);
buffer_info->skb = NULL; buffer_info->skb = NULL;
} }
tpd->buffer_addr = 0;
tpd->desc.data = 0;
if (++sw_tpd_next_to_clean == tpd_ring->count) if (++sw_tpd_next_to_clean == tpd_ring->count)
sw_tpd_next_to_clean = 0; sw_tpd_next_to_clean = 0;
...@@ -1282,48 +1280,69 @@ static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring) ...@@ -1282,48 +1280,69 @@ static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
} }
static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
struct tso_param *tso) struct tx_packet_desc *ptpd)
{ {
/* We enter this function holding a spinlock. */ /* spinlock held */
u8 ipofst; u8 hdr_len, ip_off;
u32 real_len;
int err; int err;
if (skb_shinfo(skb)->gso_size) { if (skb_shinfo(skb)->gso_size) {
if (skb_header_cloned(skb)) { if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (unlikely(err)) if (unlikely(err))
return err; return -1;
} }
if (skb->protocol == ntohs(ETH_P_IP)) { if (skb->protocol == ntohs(ETH_P_IP)) {
struct iphdr *iph = ip_hdr(skb); struct iphdr *iph = ip_hdr(skb);
iph->tot_len = 0; real_len = (((unsigned char *)iph - skb->data) +
ntohs(iph->tot_len));
if (real_len < skb->len)
pskb_trim(skb, real_len);
hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
if (skb->len == hdr_len) {
iph->check = 0;
tcp_hdr(skb)->check =
~csum_tcpudp_magic(iph->saddr,
iph->daddr, tcp_hdrlen(skb),
IPPROTO_TCP, 0);
ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
TPD_IPHL_SHIFT;
ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
TPD_TCPHDRLEN_MASK) <<
TPD_TCPHDRLEN_SHIFT;
ptpd->word3 |= 1 << TPD_IP_CSUM_SHIFT;
ptpd->word3 |= 1 << TPD_TCP_CSUM_SHIFT;
return 1;
}
iph->check = 0; iph->check = 0;
tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
iph->daddr, 0, IPPROTO_TCP, 0); iph->daddr, 0, IPPROTO_TCP, 0);
ipofst = skb_network_offset(skb); ip_off = (unsigned char *)iph -
if (ipofst != ETH_HLEN) /* 802.3 frame */ (unsigned char *) skb_network_header(skb);
tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT; if (ip_off == 8) /* 802.3-SNAP frame */
ptpd->word3 |= 1 << TPD_ETHTYPE_SHIFT;
tso->tsopl |= (iph->ihl & else if (ip_off != 0)
TSO_PARAM_IPHL_MASK) << TSO_PARAM_IPHL_SHIFT; return -2;
tso->tsopl |= ((tcp_hdrlen(skb) >> 2) &
TSO_PARAM_TCPHDRLEN_MASK) << ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
TSO_PARAM_TCPHDRLEN_SHIFT; TPD_IPHL_SHIFT;
tso->tsopl |= (skb_shinfo(skb)->gso_size & ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT; TPD_TCPHDRLEN_MASK) << TPD_TCPHDRLEN_SHIFT;
tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT; ptpd->word3 |= (skb_shinfo(skb)->gso_size &
tso->tsopl |= 1 << TSO_PARAM_TCPCKSUM_SHIFT; TPD_MSS_MASK) << TPD_MSS_SHIFT;
tso->tsopl |= 1 << TSO_PARAM_SEGMENT_SHIFT; ptpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
return true; return 3;
} }
} }
return false; return false;
} }
static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
struct csum_param *csum) struct tx_packet_desc *ptpd)
{ {
u8 css, cso; u8 css, cso;
...@@ -1335,115 +1354,116 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, ...@@ -1335,115 +1354,116 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
"payload offset not an even number\n"); "payload offset not an even number\n");
return -1; return -1;
} }
csum->csumpl |= (cso & CSUM_PARAM_PLOADOFFSET_MASK) << ptpd->word3 |= (cso & TPD_PLOADOFFSET_MASK) <<
CSUM_PARAM_PLOADOFFSET_SHIFT; TPD_PLOADOFFSET_SHIFT;
csum->csumpl |= (css & CSUM_PARAM_XSUMOFFSET_MASK) << ptpd->word3 |= (css & TPD_CCSUMOFFSET_MASK) <<
CSUM_PARAM_XSUMOFFSET_SHIFT; TPD_CCSUMOFFSET_SHIFT;
csum->csumpl |= 1 << CSUM_PARAM_CUSTOMCKSUM_SHIFT; ptpd->word3 |= 1 << TPD_CUST_CSUM_EN_SHIFT;
return true; return true;
} }
return 0;
return true;
} }
static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
bool tcp_seg) struct tx_packet_desc *ptpd)
{ {
/* We enter this function holding a spinlock. */ /* spinlock held */
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
struct atl1_buffer *buffer_info; struct atl1_buffer *buffer_info;
u16 buf_len = skb->len;
struct page *page; struct page *page;
int first_buf_len = skb->len;
unsigned long offset; unsigned long offset;
unsigned int nr_frags; unsigned int nr_frags;
unsigned int f; unsigned int f;
u16 tpd_next_to_use; int retval;
u16 proto_hdr_len; u16 next_to_use;
u16 len12; u16 data_len;
u8 hdr_len;
first_buf_len -= skb->data_len; buf_len -= skb->data_len;
nr_frags = skb_shinfo(skb)->nr_frags; nr_frags = skb_shinfo(skb)->nr_frags;
tpd_next_to_use = atomic_read(&tpd_ring->next_to_use); next_to_use = atomic_read(&tpd_ring->next_to_use);
buffer_info = &tpd_ring->buffer_info[tpd_next_to_use]; buffer_info = &tpd_ring->buffer_info[next_to_use];
if (unlikely(buffer_info->skb)) if (unlikely(buffer_info->skb))
BUG(); BUG();
/* put skb in last TPD */ /* put skb in last TPD */
buffer_info->skb = NULL; buffer_info->skb = NULL;
if (tcp_seg) { retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
/* TSO/GSO */ if (retval) {
proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); /* TSO */
buffer_info->length = proto_hdr_len; hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
buffer_info->length = hdr_len;
page = virt_to_page(skb->data); page = virt_to_page(skb->data);
offset = (unsigned long)skb->data & ~PAGE_MASK; offset = (unsigned long)skb->data & ~PAGE_MASK;
buffer_info->dma = pci_map_page(adapter->pdev, page, buffer_info->dma = pci_map_page(adapter->pdev, page,
offset, proto_hdr_len, offset, hdr_len,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
if (++tpd_next_to_use == tpd_ring->count) if (++next_to_use == tpd_ring->count)
tpd_next_to_use = 0; next_to_use = 0;
if (first_buf_len > proto_hdr_len) { if (buf_len > hdr_len) {
int i, m; int i, nseg;
len12 = first_buf_len - proto_hdr_len; data_len = buf_len - hdr_len;
m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) / nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
ATL1_MAX_TX_BUF_LEN; ATL1_MAX_TX_BUF_LEN;
for (i = 0; i < m; i++) { for (i = 0; i < nseg; i++) {
buffer_info = buffer_info =
&tpd_ring->buffer_info[tpd_next_to_use]; &tpd_ring->buffer_info[next_to_use];
buffer_info->skb = NULL; buffer_info->skb = NULL;
buffer_info->length = buffer_info->length =
(ATL1_MAX_TX_BUF_LEN >= (ATL1_MAX_TX_BUF_LEN >=
len12) ? ATL1_MAX_TX_BUF_LEN : len12; data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
len12 -= buffer_info->length; data_len -= buffer_info->length;
page = virt_to_page(skb->data + page = virt_to_page(skb->data +
(proto_hdr_len + (hdr_len + i * ATL1_MAX_TX_BUF_LEN));
i * ATL1_MAX_TX_BUF_LEN));
offset = (unsigned long)(skb->data + offset = (unsigned long)(skb->data +
(proto_hdr_len + (hdr_len + i * ATL1_MAX_TX_BUF_LEN)) &
i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK; ~PAGE_MASK;
buffer_info->dma = pci_map_page(adapter->pdev, buffer_info->dma = pci_map_page(adapter->pdev,
page, offset, buffer_info->length, page, offset, buffer_info->length,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
if (++tpd_next_to_use == tpd_ring->count) if (++next_to_use == tpd_ring->count)
tpd_next_to_use = 0; next_to_use = 0;
} }
} }
} else { } else {
/* not TSO/GSO */ /* not TSO */
buffer_info->length = first_buf_len; buffer_info->length = buf_len;
page = virt_to_page(skb->data); page = virt_to_page(skb->data);
offset = (unsigned long)skb->data & ~PAGE_MASK; offset = (unsigned long)skb->data & ~PAGE_MASK;
buffer_info->dma = pci_map_page(adapter->pdev, page, buffer_info->dma = pci_map_page(adapter->pdev, page,
offset, first_buf_len, PCI_DMA_TODEVICE); offset, buf_len, PCI_DMA_TODEVICE);
if (++tpd_next_to_use == tpd_ring->count) if (++next_to_use == tpd_ring->count)
tpd_next_to_use = 0; next_to_use = 0;
} }
for (f = 0; f < nr_frags; f++) { for (f = 0; f < nr_frags; f++) {
struct skb_frag_struct *frag; struct skb_frag_struct *frag;
u16 lenf, i, m; u16 i, nseg;
frag = &skb_shinfo(skb)->frags[f]; frag = &skb_shinfo(skb)->frags[f];
lenf = frag->size; buf_len = frag->size;
m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN; nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
for (i = 0; i < m; i++) { ATL1_MAX_TX_BUF_LEN;
buffer_info = &tpd_ring->buffer_info[tpd_next_to_use]; for (i = 0; i < nseg; i++) {
buffer_info = &tpd_ring->buffer_info[next_to_use];
if (unlikely(buffer_info->skb)) if (unlikely(buffer_info->skb))
BUG(); BUG();
buffer_info->skb = NULL; buffer_info->skb = NULL;
buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ? buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
ATL1_MAX_TX_BUF_LEN : lenf; ATL1_MAX_TX_BUF_LEN : buf_len;
lenf -= buffer_info->length; buf_len -= buffer_info->length;
buffer_info->dma = pci_map_page(adapter->pdev, buffer_info->dma = pci_map_page(adapter->pdev,
frag->page, frag->page,
frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN), frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
buffer_info->length, PCI_DMA_TODEVICE); buffer_info->length, PCI_DMA_TODEVICE);
if (++tpd_next_to_use == tpd_ring->count) if (++next_to_use == tpd_ring->count)
tpd_next_to_use = 0; next_to_use = 0;
} }
} }
...@@ -1451,39 +1471,44 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, ...@@ -1451,39 +1471,44 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->skb = skb; buffer_info->skb = skb;
} }
static void atl1_tx_queue(struct atl1_adapter *adapter, int count, static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
union tpd_descr *descr) struct tx_packet_desc *ptpd)
{ {
/* We enter this function holding a spinlock. */ /* spinlock held */
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
int j;
u32 val;
struct atl1_buffer *buffer_info; struct atl1_buffer *buffer_info;
struct tx_packet_desc *tpd; struct tx_packet_desc *tpd;
u16 tpd_next_to_use = atomic_read(&tpd_ring->next_to_use); u16 j;
u32 val;
u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use);
for (j = 0; j < count; j++) { for (j = 0; j < count; j++) {
buffer_info = &tpd_ring->buffer_info[tpd_next_to_use]; buffer_info = &tpd_ring->buffer_info[next_to_use];
tpd = ATL1_TPD_DESC(&adapter->tpd_ring, tpd_next_to_use); tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use);
tpd->desc.csum.csumpu = descr->csum.csumpu; if (tpd != ptpd)
tpd->desc.csum.csumpl = descr->csum.csumpl; memcpy(tpd, ptpd, sizeof(struct tx_packet_desc));
tpd->desc.tso.tsopu = descr->tso.tsopu;
tpd->desc.tso.tsopl = descr->tso.tsopl;
tpd->buffer_addr = cpu_to_le64(buffer_info->dma); tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
tpd->desc.data = descr->data; tpd->word2 = (cpu_to_le16(buffer_info->length) &
tpd->desc.tso.tsopu |= (cpu_to_le16(buffer_info->length) & TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT;
TSO_PARAM_BUFLEN_MASK) << TSO_PARAM_BUFLEN_SHIFT;
val = (descr->tso.tsopl >> TSO_PARAM_SEGMENT_SHIFT) & /*
TSO_PARAM_SEGMENT_MASK; * if this is the first packet in a TSO chain, set
if (val && !j) * TPD_HDRFLAG, otherwise, clear it.
tpd->desc.tso.tsopl |= 1 << TSO_PARAM_HDRFLAG_SHIFT; */
val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) &
TPD_SEGMENT_EN_MASK;
if (val) {
if (!j)
tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
else
tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT);
}
if (j == (count - 1)) if (j == (count - 1))
tpd->desc.tso.tsopl |= 1 << TSO_PARAM_EOP_SHIFT; tpd->word3 |= 1 << TPD_EOP_SHIFT;
if (++tpd_next_to_use == tpd_ring->count) if (++next_to_use == tpd_ring->count)
tpd_next_to_use = 0; next_to_use = 0;
} }
/* /*
* Force memory writes to complete before letting h/w * Force memory writes to complete before letting h/w
...@@ -1493,18 +1518,18 @@ static void atl1_tx_queue(struct atl1_adapter *adapter, int count, ...@@ -1493,18 +1518,18 @@ static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
*/ */
wmb(); wmb();
atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use); atomic_set(&tpd_ring->next_to_use, next_to_use);
} }
static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ {
struct atl1_adapter *adapter = netdev_priv(netdev); struct atl1_adapter *adapter = netdev_priv(netdev);
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
int len = skb->len; int len = skb->len;
int tso; int tso;
int count = 1; int count = 1;
int ret_val; int ret_val;
u32 val; struct tx_packet_desc *ptpd;
union tpd_descr param;
u16 frag_size; u16 frag_size;
u16 vlan_tag; u16 vlan_tag;
unsigned long flags; unsigned long flags;
...@@ -1515,18 +1540,11 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1515,18 +1540,11 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
len -= skb->data_len; len -= skb->data_len;
if (unlikely(skb->len == 0)) { if (unlikely(skb->len <= 0)) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
param.data = 0;
param.tso.tsopu = 0;
param.tso.tsopl = 0;
param.csum.csumpu = 0;
param.csum.csumpl = 0;
/* nr_frags will be nonzero if we're doing scatter/gather (SG) */
nr_frags = skb_shinfo(skb)->nr_frags; nr_frags = skb_shinfo(skb)->nr_frags;
for (f = 0; f < nr_frags; f++) { for (f = 0; f < nr_frags; f++) {
frag_size = skb_shinfo(skb)->frags[f].size; frag_size = skb_shinfo(skb)->frags[f].size;
...@@ -1535,10 +1553,9 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1535,10 +1553,9 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
ATL1_MAX_TX_BUF_LEN; ATL1_MAX_TX_BUF_LEN;
} }
/* mss will be nonzero if we're doing segment offload (TSO/GSO) */
mss = skb_shinfo(skb)->gso_size; mss = skb_shinfo(skb)->gso_size;
if (mss) { if (mss) {
if (skb->protocol == htons(ETH_P_IP)) { if (skb->protocol == ntohs(ETH_P_IP)) {
proto_hdr_len = (skb_transport_offset(skb) + proto_hdr_len = (skb_transport_offset(skb) +
tcp_hdrlen(skb)); tcp_hdrlen(skb));
if (unlikely(proto_hdr_len > len)) { if (unlikely(proto_hdr_len > len)) {
...@@ -1567,18 +1584,20 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1567,18 +1584,20 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
param.data = 0; ptpd = ATL1_TPD_DESC(tpd_ring,
(u16) atomic_read(&tpd_ring->next_to_use));
memset(ptpd, 0, sizeof(struct tx_packet_desc));
if (adapter->vlgrp && vlan_tx_tag_present(skb)) { if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
vlan_tag = vlan_tx_tag_get(skb); vlan_tag = vlan_tx_tag_get(skb);
vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) | vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
((vlan_tag >> 9) & 0x8); ((vlan_tag >> 9) & 0x8);
param.tso.tsopl |= 1 << TSO_PARAM_INSVLAG_SHIFT; ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
param.tso.tsopu |= (vlan_tag & TSO_PARAM_VLANTAG_MASK) << ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) <<
TSO_PARAM_VLAN_SHIFT; TPD_VL_TAGGED_SHIFT;
} }
tso = atl1_tso(adapter, skb, &param.tso); tso = atl1_tso(adapter, skb, ptpd);
if (tso < 0) { if (tso < 0) {
spin_unlock_irqrestore(&adapter->lock, flags); spin_unlock_irqrestore(&adapter->lock, flags);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -1586,7 +1605,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1586,7 +1605,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
} }
if (!tso) { if (!tso) {
ret_val = atl1_tx_csum(adapter, skb, &param.csum); ret_val = atl1_tx_csum(adapter, skb, ptpd);
if (ret_val < 0) { if (ret_val < 0) {
spin_unlock_irqrestore(&adapter->lock, flags); spin_unlock_irqrestore(&adapter->lock, flags);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -1594,13 +1613,11 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1594,13 +1613,11 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
} }
} }
val = (param.tso.tsopl >> TSO_PARAM_SEGMENT_SHIFT) & atl1_tx_map(adapter, skb, ptpd);
TSO_PARAM_SEGMENT_MASK; atl1_tx_queue(adapter, count, ptpd);
atl1_tx_map(adapter, skb, 1 == val);
atl1_tx_queue(adapter, count, &param);
netdev->trans_start = jiffies;
spin_unlock_irqrestore(&adapter->lock, flags);
atl1_update_mailbox(adapter); atl1_update_mailbox(adapter);
spin_unlock_irqrestore(&adapter->lock, flags);
netdev->trans_start = jiffies;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
...@@ -2759,7 +2776,7 @@ const struct ethtool_ops atl1_ethtool_ops = { ...@@ -2759,7 +2776,7 @@ const struct ethtool_ops atl1_ethtool_ops = {
.get_ringparam = atl1_get_ringparam, .get_ringparam = atl1_get_ringparam,
.set_ringparam = atl1_set_ringparam, .set_ringparam = atl1_set_ringparam,
.get_pauseparam = atl1_get_pauseparam, .get_pauseparam = atl1_get_pauseparam,
.set_pauseparam = atl1_set_pauseparam, .set_pauseparam = atl1_set_pauseparam,
.get_rx_csum = atl1_get_rx_csum, .get_rx_csum = atl1_get_rx_csum,
.set_tx_csum = ethtool_op_set_tx_hw_csum, .set_tx_csum = ethtool_op_set_tx_hw_csum,
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
......
...@@ -452,106 +452,115 @@ struct rx_free_desc { ...@@ -452,106 +452,115 @@ struct rx_free_desc {
/* __attribute__ ((packed)) is required */ /* __attribute__ ((packed)) is required */
} __attribute__ ((packed)); } __attribute__ ((packed));
/* tsopu defines */ /*
#define TSO_PARAM_BUFLEN_MASK 0x3FFF * The L1 transmit packet descriptor is comprised of four 32-bit words.
#define TSO_PARAM_BUFLEN_SHIFT 0 *
#define TSO_PARAM_DMAINT_MASK 0x0001 * 31 0
#define TSO_PARAM_DMAINT_SHIFT 14 * +---------------------------------------+
#define TSO_PARAM_PKTNT_MASK 0x0001 * | Word 0: Buffer addr lo |
#define TSO_PARAM_PKTINT_SHIFT 15 * +---------------------------------------+
#define TSO_PARAM_VLANTAG_MASK 0xFFFF * | Word 1: Buffer addr hi |
#define TSO_PARAM_VLAN_SHIFT 16 * +---------------------------------------+
* | Word 2 |
/* tsopl defines */ * +---------------------------------------+
#define TSO_PARAM_EOP_MASK 0x0001 * | Word 3 |
#define TSO_PARAM_EOP_SHIFT 0 * +---------------------------------------+
#define TSO_PARAM_COALESCE_MASK 0x0001 *
#define TSO_PARAM_COALESCE_SHIFT 1 * Words 0 and 1 combine to form a 64-bit buffer address.
#define TSO_PARAM_INSVLAG_MASK 0x0001 *
#define TSO_PARAM_INSVLAG_SHIFT 2 * Word 2 is self explanatory in the #define block below.
#define TSO_PARAM_CUSTOMCKSUM_MASK 0x0001 *
#define TSO_PARAM_CUSTOMCKSUM_SHIFT 3 * Word 3 has two forms, depending upon the state of bits 3 and 4.
#define TSO_PARAM_SEGMENT_MASK 0x0001 * If bits 3 and 4 are both zero, then bits 14:31 are unused by the
#define TSO_PARAM_SEGMENT_SHIFT 4 * hardware. Otherwise, if either bit 3 or 4 is set, the definition
#define TSO_PARAM_IPCKSUM_MASK 0x0001 * of bits 14:31 vary according to the following depiction.
#define TSO_PARAM_IPCKSUM_SHIFT 5 *
#define TSO_PARAM_TCPCKSUM_MASK 0x0001 * 0 End of packet 0 End of packet
#define TSO_PARAM_TCPCKSUM_SHIFT 6 * 1 Coalesce 1 Coalesce
#define TSO_PARAM_UDPCKSUM_MASK 0x0001 * 2 Insert VLAN tag 2 Insert VLAN tag
#define TSO_PARAM_UDPCKSUM_SHIFT 7 * 3 Custom csum enable = 0 3 Custom csum enable = 1
#define TSO_PARAM_VLANTAGGED_MASK 0x0001 * 4 Segment enable = 1 4 Segment enable = 0
#define TSO_PARAM_VLANTAGGED_SHIFT 8 * 5 Generate IP checksum 5 Generate IP checksum
#define TSO_PARAM_ETHTYPE_MASK 0x0001 * 6 Generate TCP checksum 6 Generate TCP checksum
#define TSO_PARAM_ETHTYPE_SHIFT 9 * 7 Generate UDP checksum 7 Generate UDP checksum
#define TSO_PARAM_IPHL_MASK 0x000F * 8 VLAN tagged 8 VLAN tagged
#define TSO_PARAM_IPHL_SHIFT 10 * 9 Ethernet frame type 9 Ethernet frame type
#define TSO_PARAM_TCPHDRLEN_MASK 0x000F * 10-+ 10-+
#define TSO_PARAM_TCPHDRLEN_SHIFT 14 * 11 | IP hdr length (10:13) 11 | IP hdr length (10:13)
#define TSO_PARAM_HDRFLAG_MASK 0x0001 * 12 | (num 32-bit words) 12 | (num 32-bit words)
#define TSO_PARAM_HDRFLAG_SHIFT 18 * 13-+ 13-+
#define TSO_PARAM_MSS_MASK 0x1FFF * 14-+ 14 Unused
#define TSO_PARAM_MSS_SHIFT 19 * 15 | TCP hdr length (14:17) 15 Unused
* 16 | (num 32-bit words) 16-+
/* csumpu defines */ * 17-+ 17 |
#define CSUM_PARAM_BUFLEN_MASK 0x3FFF * 18 Header TPD flag 18 |
#define CSUM_PARAM_BUFLEN_SHIFT 0 * 19-+ 19 | Payload offset
#define CSUM_PARAM_DMAINT_MASK 0x0001 * 20 | 20 | (16:23)
#define CSUM_PARAM_DMAINT_SHIFT 14 * 21 | 21 |
#define CSUM_PARAM_PKTINT_MASK 0x0001 * 22 | 22 |
#define CSUM_PARAM_PKTINT_SHIFT 15 * 23 | 23-+
#define CSUM_PARAM_VALANTAG_MASK 0xFFFF * 24 | 24-+
#define CSUM_PARAM_VALAN_SHIFT 16 * 25 | MSS (19:31) 25 |
* 26 | 26 |
/* csumpl defines*/ * 27 | 27 | Custom csum offset
#define CSUM_PARAM_EOP_MASK 0x0001 * 28 | 28 | (24:31)
#define CSUM_PARAM_EOP_SHIFT 0 * 29 | 29 |
#define CSUM_PARAM_COALESCE_MASK 0x0001 * 30 | 30 |
#define CSUM_PARAM_COALESCE_SHIFT 1 * 31-+ 31-+
#define CSUM_PARAM_INSVLAG_MASK 0x0001 */
#define CSUM_PARAM_INSVLAG_SHIFT 2
#define CSUM_PARAM_CUSTOMCKSUM_MASK 0x0001
#define CSUM_PARAM_CUSTOMCKSUM_SHIFT 3
#define CSUM_PARAM_SEGMENT_MASK 0x0001
#define CSUM_PARAM_SEGMENT_SHIFT 4
#define CSUM_PARAM_IPCKSUM_MASK 0x0001
#define CSUM_PARAM_IPCKSUM_SHIFT 5
#define CSUM_PARAM_TCPCKSUM_MASK 0x0001
#define CSUM_PARAM_TCPCKSUM_SHIFT 6
#define CSUM_PARAM_UDPCKSUM_MASK 0x0001
#define CSUM_PARAM_UDPCKSUM_SHIFT 7
#define CSUM_PARAM_VLANTAGGED_MASK 0x0001
#define CSUM_PARAM_VLANTAGGED_SHIFT 8
#define CSUM_PARAM_ETHTYPE_MASK 0x0001
#define CSUM_PARAM_ETHTYPE_SHIFT 9
#define CSUM_PARAM_IPHL_MASK 0x000F
#define CSUM_PARAM_IPHL_SHIFT 10
#define CSUM_PARAM_PLOADOFFSET_MASK 0x00FF
#define CSUM_PARAM_PLOADOFFSET_SHIFT 16
#define CSUM_PARAM_XSUMOFFSET_MASK 0x00FF
#define CSUM_PARAM_XSUMOFFSET_SHIFT 24
/* TPD descriptor */
struct tso_param {
/* The order of these declarations is important -- don't change it */
u32 tsopu; /* tso_param upper word */
u32 tsopl; /* tso_param lower word */
};
struct csum_param {
/* The order of these declarations is important -- don't change it */
u32 csumpu; /* csum_param upper word */
u32 csumpl; /* csum_param lower word */
};
union tpd_descr { /* tpd word 2 */
u64 data; #define TPD_BUFLEN_MASK 0x3FFF
struct csum_param csum; #define TPD_BUFLEN_SHIFT 0
struct tso_param tso; #define TPD_DMAINT_MASK 0x0001
}; #define TPD_DMAINT_SHIFT 14
#define TPD_PKTNT_MASK 0x0001
#define TPD_PKTINT_SHIFT 15
#define TPD_VLANTAG_MASK 0xFFFF
#define TPD_VLAN_SHIFT 16
/* tpd word 3 bits 0:13 */
#define TPD_EOP_MASK 0x0001
#define TPD_EOP_SHIFT 0
#define TPD_COALESCE_MASK 0x0001
#define TPD_COALESCE_SHIFT 1
#define TPD_INS_VL_TAG_MASK 0x0001
#define TPD_INS_VL_TAG_SHIFT 2
#define TPD_CUST_CSUM_EN_MASK 0x0001
#define TPD_CUST_CSUM_EN_SHIFT 3
#define TPD_SEGMENT_EN_MASK 0x0001
#define TPD_SEGMENT_EN_SHIFT 4
#define TPD_IP_CSUM_MASK 0x0001
#define TPD_IP_CSUM_SHIFT 5
#define TPD_TCP_CSUM_MASK 0x0001
#define TPD_TCP_CSUM_SHIFT 6
#define TPD_UDP_CSUM_MASK 0x0001
#define TPD_UDP_CSUM_SHIFT 7
#define TPD_VL_TAGGED_MASK 0x0001
#define TPD_VL_TAGGED_SHIFT 8
#define TPD_ETHTYPE_MASK 0x0001
#define TPD_ETHTYPE_SHIFT 9
#define TPD_IPHL_MASK 0x000F
#define TPD_IPHL_SHIFT 10
/* tpd word 3 bits 14:31 if segment enabled */
#define TPD_TCPHDRLEN_MASK 0x000F
#define TPD_TCPHDRLEN_SHIFT 14
#define TPD_HDRFLAG_MASK 0x0001
#define TPD_HDRFLAG_SHIFT 18
#define TPD_MSS_MASK 0x1FFF
#define TPD_MSS_SHIFT 19
/* tpd word 3 bits 16:31 if custom csum enabled */
#define TPD_PLOADOFFSET_MASK 0x00FF
#define TPD_PLOADOFFSET_SHIFT 16
#define TPD_CCSUMOFFSET_MASK 0x00FF
#define TPD_CCSUMOFFSET_SHIFT 24
struct tx_packet_desc { struct tx_packet_desc {
__le64 buffer_addr; __le64 buffer_addr;
union tpd_descr desc; __le32 word2;
__le32 word3;
}; };
/* DMA Order Settings */ /* DMA Order Settings */
......
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