mirror of https://gitee.com/openkylin/linux.git
sfc: Fix maximum number of TSO segments and minimum TX queue size
Currently an skb requiring TSO may not fit within a minimum-size TX queue. The TX queue selected for the skb may stall and trigger the TX watchdog repeatedly (since the problem skb will be retried after the TX reset). This issue is designated as CVE-2012-3412. Set the maximum number of TSO segments for our devices to 100. This should make no difference to behaviour unless the actual MSS is less than about 700. Increase the minimum TX queue size accordingly to allow for 2 worst-case skbs, so that there will definitely be space to add an skb after we wake a queue. To avoid invalidating existing configurations, change efx_ethtool_set_ringparam() to fix up values that are too small rather than returning -EINVAL. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
30b678d844
commit
7e6d06f0de
|
@ -1503,6 +1503,11 @@ static int efx_probe_all(struct efx_nic *efx)
|
|||
goto fail2;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT);
|
||||
if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) {
|
||||
rc = -EINVAL;
|
||||
goto fail3;
|
||||
}
|
||||
efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
|
||||
|
||||
rc = efx_probe_filters(efx);
|
||||
|
@ -2070,6 +2075,7 @@ static int efx_register_netdev(struct efx_nic *efx)
|
|||
net_dev->irq = efx->pci_dev->irq;
|
||||
net_dev->netdev_ops = &efx_netdev_ops;
|
||||
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
|
||||
net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ extern netdev_tx_t
|
|||
efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
|
||||
extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
|
||||
extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc);
|
||||
extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
|
||||
|
||||
/* RX */
|
||||
extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
|
||||
|
@ -52,10 +53,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
|
|||
#define EFX_MAX_EVQ_SIZE 16384UL
|
||||
#define EFX_MIN_EVQ_SIZE 512UL
|
||||
|
||||
/* The smallest [rt]xq_entries that the driver supports. Callers of
|
||||
* efx_wake_queue() assume that they can subsequently send at least one
|
||||
* skb. Falcon/A1 may require up to three descriptors per skb_frag. */
|
||||
#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS))
|
||||
/* Maximum number of TCP segments we support for soft-TSO */
|
||||
#define EFX_TSO_MAX_SEGS 100
|
||||
|
||||
/* The smallest [rt]xq_entries that the driver supports. RX minimum
|
||||
* is a bit arbitrary. For TX, we must have space for at least 2
|
||||
* TSO skbs.
|
||||
*/
|
||||
#define EFX_RXQ_MIN_ENT 128U
|
||||
#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx))
|
||||
|
||||
/* Filters */
|
||||
extern int efx_probe_filters(struct efx_nic *efx);
|
||||
|
|
|
@ -680,21 +680,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev,
|
|||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct efx_nic *efx = netdev_priv(net_dev);
|
||||
u32 txq_entries;
|
||||
|
||||
if (ring->rx_mini_pending || ring->rx_jumbo_pending ||
|
||||
ring->rx_pending > EFX_MAX_DMAQ_SIZE ||
|
||||
ring->tx_pending > EFX_MAX_DMAQ_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (ring->rx_pending < EFX_MIN_RING_SIZE ||
|
||||
ring->tx_pending < EFX_MIN_RING_SIZE) {
|
||||
if (ring->rx_pending < EFX_RXQ_MIN_ENT) {
|
||||
netif_err(efx, drv, efx->net_dev,
|
||||
"TX and RX queues cannot be smaller than %ld\n",
|
||||
EFX_MIN_RING_SIZE);
|
||||
"RX queues cannot be smaller than %u\n",
|
||||
EFX_RXQ_MIN_ENT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending);
|
||||
txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx));
|
||||
if (txq_entries != ring->tx_pending)
|
||||
netif_warn(efx, drv, efx->net_dev,
|
||||
"increasing TX queue size to minimum of %u\n",
|
||||
txq_entries);
|
||||
|
||||
return efx_realloc_channels(efx, ring->rx_pending, txq_entries);
|
||||
}
|
||||
|
||||
static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
|
||||
|
|
|
@ -119,6 +119,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr)
|
|||
return len;
|
||||
}
|
||||
|
||||
unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
|
||||
{
|
||||
/* Header and payload descriptor for each output segment, plus
|
||||
* one for every input fragment boundary within a segment
|
||||
*/
|
||||
unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS;
|
||||
|
||||
/* Possibly one more per segment for the alignment workaround */
|
||||
if (EFX_WORKAROUND_5391(efx))
|
||||
max_descs += EFX_TSO_MAX_SEGS;
|
||||
|
||||
/* Possibly more for PCIe page boundaries within input fragments */
|
||||
if (PAGE_SIZE > EFX_PAGE_SIZE)
|
||||
max_descs += max_t(unsigned int, MAX_SKB_FRAGS,
|
||||
DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE));
|
||||
|
||||
return max_descs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a socket buffer to a TX queue
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue