Merge branch 'amd-xgbe-next'
Tom Lendacky says: ==================== amd-xgbe: AMD XGBE driver updates 2014-11-20 The following series of patches includes functional updates to the driver as well as some trivial changes. - Add a read memory barrier in the Tx and Rx path after checking the descriptor ownership bit - Wait for the Tx engine to stop/suspend before issuing a stop command - Implement a smatch tool suggestion to simplify an if statement - Separate out Tx and Rx ring data fields into their own structures - Add BQL support - Remove an unused variable - Change Tx coalescing support to operate on packet basis instead of a descriptor basis - Add support for the skb->xmit_more flag This patch series is based on net-next. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
7d7a10792d
|
@ -125,9 +125,6 @@
|
||||||
#define DMA_AXIAWCR 0x3018
|
#define DMA_AXIAWCR 0x3018
|
||||||
#define DMA_DSR0 0x3020
|
#define DMA_DSR0 0x3020
|
||||||
#define DMA_DSR1 0x3024
|
#define DMA_DSR1 0x3024
|
||||||
#define DMA_DSR2 0x3028
|
|
||||||
#define DMA_DSR3 0x302c
|
|
||||||
#define DMA_DSR4 0x3030
|
|
||||||
|
|
||||||
/* DMA register entry bit positions and sizes */
|
/* DMA register entry bit positions and sizes */
|
||||||
#define DMA_AXIARCR_DRC_INDEX 0
|
#define DMA_AXIARCR_DRC_INDEX 0
|
||||||
|
@ -158,10 +155,6 @@
|
||||||
#define DMA_AXIAWCR_TDC_WIDTH 4
|
#define DMA_AXIAWCR_TDC_WIDTH 4
|
||||||
#define DMA_AXIAWCR_TDD_INDEX 28
|
#define DMA_AXIAWCR_TDD_INDEX 28
|
||||||
#define DMA_AXIAWCR_TDD_WIDTH 2
|
#define DMA_AXIAWCR_TDD_WIDTH 2
|
||||||
#define DMA_DSR0_RPS_INDEX 8
|
|
||||||
#define DMA_DSR0_RPS_WIDTH 4
|
|
||||||
#define DMA_DSR0_TPS_INDEX 12
|
|
||||||
#define DMA_DSR0_TPS_WIDTH 4
|
|
||||||
#define DMA_ISR_MACIS_INDEX 17
|
#define DMA_ISR_MACIS_INDEX 17
|
||||||
#define DMA_ISR_MACIS_WIDTH 1
|
#define DMA_ISR_MACIS_WIDTH 1
|
||||||
#define DMA_ISR_MTLIS_INDEX 16
|
#define DMA_ISR_MTLIS_INDEX 16
|
||||||
|
@ -175,6 +168,20 @@
|
||||||
#define DMA_SBMR_UNDEF_INDEX 0
|
#define DMA_SBMR_UNDEF_INDEX 0
|
||||||
#define DMA_SBMR_UNDEF_WIDTH 1
|
#define DMA_SBMR_UNDEF_WIDTH 1
|
||||||
|
|
||||||
|
/* DMA register values */
|
||||||
|
#define DMA_DSR_RPS_WIDTH 4
|
||||||
|
#define DMA_DSR_TPS_WIDTH 4
|
||||||
|
#define DMA_DSR_Q_WIDTH (DMA_DSR_RPS_WIDTH + DMA_DSR_TPS_WIDTH)
|
||||||
|
#define DMA_DSR0_RPS_START 8
|
||||||
|
#define DMA_DSR0_TPS_START 12
|
||||||
|
#define DMA_DSRX_FIRST_QUEUE 3
|
||||||
|
#define DMA_DSRX_INC 4
|
||||||
|
#define DMA_DSRX_QPR 4
|
||||||
|
#define DMA_DSRX_RPS_START 0
|
||||||
|
#define DMA_DSRX_TPS_START 4
|
||||||
|
#define DMA_TPS_STOPPED 0x00
|
||||||
|
#define DMA_TPS_SUSPENDED 0x06
|
||||||
|
|
||||||
/* DMA channel register offsets
|
/* DMA channel register offsets
|
||||||
* Multiple channels can be active. The first channel has registers
|
* Multiple channels can be active. The first channel has registers
|
||||||
* that begin at 0x3100. Each subsequent channel has registers that
|
* that begin at 0x3100. Each subsequent channel has registers that
|
||||||
|
|
|
@ -335,11 +335,11 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the header page info */
|
/* Set up the header page info */
|
||||||
xgbe_set_buffer_data(&rdata->rx_hdr, &ring->rx_hdr_pa,
|
xgbe_set_buffer_data(&rdata->rx.hdr, &ring->rx_hdr_pa,
|
||||||
XGBE_SKB_ALLOC_SIZE);
|
XGBE_SKB_ALLOC_SIZE);
|
||||||
|
|
||||||
/* Set up the buffer page info */
|
/* Set up the buffer page info */
|
||||||
xgbe_set_buffer_data(&rdata->rx_buf, &ring->rx_buf_pa,
|
xgbe_set_buffer_data(&rdata->rx.buf, &ring->rx_buf_pa,
|
||||||
pdata->rx_buf_size);
|
pdata->rx_buf_size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -378,7 +378,7 @@ static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||||
|
|
||||||
ring->cur = 0;
|
ring->cur = 0;
|
||||||
ring->dirty = 0;
|
ring->dirty = 0;
|
||||||
ring->tx.queue_stopped = 0;
|
memset(&ring->tx, 0, sizeof(ring->tx));
|
||||||
|
|
||||||
hw_if->tx_desc_init(channel);
|
hw_if->tx_desc_init(channel);
|
||||||
}
|
}
|
||||||
|
@ -422,8 +422,7 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||||
|
|
||||||
ring->cur = 0;
|
ring->cur = 0;
|
||||||
ring->dirty = 0;
|
ring->dirty = 0;
|
||||||
ring->rx.realloc_index = 0;
|
memset(&ring->rx, 0, sizeof(ring->rx));
|
||||||
ring->rx.realloc_threshold = 0;
|
|
||||||
|
|
||||||
hw_if->rx_desc_init(channel);
|
hw_if->rx_desc_init(channel);
|
||||||
}
|
}
|
||||||
|
@ -451,31 +450,29 @@ static void xgbe_unmap_rdata(struct xgbe_prv_data *pdata,
|
||||||
rdata->skb = NULL;
|
rdata->skb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rdata->rx_hdr.pa.pages)
|
if (rdata->rx.hdr.pa.pages)
|
||||||
put_page(rdata->rx_hdr.pa.pages);
|
put_page(rdata->rx.hdr.pa.pages);
|
||||||
|
|
||||||
if (rdata->rx_hdr.pa_unmap.pages) {
|
if (rdata->rx.hdr.pa_unmap.pages) {
|
||||||
dma_unmap_page(pdata->dev, rdata->rx_hdr.pa_unmap.pages_dma,
|
dma_unmap_page(pdata->dev, rdata->rx.hdr.pa_unmap.pages_dma,
|
||||||
rdata->rx_hdr.pa_unmap.pages_len,
|
rdata->rx.hdr.pa_unmap.pages_len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
put_page(rdata->rx_hdr.pa_unmap.pages);
|
put_page(rdata->rx.hdr.pa_unmap.pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rdata->rx_buf.pa.pages)
|
if (rdata->rx.buf.pa.pages)
|
||||||
put_page(rdata->rx_buf.pa.pages);
|
put_page(rdata->rx.buf.pa.pages);
|
||||||
|
|
||||||
if (rdata->rx_buf.pa_unmap.pages) {
|
if (rdata->rx.buf.pa_unmap.pages) {
|
||||||
dma_unmap_page(pdata->dev, rdata->rx_buf.pa_unmap.pages_dma,
|
dma_unmap_page(pdata->dev, rdata->rx.buf.pa_unmap.pages_dma,
|
||||||
rdata->rx_buf.pa_unmap.pages_len,
|
rdata->rx.buf.pa_unmap.pages_len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
put_page(rdata->rx_buf.pa_unmap.pages);
|
put_page(rdata->rx.buf.pa_unmap.pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&rdata->rx_hdr, 0, sizeof(rdata->rx_hdr));
|
memset(&rdata->tx, 0, sizeof(rdata->tx));
|
||||||
memset(&rdata->rx_buf, 0, sizeof(rdata->rx_buf));
|
memset(&rdata->rx, 0, sizeof(rdata->rx));
|
||||||
|
|
||||||
rdata->tso_header = 0;
|
|
||||||
rdata->len = 0;
|
|
||||||
rdata->interrupt = 0;
|
rdata->interrupt = 0;
|
||||||
rdata->mapped_as_page = 0;
|
rdata->mapped_as_page = 0;
|
||||||
|
|
||||||
|
@ -534,7 +531,6 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
rdata->skb_dma = skb_dma;
|
rdata->skb_dma = skb_dma;
|
||||||
rdata->skb_dma_len = packet->header_len;
|
rdata->skb_dma_len = packet->header_len;
|
||||||
rdata->tso_header = 1;
|
|
||||||
|
|
||||||
offset = packet->header_len;
|
offset = packet->header_len;
|
||||||
|
|
||||||
|
|
|
@ -1085,10 +1085,10 @@ static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata)
|
||||||
* Set buffer 2 (hi) address to buffer dma address (hi) and
|
* Set buffer 2 (hi) address to buffer dma address (hi) and
|
||||||
* set control bits OWN and INTE
|
* set control bits OWN and INTE
|
||||||
*/
|
*/
|
||||||
rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx_hdr.dma));
|
rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx.hdr.dma));
|
||||||
rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx_hdr.dma));
|
rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx.hdr.dma));
|
||||||
rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx_buf.dma));
|
rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma));
|
||||||
rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx_buf.dma));
|
rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma));
|
||||||
|
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE,
|
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE,
|
||||||
rdata->interrupt ? 1 : 0);
|
rdata->interrupt ? 1 : 0);
|
||||||
|
@ -1325,6 +1325,29 @@ static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
|
||||||
xgbe_config_flow_control(pdata);
|
xgbe_config_flow_control(pdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
|
||||||
|
struct xgbe_ring *ring)
|
||||||
|
{
|
||||||
|
struct xgbe_prv_data *pdata = channel->pdata;
|
||||||
|
struct xgbe_ring_data *rdata;
|
||||||
|
|
||||||
|
/* Issue a poll command to Tx DMA by writing address
|
||||||
|
* of next immediate free descriptor */
|
||||||
|
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
|
||||||
|
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
|
||||||
|
lower_32_bits(rdata->rdesc_dma));
|
||||||
|
|
||||||
|
/* Start the Tx coalescing timer */
|
||||||
|
if (pdata->tx_usecs && !channel->tx_timer_active) {
|
||||||
|
channel->tx_timer_active = 1;
|
||||||
|
hrtimer_start(&channel->tx_timer,
|
||||||
|
ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC),
|
||||||
|
HRTIMER_MODE_REL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ring->tx.xmit_more = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
||||||
{
|
{
|
||||||
struct xgbe_prv_data *pdata = channel->pdata;
|
struct xgbe_prv_data *pdata = channel->pdata;
|
||||||
|
@ -1334,7 +1357,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
||||||
struct xgbe_packet_data *packet = &ring->packet_data;
|
struct xgbe_packet_data *packet = &ring->packet_data;
|
||||||
unsigned int csum, tso, vlan;
|
unsigned int csum, tso, vlan;
|
||||||
unsigned int tso_context, vlan_context;
|
unsigned int tso_context, vlan_context;
|
||||||
unsigned int tx_coalesce, tx_frames;
|
unsigned int tx_set_ic;
|
||||||
int start_index = ring->cur;
|
int start_index = ring->cur;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1357,10 +1380,26 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
||||||
else
|
else
|
||||||
vlan_context = 0;
|
vlan_context = 0;
|
||||||
|
|
||||||
tx_coalesce = (pdata->tx_usecs || pdata->tx_frames) ? 1 : 0;
|
/* Determine if an interrupt should be generated for this Tx:
|
||||||
tx_frames = pdata->tx_frames;
|
* Interrupt:
|
||||||
if (tx_coalesce && !channel->tx_timer_active)
|
* - Tx frame count exceeds the frame count setting
|
||||||
ring->coalesce_count = 0;
|
* - Addition of Tx frame count to the frame count since the
|
||||||
|
* last interrupt was set exceeds the frame count setting
|
||||||
|
* No interrupt:
|
||||||
|
* - No frame count setting specified (ethtool -C ethX tx-frames 0)
|
||||||
|
* - Addition of Tx frame count to the frame count since the
|
||||||
|
* last interrupt was set does not exceed the frame count setting
|
||||||
|
*/
|
||||||
|
ring->coalesce_count += packet->tx_packets;
|
||||||
|
if (!pdata->tx_frames)
|
||||||
|
tx_set_ic = 0;
|
||||||
|
else if (packet->tx_packets > pdata->tx_frames)
|
||||||
|
tx_set_ic = 1;
|
||||||
|
else if ((ring->coalesce_count % pdata->tx_frames) <
|
||||||
|
packet->tx_packets)
|
||||||
|
tx_set_ic = 1;
|
||||||
|
else
|
||||||
|
tx_set_ic = 0;
|
||||||
|
|
||||||
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
|
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
|
||||||
rdesc = rdata->rdesc;
|
rdesc = rdata->rdesc;
|
||||||
|
@ -1427,13 +1466,6 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
||||||
if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP))
|
if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP))
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1);
|
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1);
|
||||||
|
|
||||||
/* Set IC bit based on Tx coalescing settings */
|
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
|
|
||||||
if (tx_coalesce && (!tx_frames ||
|
|
||||||
(++ring->coalesce_count % tx_frames)))
|
|
||||||
/* Clear IC bit */
|
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 0);
|
|
||||||
|
|
||||||
/* Mark it as First Descriptor */
|
/* Mark it as First Descriptor */
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FD, 1);
|
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FD, 1);
|
||||||
|
|
||||||
|
@ -1478,13 +1510,6 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L,
|
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L,
|
||||||
rdata->skb_dma_len);
|
rdata->skb_dma_len);
|
||||||
|
|
||||||
/* Set IC bit based on Tx coalescing settings */
|
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
|
|
||||||
if (tx_coalesce && (!tx_frames ||
|
|
||||||
(++ring->coalesce_count % tx_frames)))
|
|
||||||
/* Clear IC bit */
|
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 0);
|
|
||||||
|
|
||||||
/* Set OWN bit */
|
/* Set OWN bit */
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
|
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
|
||||||
|
|
||||||
|
@ -1500,6 +1525,14 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
||||||
/* Set LAST bit for the last descriptor */
|
/* Set LAST bit for the last descriptor */
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1);
|
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1);
|
||||||
|
|
||||||
|
/* Set IC bit based on Tx coalescing settings */
|
||||||
|
if (tx_set_ic)
|
||||||
|
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
|
||||||
|
|
||||||
|
/* Save the Tx info to report back during cleanup */
|
||||||
|
rdata->tx.packets = packet->tx_packets;
|
||||||
|
rdata->tx.bytes = packet->tx_bytes;
|
||||||
|
|
||||||
/* In case the Tx DMA engine is running, make sure everything
|
/* In case the Tx DMA engine is running, make sure everything
|
||||||
* is written to the descriptor(s) before setting the OWN bit
|
* is written to the descriptor(s) before setting the OWN bit
|
||||||
* for the first descriptor
|
* for the first descriptor
|
||||||
|
@ -1518,20 +1551,13 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
||||||
/* Make sure ownership is written to the descriptor */
|
/* Make sure ownership is written to the descriptor */
|
||||||
wmb();
|
wmb();
|
||||||
|
|
||||||
/* Issue a poll command to Tx DMA by writing address
|
|
||||||
* of next immediate free descriptor */
|
|
||||||
ring->cur++;
|
ring->cur++;
|
||||||
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
|
if (!packet->skb->xmit_more ||
|
||||||
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
|
netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev,
|
||||||
lower_32_bits(rdata->rdesc_dma));
|
channel->queue_index)))
|
||||||
|
xgbe_tx_start_xmit(channel, ring);
|
||||||
/* Start the Tx coalescing timer */
|
else
|
||||||
if (tx_coalesce && !channel->tx_timer_active) {
|
ring->tx.xmit_more = 1;
|
||||||
channel->tx_timer_active = 1;
|
|
||||||
hrtimer_start(&channel->tx_timer,
|
|
||||||
ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC),
|
|
||||||
HRTIMER_MODE_REL);
|
|
||||||
}
|
|
||||||
|
|
||||||
DBGPR(" %s: descriptors %u to %u written\n",
|
DBGPR(" %s: descriptors %u to %u written\n",
|
||||||
channel->name, start_index & (ring->rdesc_count - 1),
|
channel->name, start_index & (ring->rdesc_count - 1),
|
||||||
|
@ -1558,6 +1584,9 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
|
||||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN))
|
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* Make sure descriptor fields are read after reading the OWN bit */
|
||||||
|
rmb();
|
||||||
|
|
||||||
#ifdef XGMAC_ENABLE_RX_DESC_DUMP
|
#ifdef XGMAC_ENABLE_RX_DESC_DUMP
|
||||||
xgbe_dump_rx_desc(ring, rdesc, ring->cur);
|
xgbe_dump_rx_desc(ring, rdesc, ring->cur);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1583,8 +1612,8 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
|
||||||
|
|
||||||
/* Get the header length */
|
/* Get the header length */
|
||||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD))
|
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD))
|
||||||
rdata->hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
|
rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
|
||||||
RX_NORMAL_DESC2, HL);
|
RX_NORMAL_DESC2, HL);
|
||||||
|
|
||||||
/* Get the RSS hash */
|
/* Get the RSS hash */
|
||||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, RSV)) {
|
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, RSV)) {
|
||||||
|
@ -1607,7 +1636,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the packet length */
|
/* Get the packet length */
|
||||||
rdata->len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
|
rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
|
||||||
|
|
||||||
if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) {
|
if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) {
|
||||||
/* Not all the data has been transferred for this packet */
|
/* Not all the data has been transferred for this packet */
|
||||||
|
@ -1630,7 +1659,8 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
|
||||||
etlt = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, ETLT);
|
etlt = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, ETLT);
|
||||||
DBGPR(" err=%u, etlt=%#x\n", err, etlt);
|
DBGPR(" err=%u, etlt=%#x\n", err, etlt);
|
||||||
|
|
||||||
if (!err || (err && !etlt)) {
|
if (!err || !etlt) {
|
||||||
|
/* No error if err is 0 or etlt is 0 */
|
||||||
if ((etlt == 0x09) &&
|
if ((etlt == 0x09) &&
|
||||||
(netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
|
(netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
|
||||||
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
||||||
|
@ -2450,6 +2480,47 @@ static void xgbe_config_mmc(struct xgbe_prv_data *pdata)
|
||||||
XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1);
|
XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata,
|
||||||
|
struct xgbe_channel *channel)
|
||||||
|
{
|
||||||
|
unsigned int tx_dsr, tx_pos, tx_qidx;
|
||||||
|
unsigned int tx_status;
|
||||||
|
unsigned long tx_timeout;
|
||||||
|
|
||||||
|
/* Calculate the status register to read and the position within */
|
||||||
|
if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) {
|
||||||
|
tx_dsr = DMA_DSR0;
|
||||||
|
tx_pos = (channel->queue_index * DMA_DSR_Q_WIDTH) +
|
||||||
|
DMA_DSR0_TPS_START;
|
||||||
|
} else {
|
||||||
|
tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE;
|
||||||
|
|
||||||
|
tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC);
|
||||||
|
tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) +
|
||||||
|
DMA_DSRX_TPS_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The Tx engine cannot be stopped if it is actively processing
|
||||||
|
* descriptors. Wait for the Tx engine to enter the stopped or
|
||||||
|
* suspended state. Don't wait forever though...
|
||||||
|
*/
|
||||||
|
tx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ);
|
||||||
|
while (time_before(jiffies, tx_timeout)) {
|
||||||
|
tx_status = XGMAC_IOREAD(pdata, tx_dsr);
|
||||||
|
tx_status = GET_BITS(tx_status, tx_pos, DMA_DSR_TPS_WIDTH);
|
||||||
|
if ((tx_status == DMA_TPS_STOPPED) ||
|
||||||
|
(tx_status == DMA_TPS_SUSPENDED))
|
||||||
|
break;
|
||||||
|
|
||||||
|
usleep_range(500, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!time_before(jiffies, tx_timeout))
|
||||||
|
netdev_info(pdata->netdev,
|
||||||
|
"timed out waiting for Tx DMA channel %u to stop\n",
|
||||||
|
channel->queue_index);
|
||||||
|
}
|
||||||
|
|
||||||
static void xgbe_enable_tx(struct xgbe_prv_data *pdata)
|
static void xgbe_enable_tx(struct xgbe_prv_data *pdata)
|
||||||
{
|
{
|
||||||
struct xgbe_channel *channel;
|
struct xgbe_channel *channel;
|
||||||
|
@ -2478,6 +2549,15 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata)
|
||||||
struct xgbe_channel *channel;
|
struct xgbe_channel *channel;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Prepare for Tx DMA channel stop */
|
||||||
|
channel = pdata->channel;
|
||||||
|
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||||
|
if (!channel->tx_ring)
|
||||||
|
break;
|
||||||
|
|
||||||
|
xgbe_prepare_tx_stop(pdata, channel);
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable MAC Tx */
|
/* Disable MAC Tx */
|
||||||
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
|
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
|
||||||
|
|
||||||
|
@ -2569,6 +2649,15 @@ static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata)
|
||||||
struct xgbe_channel *channel;
|
struct xgbe_channel *channel;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Prepare for Tx DMA channel stop */
|
||||||
|
channel = pdata->channel;
|
||||||
|
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||||
|
if (!channel->tx_ring)
|
||||||
|
break;
|
||||||
|
|
||||||
|
xgbe_prepare_tx_stop(pdata, channel);
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable MAC Tx */
|
/* Disable MAC Tx */
|
||||||
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
|
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
|
||||||
|
|
||||||
|
@ -2729,6 +2818,7 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
|
||||||
hw_if->rx_desc_reset = xgbe_rx_desc_reset;
|
hw_if->rx_desc_reset = xgbe_rx_desc_reset;
|
||||||
hw_if->is_last_desc = xgbe_is_last_desc;
|
hw_if->is_last_desc = xgbe_is_last_desc;
|
||||||
hw_if->is_context_desc = xgbe_is_context_desc;
|
hw_if->is_context_desc = xgbe_is_context_desc;
|
||||||
|
hw_if->tx_start_xmit = xgbe_tx_start_xmit;
|
||||||
|
|
||||||
/* For FLOW ctrl */
|
/* For FLOW ctrl */
|
||||||
hw_if->config_tx_flow_control = xgbe_config_tx_flow_control;
|
hw_if->config_tx_flow_control = xgbe_config_tx_flow_control;
|
||||||
|
|
|
@ -225,6 +225,28 @@ static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring)
|
||||||
return (ring->rdesc_count - (ring->cur - ring->dirty));
|
return (ring->rdesc_count - (ring->cur - ring->dirty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xgbe_maybe_stop_tx_queue(struct xgbe_channel *channel,
|
||||||
|
struct xgbe_ring *ring, unsigned int count)
|
||||||
|
{
|
||||||
|
struct xgbe_prv_data *pdata = channel->pdata;
|
||||||
|
|
||||||
|
if (count > xgbe_tx_avail_desc(ring)) {
|
||||||
|
DBGPR(" Tx queue stopped, not enough descriptors available\n");
|
||||||
|
netif_stop_subqueue(pdata->netdev, channel->queue_index);
|
||||||
|
ring->tx.queue_stopped = 1;
|
||||||
|
|
||||||
|
/* If we haven't notified the hardware because of xmit_more
|
||||||
|
* support, tell it now
|
||||||
|
*/
|
||||||
|
if (ring->tx.xmit_more)
|
||||||
|
pdata->hw_if.tx_start_xmit(channel, ring);
|
||||||
|
|
||||||
|
return NETDEV_TX_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu)
|
static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu)
|
||||||
{
|
{
|
||||||
unsigned int rx_buf_size;
|
unsigned int rx_buf_size;
|
||||||
|
@ -876,7 +898,10 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
|
||||||
static void xgbe_stop(struct xgbe_prv_data *pdata)
|
static void xgbe_stop(struct xgbe_prv_data *pdata)
|
||||||
{
|
{
|
||||||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||||
|
struct xgbe_channel *channel;
|
||||||
struct net_device *netdev = pdata->netdev;
|
struct net_device *netdev = pdata->netdev;
|
||||||
|
struct netdev_queue *txq;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
DBGPR("-->xgbe_stop\n");
|
DBGPR("-->xgbe_stop\n");
|
||||||
|
|
||||||
|
@ -890,6 +915,15 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
|
||||||
hw_if->disable_tx(pdata);
|
hw_if->disable_tx(pdata);
|
||||||
hw_if->disable_rx(pdata);
|
hw_if->disable_rx(pdata);
|
||||||
|
|
||||||
|
channel = pdata->channel;
|
||||||
|
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||||
|
if (!channel->tx_ring)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
txq = netdev_get_tx_queue(netdev, channel->queue_index);
|
||||||
|
netdev_tx_reset_queue(txq);
|
||||||
|
}
|
||||||
|
|
||||||
DBGPR("<--xgbe_stop\n");
|
DBGPR("<--xgbe_stop\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1156,6 +1190,12 @@ static int xgbe_prep_tso(struct sk_buff *skb, struct xgbe_packet_data *packet)
|
||||||
packet->tcp_header_len, packet->tcp_payload_len);
|
packet->tcp_header_len, packet->tcp_payload_len);
|
||||||
DBGPR(" packet->mss=%u\n", packet->mss);
|
DBGPR(" packet->mss=%u\n", packet->mss);
|
||||||
|
|
||||||
|
/* Update the number of packets that will ultimately be transmitted
|
||||||
|
* along with the extra bytes for each extra packet
|
||||||
|
*/
|
||||||
|
packet->tx_packets = skb_shinfo(skb)->gso_segs;
|
||||||
|
packet->tx_bytes += (packet->tx_packets - 1) * packet->header_len;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1181,9 +1221,14 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata,
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
packet->skb = skb;
|
||||||
|
|
||||||
context_desc = 0;
|
context_desc = 0;
|
||||||
packet->rdesc_count = 0;
|
packet->rdesc_count = 0;
|
||||||
|
|
||||||
|
packet->tx_packets = 1;
|
||||||
|
packet->tx_bytes = skb->len;
|
||||||
|
|
||||||
if (xgbe_is_tso(skb)) {
|
if (xgbe_is_tso(skb)) {
|
||||||
/* TSO requires an extra descriptor if mss is different */
|
/* TSO requires an extra descriptor if mss is different */
|
||||||
if (skb_shinfo(skb)->gso_size != ring->tx.cur_mss) {
|
if (skb_shinfo(skb)->gso_size != ring->tx.cur_mss) {
|
||||||
|
@ -1400,12 +1445,14 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||||
struct xgbe_channel *channel;
|
struct xgbe_channel *channel;
|
||||||
struct xgbe_ring *ring;
|
struct xgbe_ring *ring;
|
||||||
struct xgbe_packet_data *packet;
|
struct xgbe_packet_data *packet;
|
||||||
|
struct netdev_queue *txq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len);
|
DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len);
|
||||||
|
|
||||||
channel = pdata->channel + skb->queue_mapping;
|
channel = pdata->channel + skb->queue_mapping;
|
||||||
|
txq = netdev_get_tx_queue(netdev, channel->queue_index);
|
||||||
ring = channel->tx_ring;
|
ring = channel->tx_ring;
|
||||||
packet = &ring->packet_data;
|
packet = &ring->packet_data;
|
||||||
|
|
||||||
|
@ -1424,13 +1471,9 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||||
xgbe_packet_info(pdata, ring, skb, packet);
|
xgbe_packet_info(pdata, ring, skb, packet);
|
||||||
|
|
||||||
/* Check that there are enough descriptors available */
|
/* Check that there are enough descriptors available */
|
||||||
if (packet->rdesc_count > xgbe_tx_avail_desc(ring)) {
|
ret = xgbe_maybe_stop_tx_queue(channel, ring, packet->rdesc_count);
|
||||||
DBGPR(" Tx queue stopped, not enough descriptors available\n");
|
if (ret)
|
||||||
netif_stop_subqueue(netdev, channel->queue_index);
|
|
||||||
ring->tx.queue_stopped = 1;
|
|
||||||
ret = NETDEV_TX_BUSY;
|
|
||||||
goto tx_netdev_return;
|
goto tx_netdev_return;
|
||||||
}
|
|
||||||
|
|
||||||
ret = xgbe_prep_tso(skb, packet);
|
ret = xgbe_prep_tso(skb, packet);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1447,6 +1490,9 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||||
|
|
||||||
xgbe_prep_tx_tstamp(pdata, skb, packet);
|
xgbe_prep_tx_tstamp(pdata, skb, packet);
|
||||||
|
|
||||||
|
/* Report on the actual number of bytes (to be) sent */
|
||||||
|
netdev_tx_sent_queue(txq, packet->tx_bytes);
|
||||||
|
|
||||||
/* Configure required descriptor fields for transmission */
|
/* Configure required descriptor fields for transmission */
|
||||||
hw_if->dev_xmit(channel);
|
hw_if->dev_xmit(channel);
|
||||||
|
|
||||||
|
@ -1454,6 +1500,11 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||||
xgbe_print_pkt(netdev, skb, true);
|
xgbe_print_pkt(netdev, skb, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Stop the queue in advance if there may not be enough descriptors */
|
||||||
|
xgbe_maybe_stop_tx_queue(channel, ring, XGBE_TX_MAX_DESCS);
|
||||||
|
|
||||||
|
ret = NETDEV_TX_OK;
|
||||||
|
|
||||||
tx_netdev_return:
|
tx_netdev_return:
|
||||||
spin_unlock_irqrestore(&ring->lock, flags);
|
spin_unlock_irqrestore(&ring->lock, flags);
|
||||||
|
|
||||||
|
@ -1747,14 +1798,14 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
|
||||||
u8 *packet;
|
u8 *packet;
|
||||||
unsigned int copy_len;
|
unsigned int copy_len;
|
||||||
|
|
||||||
skb = netdev_alloc_skb_ip_align(netdev, rdata->rx_hdr.dma_len);
|
skb = netdev_alloc_skb_ip_align(netdev, rdata->rx.hdr.dma_len);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
packet = page_address(rdata->rx_hdr.pa.pages) +
|
packet = page_address(rdata->rx.hdr.pa.pages) +
|
||||||
rdata->rx_hdr.pa.pages_offset;
|
rdata->rx.hdr.pa.pages_offset;
|
||||||
copy_len = (rdata->hdr_len) ? rdata->hdr_len : *len;
|
copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : *len;
|
||||||
copy_len = min(rdata->rx_hdr.dma_len, copy_len);
|
copy_len = min(rdata->rx.hdr.dma_len, copy_len);
|
||||||
skb_copy_to_linear_data(skb, packet, copy_len);
|
skb_copy_to_linear_data(skb, packet, copy_len);
|
||||||
skb_put(skb, copy_len);
|
skb_put(skb, copy_len);
|
||||||
|
|
||||||
|
@ -1772,8 +1823,10 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
|
||||||
struct xgbe_ring_data *rdata;
|
struct xgbe_ring_data *rdata;
|
||||||
struct xgbe_ring_desc *rdesc;
|
struct xgbe_ring_desc *rdesc;
|
||||||
struct net_device *netdev = pdata->netdev;
|
struct net_device *netdev = pdata->netdev;
|
||||||
|
struct netdev_queue *txq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int processed = 0;
|
int processed = 0;
|
||||||
|
unsigned int tx_packets = 0, tx_bytes = 0;
|
||||||
|
|
||||||
DBGPR("-->xgbe_tx_poll\n");
|
DBGPR("-->xgbe_tx_poll\n");
|
||||||
|
|
||||||
|
@ -1781,6 +1834,8 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
|
||||||
if (!ring)
|
if (!ring)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
txq = netdev_get_tx_queue(netdev, channel->queue_index);
|
||||||
|
|
||||||
spin_lock_irqsave(&ring->lock, flags);
|
spin_lock_irqsave(&ring->lock, flags);
|
||||||
|
|
||||||
while ((processed < XGBE_TX_DESC_MAX_PROC) &&
|
while ((processed < XGBE_TX_DESC_MAX_PROC) &&
|
||||||
|
@ -1791,10 +1846,19 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
|
||||||
if (!hw_if->tx_complete(rdesc))
|
if (!hw_if->tx_complete(rdesc))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Make sure descriptor fields are read after reading the OWN
|
||||||
|
* bit */
|
||||||
|
rmb();
|
||||||
|
|
||||||
#ifdef XGMAC_ENABLE_TX_DESC_DUMP
|
#ifdef XGMAC_ENABLE_TX_DESC_DUMP
|
||||||
xgbe_dump_tx_desc(ring, ring->dirty, 1, 0);
|
xgbe_dump_tx_desc(ring, ring->dirty, 1, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (hw_if->is_last_desc(rdesc)) {
|
||||||
|
tx_packets += rdata->tx.packets;
|
||||||
|
tx_bytes += rdata->tx.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
/* Free the SKB and reset the descriptor for re-use */
|
/* Free the SKB and reset the descriptor for re-use */
|
||||||
desc_if->unmap_rdata(pdata, rdata);
|
desc_if->unmap_rdata(pdata, rdata);
|
||||||
hw_if->tx_desc_reset(rdata);
|
hw_if->tx_desc_reset(rdata);
|
||||||
|
@ -1803,14 +1867,20 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
|
||||||
ring->dirty++;
|
ring->dirty++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!processed)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
netdev_tx_completed_queue(txq, tx_packets, tx_bytes);
|
||||||
|
|
||||||
if ((ring->tx.queue_stopped == 1) &&
|
if ((ring->tx.queue_stopped == 1) &&
|
||||||
(xgbe_tx_avail_desc(ring) > XGBE_TX_DESC_MIN_FREE)) {
|
(xgbe_tx_avail_desc(ring) > XGBE_TX_DESC_MIN_FREE)) {
|
||||||
ring->tx.queue_stopped = 0;
|
ring->tx.queue_stopped = 0;
|
||||||
netif_wake_subqueue(netdev, channel->queue_index);
|
netif_tx_wake_queue(txq);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBGPR("<--xgbe_tx_poll: processed=%d\n", processed);
|
DBGPR("<--xgbe_tx_poll: processed=%d\n", processed);
|
||||||
|
|
||||||
|
unlock:
|
||||||
spin_unlock_irqrestore(&ring->lock, flags);
|
spin_unlock_irqrestore(&ring->lock, flags);
|
||||||
|
|
||||||
return processed;
|
return processed;
|
||||||
|
@ -1896,13 +1966,13 @@ read_again:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
put_len = rdata->len - len;
|
put_len = rdata->rx.len - len;
|
||||||
len += put_len;
|
len += put_len;
|
||||||
|
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
dma_sync_single_for_cpu(pdata->dev,
|
dma_sync_single_for_cpu(pdata->dev,
|
||||||
rdata->rx_hdr.dma,
|
rdata->rx.hdr.dma,
|
||||||
rdata->rx_hdr.dma_len,
|
rdata->rx.hdr.dma_len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
skb = xgbe_create_skb(pdata, rdata, &put_len);
|
skb = xgbe_create_skb(pdata, rdata, &put_len);
|
||||||
|
@ -1914,15 +1984,15 @@ read_again:
|
||||||
|
|
||||||
if (put_len) {
|
if (put_len) {
|
||||||
dma_sync_single_for_cpu(pdata->dev,
|
dma_sync_single_for_cpu(pdata->dev,
|
||||||
rdata->rx_buf.dma,
|
rdata->rx.buf.dma,
|
||||||
rdata->rx_buf.dma_len,
|
rdata->rx.buf.dma_len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
||||||
rdata->rx_buf.pa.pages,
|
rdata->rx.buf.pa.pages,
|
||||||
rdata->rx_buf.pa.pages_offset,
|
rdata->rx.buf.pa.pages_offset,
|
||||||
put_len, rdata->rx_buf.dma_len);
|
put_len, rdata->rx.buf.dma_len);
|
||||||
rdata->rx_buf.pa.pages = NULL;
|
rdata->rx.buf.pa.pages = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,17 @@
|
||||||
|
|
||||||
#define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1))
|
#define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1))
|
||||||
|
|
||||||
|
/* Descriptors required for maximum contigous TSO/GSO packet */
|
||||||
|
#define XGBE_TX_MAX_SPLIT ((GSO_MAX_SIZE / XGBE_TX_MAX_BUF_SIZE) + 1)
|
||||||
|
|
||||||
|
/* Maximum possible descriptors needed for an SKB:
|
||||||
|
* - Maximum number of SKB frags
|
||||||
|
* - Maximum descriptors for contiguous TSO/GSO packet
|
||||||
|
* - Possible context descriptor
|
||||||
|
* - Possible TSO header descriptor
|
||||||
|
*/
|
||||||
|
#define XGBE_TX_MAX_DESCS (MAX_SKB_FRAGS + XGBE_TX_MAX_SPLIT + 2)
|
||||||
|
|
||||||
#define XGBE_RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
|
#define XGBE_RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
|
||||||
#define XGBE_RX_BUF_ALIGN 64
|
#define XGBE_RX_BUF_ALIGN 64
|
||||||
#define XGBE_SKB_ALLOC_SIZE 256
|
#define XGBE_SKB_ALLOC_SIZE 256
|
||||||
|
@ -147,6 +158,7 @@
|
||||||
|
|
||||||
#define XGBE_MAX_DMA_CHANNELS 16
|
#define XGBE_MAX_DMA_CHANNELS 16
|
||||||
#define XGBE_MAX_QUEUES 16
|
#define XGBE_MAX_QUEUES 16
|
||||||
|
#define XGBE_DMA_STOP_TIMEOUT 5
|
||||||
|
|
||||||
/* DMA cache settings - Outer sharable, write-back, write-allocate */
|
/* DMA cache settings - Outer sharable, write-back, write-allocate */
|
||||||
#define XGBE_DMA_OS_AXDOMAIN 0x2
|
#define XGBE_DMA_OS_AXDOMAIN 0x2
|
||||||
|
@ -224,6 +236,8 @@
|
||||||
struct xgbe_prv_data;
|
struct xgbe_prv_data;
|
||||||
|
|
||||||
struct xgbe_packet_data {
|
struct xgbe_packet_data {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
|
||||||
unsigned int attributes;
|
unsigned int attributes;
|
||||||
|
|
||||||
unsigned int errors;
|
unsigned int errors;
|
||||||
|
@ -242,6 +256,9 @@ struct xgbe_packet_data {
|
||||||
|
|
||||||
u32 rss_hash;
|
u32 rss_hash;
|
||||||
enum pkt_hash_types rss_hash_type;
|
enum pkt_hash_types rss_hash_type;
|
||||||
|
|
||||||
|
unsigned int tx_packets;
|
||||||
|
unsigned int tx_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Common Rx and Tx descriptor mapping */
|
/* Common Rx and Tx descriptor mapping */
|
||||||
|
@ -270,6 +287,21 @@ struct xgbe_buffer_data {
|
||||||
unsigned int dma_len;
|
unsigned int dma_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Tx-related ring data */
|
||||||
|
struct xgbe_tx_ring_data {
|
||||||
|
unsigned int packets; /* BQL packet count */
|
||||||
|
unsigned int bytes; /* BQL byte count */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Rx-related ring data */
|
||||||
|
struct xgbe_rx_ring_data {
|
||||||
|
struct xgbe_buffer_data hdr; /* Header locations */
|
||||||
|
struct xgbe_buffer_data buf; /* Payload locations */
|
||||||
|
|
||||||
|
unsigned short hdr_len; /* Length of received header */
|
||||||
|
unsigned short len; /* Length of received packet */
|
||||||
|
};
|
||||||
|
|
||||||
/* Structure used to hold information related to the descriptor
|
/* Structure used to hold information related to the descriptor
|
||||||
* and the packet associated with the descriptor (always use
|
* and the packet associated with the descriptor (always use
|
||||||
* use the XGBE_GET_DESC_DATA macro to access this data from the ring)
|
* use the XGBE_GET_DESC_DATA macro to access this data from the ring)
|
||||||
|
@ -281,13 +313,9 @@ struct xgbe_ring_data {
|
||||||
struct sk_buff *skb; /* Virtual address of SKB */
|
struct sk_buff *skb; /* Virtual address of SKB */
|
||||||
dma_addr_t skb_dma; /* DMA address of SKB data */
|
dma_addr_t skb_dma; /* DMA address of SKB data */
|
||||||
unsigned int skb_dma_len; /* Length of SKB DMA area */
|
unsigned int skb_dma_len; /* Length of SKB DMA area */
|
||||||
unsigned int tso_header; /* TSO header indicator */
|
|
||||||
|
|
||||||
struct xgbe_buffer_data rx_hdr; /* Header locations */
|
struct xgbe_tx_ring_data tx; /* Tx-related data */
|
||||||
struct xgbe_buffer_data rx_buf; /* Payload locations */
|
struct xgbe_rx_ring_data rx; /* Rx-related data */
|
||||||
|
|
||||||
unsigned short hdr_len; /* Length of received header */
|
|
||||||
unsigned short len; /* Length of received Rx packet */
|
|
||||||
|
|
||||||
unsigned int interrupt; /* Interrupt indicator */
|
unsigned int interrupt; /* Interrupt indicator */
|
||||||
|
|
||||||
|
@ -345,6 +373,7 @@ struct xgbe_ring {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
unsigned int queue_stopped;
|
unsigned int queue_stopped;
|
||||||
|
unsigned int xmit_more;
|
||||||
unsigned short cur_mss;
|
unsigned short cur_mss;
|
||||||
unsigned short cur_vlan_ctag;
|
unsigned short cur_vlan_ctag;
|
||||||
} tx;
|
} tx;
|
||||||
|
@ -508,6 +537,7 @@ struct xgbe_hw_if {
|
||||||
void (*tx_desc_reset)(struct xgbe_ring_data *);
|
void (*tx_desc_reset)(struct xgbe_ring_data *);
|
||||||
int (*is_last_desc)(struct xgbe_ring_desc *);
|
int (*is_last_desc)(struct xgbe_ring_desc *);
|
||||||
int (*is_context_desc)(struct xgbe_ring_desc *);
|
int (*is_context_desc)(struct xgbe_ring_desc *);
|
||||||
|
void (*tx_start_xmit)(struct xgbe_channel *, struct xgbe_ring *);
|
||||||
|
|
||||||
/* For FLOW ctrl */
|
/* For FLOW ctrl */
|
||||||
int (*config_tx_flow_control)(struct xgbe_prv_data *);
|
int (*config_tx_flow_control)(struct xgbe_prv_data *);
|
||||||
|
|
Loading…
Reference in New Issue