sfc: add support for skb->xmit_more

Don't ring the doorbell, and don't do PIO.  This will also prevent
 TX Push, because there will be more than one buffer waiting when
 the doorbell is rung.

Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Edward Cree 2014-10-17 15:32:25 +01:00 committed by David S. Miller
parent 6cc69f2a40
commit 70b33fb0dd
2 changed files with 43 additions and 29 deletions

View File

@ -71,9 +71,17 @@ efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
return ((efx_qword_t *) (tx_queue->txd.buf.addr)) + index; return ((efx_qword_t *) (tx_queue->txd.buf.addr)) + index;
} }
/* Report whether the NIC considers this TX queue empty, given the /* Get partner of a TX queue, seen as part of the same net core queue */
* write_count used for the last doorbell push. May return false static struct efx_tx_queue *efx_tx_queue_partner(struct efx_tx_queue *tx_queue)
* negative. {
if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
return tx_queue - EFX_TXQ_TYPE_OFFLOAD;
else
return tx_queue + EFX_TXQ_TYPE_OFFLOAD;
}
/* Report whether this TX queue would be empty for the given write_count.
* May return false negative.
*/ */
static inline bool __efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue, static inline bool __efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue,
unsigned int write_count) unsigned int write_count)
@ -86,9 +94,18 @@ static inline bool __efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue,
return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0; return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0;
} }
static inline bool efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue) /* Decide whether we can use TX PIO, ie. write packet data directly into
* a buffer on the device. This can reduce latency at the expense of
* throughput, so we only do this if both hardware and software TX rings
* are empty. This also ensures that only one packet at a time can be
* using the PIO buffer.
*/
static inline bool efx_nic_may_tx_pio(struct efx_tx_queue *tx_queue)
{ {
return __efx_nic_tx_is_empty(tx_queue, tx_queue->write_count); struct efx_tx_queue *partner = efx_tx_queue_partner(tx_queue);
return tx_queue->piobuf &&
__efx_nic_tx_is_empty(tx_queue, tx_queue->insert_count) &&
__efx_nic_tx_is_empty(partner, partner->insert_count);
} }
/* Decide whether to push a TX descriptor to the NIC vs merely writing /* Decide whether to push a TX descriptor to the NIC vs merely writing
@ -96,6 +113,8 @@ static inline bool efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue)
* descriptor to an empty queue, but is otherwise pointless. Further, * descriptor to an empty queue, but is otherwise pointless. Further,
* Falcon and Siena have hardware bugs (SF bug 33851) that may be * Falcon and Siena have hardware bugs (SF bug 33851) that may be
* triggered if we don't check this. * triggered if we don't check this.
* We use the write_count used for the last doorbell push, to get the
* NIC's view of the tx queue.
*/ */
static inline bool efx_nic_may_push_tx_desc(struct efx_tx_queue *tx_queue, static inline bool efx_nic_may_push_tx_desc(struct efx_tx_queue *tx_queue,
unsigned int write_count) unsigned int write_count)

View File

@ -132,15 +132,6 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
return max_descs; return max_descs;
} }
/* Get partner of a TX queue, seen as part of the same net core queue */
static struct efx_tx_queue *efx_tx_queue_partner(struct efx_tx_queue *tx_queue)
{
if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
return tx_queue - EFX_TXQ_TYPE_OFFLOAD;
else
return tx_queue + EFX_TXQ_TYPE_OFFLOAD;
}
static void efx_tx_maybe_stop_queue(struct efx_tx_queue *txq1) static void efx_tx_maybe_stop_queue(struct efx_tx_queue *txq1)
{ {
/* We need to consider both queues that the net core sees as one */ /* We need to consider both queues that the net core sees as one */
@ -344,6 +335,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
struct efx_nic *efx = tx_queue->efx; struct efx_nic *efx = tx_queue->efx;
struct device *dma_dev = &efx->pci_dev->dev; struct device *dma_dev = &efx->pci_dev->dev;
struct efx_tx_buffer *buffer; struct efx_tx_buffer *buffer;
unsigned int old_insert_count = tx_queue->insert_count;
skb_frag_t *fragment; skb_frag_t *fragment;
unsigned int len, unmap_len = 0; unsigned int len, unmap_len = 0;
dma_addr_t dma_addr, unmap_addr = 0; dma_addr_t dma_addr, unmap_addr = 0;
@ -351,7 +343,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
unsigned short dma_flags; unsigned short dma_flags;
int i = 0; int i = 0;
EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count); EFX_BUG_ON_PARANOID(tx_queue->write_count > tx_queue->insert_count);
if (skb_shinfo(skb)->gso_size) if (skb_shinfo(skb)->gso_size)
return efx_enqueue_skb_tso(tx_queue, skb); return efx_enqueue_skb_tso(tx_queue, skb);
@ -369,9 +361,8 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
/* Consider using PIO for short packets */ /* Consider using PIO for short packets */
#ifdef EFX_USE_PIO #ifdef EFX_USE_PIO
if (skb->len <= efx_piobuf_size && tx_queue->piobuf && if (skb->len <= efx_piobuf_size && !skb->xmit_more &&
efx_nic_tx_is_empty(tx_queue) && efx_nic_may_tx_pio(tx_queue)) {
efx_nic_tx_is_empty(efx_tx_queue_partner(tx_queue))) {
buffer = efx_enqueue_skb_pio(tx_queue, skb); buffer = efx_enqueue_skb_pio(tx_queue, skb);
dma_flags = EFX_TX_BUF_OPTION; dma_flags = EFX_TX_BUF_OPTION;
goto finish_packet; goto finish_packet;
@ -439,13 +430,14 @@ finish_packet:
netdev_tx_sent_queue(tx_queue->core_txq, skb->len); netdev_tx_sent_queue(tx_queue->core_txq, skb->len);
efx_tx_maybe_stop_queue(tx_queue);
/* Pass off to hardware */ /* Pass off to hardware */
efx_nic_push_buffers(tx_queue); if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
efx_nic_push_buffers(tx_queue);
tx_queue->tx_packets++; tx_queue->tx_packets++;
efx_tx_maybe_stop_queue(tx_queue);
return NETDEV_TX_OK; return NETDEV_TX_OK;
dma_err: dma_err:
@ -458,7 +450,7 @@ finish_packet:
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
/* Work backwards until we hit the original insert pointer value */ /* Work backwards until we hit the original insert pointer value */
while (tx_queue->insert_count != tx_queue->write_count) { while (tx_queue->insert_count != old_insert_count) {
unsigned int pkts_compl = 0, bytes_compl = 0; unsigned int pkts_compl = 0, bytes_compl = 0;
--tx_queue->insert_count; --tx_queue->insert_count;
buffer = __efx_tx_queue_get_insert_buffer(tx_queue); buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
@ -989,12 +981,13 @@ static int efx_tso_put_header(struct efx_tx_queue *tx_queue,
/* Remove buffers put into a tx_queue. None of the buffers must have /* Remove buffers put into a tx_queue. None of the buffers must have
* an skb attached. * an skb attached.
*/ */
static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
unsigned int insert_count)
{ {
struct efx_tx_buffer *buffer; struct efx_tx_buffer *buffer;
/* Work backwards until we hit the original insert pointer value */ /* Work backwards until we hit the original insert pointer value */
while (tx_queue->insert_count != tx_queue->write_count) { while (tx_queue->insert_count != insert_count) {
--tx_queue->insert_count; --tx_queue->insert_count;
buffer = __efx_tx_queue_get_insert_buffer(tx_queue); buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
efx_dequeue_buffer(tx_queue, buffer, NULL, NULL); efx_dequeue_buffer(tx_queue, buffer, NULL, NULL);
@ -1258,13 +1251,14 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct efx_nic *efx = tx_queue->efx; struct efx_nic *efx = tx_queue->efx;
unsigned int old_insert_count = tx_queue->insert_count;
int frag_i, rc; int frag_i, rc;
struct tso_state state; struct tso_state state;
/* Find the packet protocol and sanity-check it */ /* Find the packet protocol and sanity-check it */
state.protocol = efx_tso_check_protocol(skb); state.protocol = efx_tso_check_protocol(skb);
EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count); EFX_BUG_ON_PARANOID(tx_queue->write_count > tx_queue->insert_count);
rc = tso_start(&state, efx, skb); rc = tso_start(&state, efx, skb);
if (rc) if (rc)
@ -1308,11 +1302,12 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
netdev_tx_sent_queue(tx_queue->core_txq, skb->len); netdev_tx_sent_queue(tx_queue->core_txq, skb->len);
/* Pass off to hardware */
efx_nic_push_buffers(tx_queue);
efx_tx_maybe_stop_queue(tx_queue); efx_tx_maybe_stop_queue(tx_queue);
/* Pass off to hardware */
if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
efx_nic_push_buffers(tx_queue);
tx_queue->tso_bursts++; tx_queue->tso_bursts++;
return NETDEV_TX_OK; return NETDEV_TX_OK;
@ -1336,6 +1331,6 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
dma_unmap_single(&efx->pci_dev->dev, state.header_dma_addr, dma_unmap_single(&efx->pci_dev->dev, state.header_dma_addr,
state.header_unmap_len, DMA_TO_DEVICE); state.header_unmap_len, DMA_TO_DEVICE);
efx_enqueue_unwind(tx_queue); efx_enqueue_unwind(tx_queue, old_insert_count);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }