mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
Merge branch 'implement-more-features-for-txgbe-devices'
Jiawen Wu says: ==================== Implement more features for txgbe devices Based on the features of hardware support, implement RX desc merge and TX head write-back for AML devices, support RSC offload for AML and SP devices. ==================== Link: https://patch.msgid.link/20251023014538.12644-1-jiawenwu@trustnetic.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -51,6 +51,11 @@ static const struct wx_stats wx_gstrings_fdir_stats[] = {
|
||||
WX_STAT("fdir_miss", stats.fdirmiss),
|
||||
};
|
||||
|
||||
static const struct wx_stats wx_gstrings_rsc_stats[] = {
|
||||
WX_STAT("rsc_aggregated", rsc_count),
|
||||
WX_STAT("rsc_flushed", rsc_flush),
|
||||
};
|
||||
|
||||
/* drivers allocates num_tx_queues and num_rx_queues symmetrically so
|
||||
* we set the num_rx_queues to evaluate to num_tx_queues. This is
|
||||
* used because we do not have a good way to get the max number of
|
||||
@@ -64,16 +69,21 @@ static const struct wx_stats wx_gstrings_fdir_stats[] = {
|
||||
(sizeof(struct wx_queue_stats) / sizeof(u64)))
|
||||
#define WX_GLOBAL_STATS_LEN ARRAY_SIZE(wx_gstrings_stats)
|
||||
#define WX_FDIR_STATS_LEN ARRAY_SIZE(wx_gstrings_fdir_stats)
|
||||
#define WX_RSC_STATS_LEN ARRAY_SIZE(wx_gstrings_rsc_stats)
|
||||
#define WX_STATS_LEN (WX_GLOBAL_STATS_LEN + WX_QUEUE_STATS_LEN)
|
||||
|
||||
int wx_get_sset_count(struct net_device *netdev, int sset)
|
||||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
int len = WX_STATS_LEN;
|
||||
|
||||
switch (sset) {
|
||||
case ETH_SS_STATS:
|
||||
return (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) ?
|
||||
WX_STATS_LEN + WX_FDIR_STATS_LEN : WX_STATS_LEN;
|
||||
if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))
|
||||
len += WX_FDIR_STATS_LEN;
|
||||
if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags))
|
||||
len += WX_RSC_STATS_LEN;
|
||||
return len;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -94,6 +104,10 @@ void wx_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
|
||||
for (i = 0; i < WX_FDIR_STATS_LEN; i++)
|
||||
ethtool_puts(&p, wx_gstrings_fdir_stats[i].stat_string);
|
||||
}
|
||||
if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) {
|
||||
for (i = 0; i < WX_RSC_STATS_LEN; i++)
|
||||
ethtool_puts(&p, wx_gstrings_rsc_stats[i].stat_string);
|
||||
}
|
||||
for (i = 0; i < netdev->num_tx_queues; i++) {
|
||||
ethtool_sprintf(&p, "tx_queue_%u_packets", i);
|
||||
ethtool_sprintf(&p, "tx_queue_%u_bytes", i);
|
||||
@@ -131,6 +145,13 @@ void wx_get_ethtool_stats(struct net_device *netdev,
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) {
|
||||
for (k = 0; k < WX_RSC_STATS_LEN; k++) {
|
||||
p = (char *)wx + wx_gstrings_rsc_stats[k].stat_offset;
|
||||
data[i++] = *(u64 *)p;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < netdev->num_tx_queues; j++) {
|
||||
ring = wx->tx_ring[j];
|
||||
if (!ring) {
|
||||
@@ -322,6 +343,40 @@ int wx_get_coalesce(struct net_device *netdev,
|
||||
}
|
||||
EXPORT_SYMBOL(wx_get_coalesce);
|
||||
|
||||
static void wx_update_rsc(struct wx *wx)
|
||||
{
|
||||
struct net_device *netdev = wx->netdev;
|
||||
bool need_reset = false;
|
||||
|
||||
/* nothing to do if LRO or RSC are not enabled */
|
||||
if (!test_bit(WX_FLAG_RSC_CAPABLE, wx->flags) ||
|
||||
!(netdev->features & NETIF_F_LRO))
|
||||
return;
|
||||
|
||||
/* check the feature flag value and enable RSC if necessary */
|
||||
if (wx->rx_itr_setting == 1 ||
|
||||
wx->rx_itr_setting > WX_MIN_RSC_ITR) {
|
||||
if (!test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) {
|
||||
set_bit(WX_FLAG_RSC_ENABLED, wx->flags);
|
||||
dev_info(&wx->pdev->dev,
|
||||
"rx-usecs value high enough to re-enable RSC\n");
|
||||
|
||||
need_reset = true;
|
||||
}
|
||||
/* if interrupt rate is too high then disable RSC */
|
||||
} else if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) {
|
||||
clear_bit(WX_FLAG_RSC_ENABLED, wx->flags);
|
||||
dev_info(&wx->pdev->dev,
|
||||
"rx-usecs set too low, disabling RSC\n");
|
||||
|
||||
need_reset = true;
|
||||
}
|
||||
|
||||
/* reset the device to apply the new RSC setting */
|
||||
if (need_reset && wx->do_reset)
|
||||
wx->do_reset(netdev);
|
||||
}
|
||||
|
||||
int wx_set_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ec,
|
||||
struct kernel_ethtool_coalesce *kernel_coal,
|
||||
@@ -414,6 +469,8 @@ int wx_set_coalesce(struct net_device *netdev,
|
||||
wx_write_eitr(q_vector);
|
||||
}
|
||||
|
||||
wx_update_rsc(wx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(wx_set_coalesce);
|
||||
|
||||
@@ -1779,7 +1779,9 @@ EXPORT_SYMBOL(wx_set_rx_mode);
|
||||
static void wx_set_rx_buffer_len(struct wx *wx)
|
||||
{
|
||||
struct net_device *netdev = wx->netdev;
|
||||
struct wx_ring *rx_ring;
|
||||
u32 mhadd, max_frame;
|
||||
int i;
|
||||
|
||||
max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
|
||||
/* adjust max frame to be at least the size of a standard frame */
|
||||
@@ -1789,6 +1791,19 @@ static void wx_set_rx_buffer_len(struct wx *wx)
|
||||
mhadd = rd32(wx, WX_PSR_MAX_SZ);
|
||||
if (max_frame != mhadd)
|
||||
wr32(wx, WX_PSR_MAX_SZ, max_frame);
|
||||
|
||||
/*
|
||||
* Setup the HW Rx Head and Tail Descriptor Pointers and
|
||||
* the Base and Length of the Rx Descriptor Ring
|
||||
*/
|
||||
for (i = 0; i < wx->num_rx_queues; i++) {
|
||||
rx_ring = wx->rx_ring[i];
|
||||
rx_ring->rx_buf_len = WX_RXBUFFER_2K;
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags))
|
||||
rx_ring->rx_buf_len = WX_RXBUFFER_3K;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1865,11 +1880,27 @@ static void wx_configure_srrctl(struct wx *wx,
|
||||
srrctl |= WX_RXBUFFER_256 << WX_PX_RR_CFG_BHDRSIZE_SHIFT;
|
||||
|
||||
/* configure the packet buffer length */
|
||||
srrctl |= WX_RX_BUFSZ >> WX_PX_RR_CFG_BSIZEPKT_SHIFT;
|
||||
srrctl |= rx_ring->rx_buf_len >> WX_PX_RR_CFG_BSIZEPKT_SHIFT;
|
||||
|
||||
wr32(wx, WX_PX_RR_CFG(reg_idx), srrctl);
|
||||
}
|
||||
|
||||
static void wx_configure_rscctl(struct wx *wx,
|
||||
struct wx_ring *ring)
|
||||
{
|
||||
u8 reg_idx = ring->reg_idx;
|
||||
u32 rscctrl;
|
||||
|
||||
if (!test_bit(WX_FLAG_RSC_ENABLED, wx->flags))
|
||||
return;
|
||||
|
||||
rscctrl = rd32(wx, WX_PX_RR_CFG(reg_idx));
|
||||
rscctrl |= WX_PX_RR_CFG_RSC;
|
||||
rscctrl |= WX_PX_RR_CFG_MAX_RSCBUF_16;
|
||||
|
||||
wr32(wx, WX_PX_RR_CFG(reg_idx), rscctrl);
|
||||
}
|
||||
|
||||
static void wx_configure_tx_ring(struct wx *wx,
|
||||
struct wx_ring *ring)
|
||||
{
|
||||
@@ -1905,6 +1936,15 @@ static void wx_configure_tx_ring(struct wx *wx,
|
||||
memset(ring->tx_buffer_info, 0,
|
||||
sizeof(struct wx_tx_buffer) * ring->count);
|
||||
|
||||
if (ring->headwb_mem) {
|
||||
wr32(wx, WX_PX_TR_HEAD_ADDRL(reg_idx),
|
||||
ring->headwb_dma & DMA_BIT_MASK(32));
|
||||
wr32(wx, WX_PX_TR_HEAD_ADDRH(reg_idx),
|
||||
upper_32_bits(ring->headwb_dma));
|
||||
|
||||
txdctl |= WX_PX_TR_CFG_HEAD_WB;
|
||||
}
|
||||
|
||||
/* enable queue */
|
||||
wr32(wx, WX_PX_TR_CFG(reg_idx), txdctl);
|
||||
|
||||
@@ -1935,6 +1975,10 @@ static void wx_configure_rx_ring(struct wx *wx,
|
||||
rxdctl |= (ring->count / 128) << WX_PX_RR_CFG_RR_SIZE_SHIFT;
|
||||
|
||||
rxdctl |= 0x1 << WX_PX_RR_CFG_RR_THER_SHIFT;
|
||||
|
||||
if (test_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags))
|
||||
rxdctl |= WX_PX_RR_CFG_DESC_MERGE;
|
||||
|
||||
wr32(wx, WX_PX_RR_CFG(reg_idx), rxdctl);
|
||||
|
||||
/* reset head and tail pointers */
|
||||
@@ -1943,6 +1987,7 @@ static void wx_configure_rx_ring(struct wx *wx,
|
||||
ring->tail = wx->hw_addr + WX_PX_RR_WP(reg_idx);
|
||||
|
||||
wx_configure_srrctl(wx, ring);
|
||||
wx_configure_rscctl(wx, ring);
|
||||
|
||||
/* initialize rx_buffer_info */
|
||||
memset(ring->rx_buffer_info, 0,
|
||||
@@ -2181,7 +2226,9 @@ void wx_configure_rx(struct wx *wx)
|
||||
/* RSC Setup */
|
||||
psrctl = rd32(wx, WX_PSR_CTL);
|
||||
psrctl |= WX_PSR_CTL_RSC_ACK; /* Disable RSC for ACK packets */
|
||||
psrctl |= WX_PSR_CTL_RSC_DIS;
|
||||
psrctl &= ~WX_PSR_CTL_RSC_DIS;
|
||||
if (!test_bit(WX_FLAG_RSC_ENABLED, wx->flags))
|
||||
psrctl |= WX_PSR_CTL_RSC_DIS;
|
||||
wr32(wx, WX_PSR_CTL, psrctl);
|
||||
}
|
||||
|
||||
@@ -2190,6 +2237,12 @@ void wx_configure_rx(struct wx *wx)
|
||||
/* set_rx_buffer_len must be called before ring initialization */
|
||||
wx_set_rx_buffer_len(wx);
|
||||
|
||||
if (test_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags)) {
|
||||
wr32(wx, WX_RDM_DCACHE_CTL, WX_RDM_DCACHE_CTL_EN);
|
||||
wr32m(wx, WX_RDM_RSC_CTL,
|
||||
WX_RDM_RSC_CTL_FREE_CTL | WX_RDM_RSC_CTL_FREE_CNT_DIS,
|
||||
WX_RDM_RSC_CTL_FREE_CTL);
|
||||
}
|
||||
/* Setup the HW Rx Head and Tail Descriptor Pointers and
|
||||
* the Base and Length of the Rx Descriptor Ring
|
||||
*/
|
||||
@@ -2805,6 +2858,18 @@ void wx_update_stats(struct wx *wx)
|
||||
wx->hw_csum_rx_error = hw_csum_rx_error;
|
||||
wx->hw_csum_rx_good = hw_csum_rx_good;
|
||||
|
||||
if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) {
|
||||
u64 rsc_count = 0;
|
||||
u64 rsc_flush = 0;
|
||||
|
||||
for (i = 0; i < wx->num_rx_queues; i++) {
|
||||
rsc_count += wx->rx_ring[i]->rx_stats.rsc_count;
|
||||
rsc_flush += wx->rx_ring[i]->rx_stats.rsc_flush;
|
||||
}
|
||||
wx->rsc_count = rsc_count;
|
||||
wx->rsc_flush = rsc_flush;
|
||||
}
|
||||
|
||||
for (i = 0; i < wx->num_tx_queues; i++) {
|
||||
struct wx_ring *tx_ring = wx->tx_ring[i];
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ static struct sk_buff *wx_build_skb(struct wx_ring *rx_ring,
|
||||
{
|
||||
unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
|
||||
#if (PAGE_SIZE < 8192)
|
||||
unsigned int truesize = WX_RX_BUFSZ;
|
||||
unsigned int truesize = wx_rx_pg_size(rx_ring) / 2;
|
||||
#else
|
||||
unsigned int truesize = ALIGN(size, L1_CACHE_BYTES);
|
||||
#endif
|
||||
@@ -341,7 +341,7 @@ void wx_alloc_rx_buffers(struct wx_ring *rx_ring, u16 cleaned_count)
|
||||
/* sync the buffer for use by the device */
|
||||
dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
|
||||
bi->page_offset,
|
||||
WX_RX_BUFSZ,
|
||||
rx_ring->rx_buf_len,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
rx_desc->read.pkt_addr =
|
||||
@@ -404,6 +404,7 @@ static bool wx_is_non_eop(struct wx_ring *rx_ring,
|
||||
union wx_rx_desc *rx_desc,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct wx *wx = rx_ring->q_vector->wx;
|
||||
u32 ntc = rx_ring->next_to_clean + 1;
|
||||
|
||||
/* fetch, update, and store next to clean */
|
||||
@@ -412,6 +413,24 @@ static bool wx_is_non_eop(struct wx_ring *rx_ring,
|
||||
|
||||
prefetch(WX_RX_DESC(rx_ring, ntc));
|
||||
|
||||
/* update RSC append count if present */
|
||||
if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) {
|
||||
__le32 rsc_enabled = rx_desc->wb.lower.lo_dword.data &
|
||||
cpu_to_le32(WX_RXD_RSCCNT_MASK);
|
||||
|
||||
if (unlikely(rsc_enabled)) {
|
||||
u32 rsc_cnt = le32_to_cpu(rsc_enabled);
|
||||
|
||||
rsc_cnt >>= WX_RXD_RSCCNT_SHIFT;
|
||||
WX_CB(skb)->append_cnt += rsc_cnt - 1;
|
||||
|
||||
/* update ntc based on RSC value */
|
||||
ntc = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
ntc &= WX_RXD_NEXTP_MASK;
|
||||
ntc >>= WX_RXD_NEXTP_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we are the last buffer then there is nothing else to do */
|
||||
if (likely(wx_test_staterr(rx_desc, WX_RXD_STAT_EOP)))
|
||||
return false;
|
||||
@@ -582,6 +601,33 @@ static void wx_rx_vlan(struct wx_ring *ring, union wx_rx_desc *rx_desc,
|
||||
}
|
||||
}
|
||||
|
||||
static void wx_set_rsc_gso_size(struct wx_ring *ring,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u16 hdr_len = skb_headlen(skb);
|
||||
|
||||
/* set gso_size to avoid messing up TCP MSS */
|
||||
skb_shinfo(skb)->gso_size = DIV_ROUND_UP((skb->len - hdr_len),
|
||||
WX_CB(skb)->append_cnt);
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
|
||||
}
|
||||
|
||||
static void wx_update_rsc_stats(struct wx_ring *rx_ring,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
/* if append_cnt is 0 then frame is not RSC */
|
||||
if (!WX_CB(skb)->append_cnt)
|
||||
return;
|
||||
|
||||
rx_ring->rx_stats.rsc_count += WX_CB(skb)->append_cnt;
|
||||
rx_ring->rx_stats.rsc_flush++;
|
||||
|
||||
wx_set_rsc_gso_size(rx_ring, skb);
|
||||
|
||||
/* gso_size is computed using append_cnt so always clear it last */
|
||||
WX_CB(skb)->append_cnt = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* wx_process_skb_fields - Populate skb header fields from Rx descriptor
|
||||
* @rx_ring: rx descriptor ring packet is being transacted on
|
||||
@@ -598,6 +644,9 @@ static void wx_process_skb_fields(struct wx_ring *rx_ring,
|
||||
{
|
||||
struct wx *wx = netdev_priv(rx_ring->netdev);
|
||||
|
||||
if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags))
|
||||
wx_update_rsc_stats(rx_ring, skb);
|
||||
|
||||
wx_rx_hash(rx_ring, rx_desc, skb);
|
||||
wx_rx_checksum(rx_ring, rx_desc, skb);
|
||||
|
||||
@@ -735,9 +784,22 @@ static bool wx_clean_tx_irq(struct wx_q_vector *q_vector,
|
||||
/* prevent any other reads prior to eop_desc */
|
||||
smp_rmb();
|
||||
|
||||
/* if DD is not set pending work has not been completed */
|
||||
if (!(eop_desc->wb.status & cpu_to_le32(WX_TXD_STAT_DD)))
|
||||
if (tx_ring->headwb_mem) {
|
||||
u32 head = *tx_ring->headwb_mem;
|
||||
|
||||
if (head == tx_ring->next_to_clean)
|
||||
break;
|
||||
else if (head > tx_ring->next_to_clean &&
|
||||
!(tx_buffer->next_eop >= tx_ring->next_to_clean &&
|
||||
tx_buffer->next_eop < head))
|
||||
break;
|
||||
else if (!(tx_buffer->next_eop >= tx_ring->next_to_clean ||
|
||||
tx_buffer->next_eop < head))
|
||||
break;
|
||||
} else if (!(eop_desc->wb.status & cpu_to_le32(WX_TXD_STAT_DD))) {
|
||||
/* if DD is not set pending work has not been completed */
|
||||
break;
|
||||
}
|
||||
|
||||
/* clear next_to_watch to prevent false hangs */
|
||||
tx_buffer->next_to_watch = NULL;
|
||||
@@ -1075,6 +1137,10 @@ static int wx_tx_map(struct wx_ring *tx_ring,
|
||||
/* set next_to_watch value indicating a packet is present */
|
||||
first->next_to_watch = tx_desc;
|
||||
|
||||
/* set next_eop for amlite tx head wb */
|
||||
if (tx_ring->headwb_mem)
|
||||
first->next_eop = i;
|
||||
|
||||
i++;
|
||||
if (i == tx_ring->count)
|
||||
i = 0;
|
||||
@@ -2532,7 +2598,7 @@ static void wx_clean_rx_ring(struct wx_ring *rx_ring)
|
||||
dma_sync_single_range_for_cpu(rx_ring->dev,
|
||||
rx_buffer->dma,
|
||||
rx_buffer->page_offset,
|
||||
WX_RX_BUFSZ,
|
||||
rx_ring->rx_buf_len,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
/* free resources associated with mapping */
|
||||
@@ -2683,6 +2749,16 @@ void wx_clean_all_tx_rings(struct wx *wx)
|
||||
}
|
||||
EXPORT_SYMBOL(wx_clean_all_tx_rings);
|
||||
|
||||
static void wx_free_headwb_resources(struct wx_ring *tx_ring)
|
||||
{
|
||||
if (!tx_ring->headwb_mem)
|
||||
return;
|
||||
|
||||
dma_free_coherent(tx_ring->dev, sizeof(u32),
|
||||
tx_ring->headwb_mem, tx_ring->headwb_dma);
|
||||
tx_ring->headwb_mem = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* wx_free_tx_resources - Free Tx Resources per Queue
|
||||
* @tx_ring: Tx descriptor ring for a specific queue
|
||||
@@ -2702,6 +2778,8 @@ static void wx_free_tx_resources(struct wx_ring *tx_ring)
|
||||
dma_free_coherent(tx_ring->dev, tx_ring->size,
|
||||
tx_ring->desc, tx_ring->dma);
|
||||
tx_ring->desc = NULL;
|
||||
|
||||
wx_free_headwb_resources(tx_ring);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2731,13 +2809,14 @@ static int wx_alloc_page_pool(struct wx_ring *rx_ring)
|
||||
|
||||
struct page_pool_params pp_params = {
|
||||
.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
|
||||
.order = 0,
|
||||
.pool_size = rx_ring->count,
|
||||
.order = wx_rx_pg_order(rx_ring),
|
||||
.pool_size = rx_ring->count * rx_ring->rx_buf_len /
|
||||
wx_rx_pg_size(rx_ring),
|
||||
.nid = dev_to_node(rx_ring->dev),
|
||||
.dev = rx_ring->dev,
|
||||
.dma_dir = DMA_FROM_DEVICE,
|
||||
.offset = 0,
|
||||
.max_len = PAGE_SIZE,
|
||||
.max_len = wx_rx_pg_size(rx_ring),
|
||||
};
|
||||
|
||||
rx_ring->page_pool = page_pool_create(&pp_params);
|
||||
@@ -2840,6 +2919,24 @@ err_setup_rx:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void wx_setup_headwb_resources(struct wx_ring *tx_ring)
|
||||
{
|
||||
struct wx *wx = netdev_priv(tx_ring->netdev);
|
||||
|
||||
if (!test_bit(WX_FLAG_TXHEAD_WB_ENABLED, wx->flags))
|
||||
return;
|
||||
|
||||
if (!tx_ring->q_vector)
|
||||
return;
|
||||
|
||||
tx_ring->headwb_mem = dma_alloc_coherent(tx_ring->dev,
|
||||
sizeof(u32),
|
||||
&tx_ring->headwb_dma,
|
||||
GFP_KERNEL);
|
||||
if (!tx_ring->headwb_mem)
|
||||
dev_info(tx_ring->dev, "Allocate headwb memory failed, disable it\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* wx_setup_tx_resources - allocate Tx resources (Descriptors)
|
||||
* @tx_ring: tx descriptor ring (for a specific queue) to setup
|
||||
@@ -2880,6 +2977,8 @@ static int wx_setup_tx_resources(struct wx_ring *tx_ring)
|
||||
if (!tx_ring->desc)
|
||||
goto err;
|
||||
|
||||
wx_setup_headwb_resources(tx_ring);
|
||||
|
||||
tx_ring->next_to_use = 0;
|
||||
tx_ring->next_to_clean = 0;
|
||||
|
||||
@@ -3026,8 +3125,25 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
|
||||
else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER))
|
||||
wx_set_rx_mode(netdev);
|
||||
|
||||
if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) {
|
||||
if (!(features & NETIF_F_LRO)) {
|
||||
if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags))
|
||||
need_reset = true;
|
||||
clear_bit(WX_FLAG_RSC_ENABLED, wx->flags);
|
||||
} else if (!(test_bit(WX_FLAG_RSC_ENABLED, wx->flags))) {
|
||||
if (wx->rx_itr_setting == 1 ||
|
||||
wx->rx_itr_setting > WX_MIN_RSC_ITR) {
|
||||
set_bit(WX_FLAG_RSC_ENABLED, wx->flags);
|
||||
need_reset = true;
|
||||
} else if (changed & NETIF_F_LRO) {
|
||||
dev_info(&wx->pdev->dev,
|
||||
"rx-usecs set too low, disable RSC\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
/* Check if Flow Director n-tuple support was enabled or disabled. If
|
||||
* the state changed, we need to reset.
|
||||
@@ -3053,6 +3169,7 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if (need_reset && wx->do_reset)
|
||||
wx->do_reset(netdev);
|
||||
|
||||
@@ -3102,6 +3219,14 @@ netdev_features_t wx_fix_features(struct net_device *netdev,
|
||||
}
|
||||
}
|
||||
|
||||
/* If Rx checksum is disabled, then RSC/LRO should also be disabled */
|
||||
if (!(features & NETIF_F_RXCSUM))
|
||||
features &= ~NETIF_F_LRO;
|
||||
|
||||
/* Turn off LRO if not RSC capable */
|
||||
if (!test_bit(WX_FLAG_RSC_CAPABLE, wx->flags))
|
||||
features &= ~NETIF_F_LRO;
|
||||
|
||||
return features;
|
||||
}
|
||||
EXPORT_SYMBOL(wx_fix_features);
|
||||
|
||||
@@ -122,6 +122,10 @@ static int __wx_enable_sriov(struct wx *wx, u8 num_vfs)
|
||||
WX_CFG_PORT_CTL_NUM_VT_MASK,
|
||||
value);
|
||||
|
||||
/* Disable RSC when in SR-IOV mode */
|
||||
clear_bit(WX_FLAG_RSC_CAPABLE, wx->flags);
|
||||
clear_bit(WX_FLAG_RSC_ENABLED, wx->flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,8 +83,13 @@
|
||||
|
||||
/*********************** Receive DMA registers **************************/
|
||||
#define WX_RDM_VF_RE(_i) (0x12004 + ((_i) * 4))
|
||||
#define WX_RDM_RSC_CTL 0x1200C
|
||||
#define WX_RDM_RSC_CTL_FREE_CNT_DIS BIT(8)
|
||||
#define WX_RDM_RSC_CTL_FREE_CTL BIT(7)
|
||||
#define WX_RDM_PF_QDE(_i) (0x12080 + ((_i) * 4))
|
||||
#define WX_RDM_VFRE_CLR(_i) (0x120A0 + ((_i) * 4))
|
||||
#define WX_RDM_DCACHE_CTL 0x120A8
|
||||
#define WX_RDM_DCACHE_CTL_EN BIT(0)
|
||||
#define WX_RDM_DRP_PKT 0x12500
|
||||
#define WX_RDM_PKT_CNT 0x12504
|
||||
#define WX_RDM_BYTE_CNT_LSB 0x12508
|
||||
@@ -419,6 +424,7 @@ enum WX_MSCA_CMD_value {
|
||||
#define WX_7K_ITR 595
|
||||
#define WX_12K_ITR 336
|
||||
#define WX_20K_ITR 200
|
||||
#define WX_MIN_RSC_ITR 24
|
||||
#define WX_SP_MAX_EITR 0x00000FF8U
|
||||
#define WX_AML_MAX_EITR 0x00000FFFU
|
||||
#define WX_EM_MAX_EITR 0x00007FFCU
|
||||
@@ -429,12 +435,15 @@ enum WX_MSCA_CMD_value {
|
||||
#define WX_PX_TR_WP(_i) (0x03008 + ((_i) * 0x40))
|
||||
#define WX_PX_TR_RP(_i) (0x0300C + ((_i) * 0x40))
|
||||
#define WX_PX_TR_CFG(_i) (0x03010 + ((_i) * 0x40))
|
||||
#define WX_PX_TR_HEAD_ADDRL(_i) (0x03028 + ((_i) * 0x40))
|
||||
#define WX_PX_TR_HEAD_ADDRH(_i) (0x0302C + ((_i) * 0x40))
|
||||
/* Transmit Config masks */
|
||||
#define WX_PX_TR_CFG_ENABLE BIT(0) /* Ena specific Tx Queue */
|
||||
#define WX_PX_TR_CFG_TR_SIZE_SHIFT 1 /* tx desc number per ring */
|
||||
#define WX_PX_TR_CFG_SWFLSH BIT(26) /* Tx Desc. wr-bk flushing */
|
||||
#define WX_PX_TR_CFG_WTHRESH_SHIFT 16 /* shift to WTHRESH bits */
|
||||
#define WX_PX_TR_CFG_THRE_SHIFT 8
|
||||
#define WX_PX_TR_CFG_HEAD_WB BIT(27)
|
||||
|
||||
/* Receive DMA Registers */
|
||||
#define WX_PX_RR_BAL(_i) (0x01000 + ((_i) * 0x40))
|
||||
@@ -446,7 +455,10 @@ enum WX_MSCA_CMD_value {
|
||||
/* PX_RR_CFG bit definitions */
|
||||
#define WX_PX_RR_CFG_VLAN BIT(31)
|
||||
#define WX_PX_RR_CFG_DROP_EN BIT(30)
|
||||
#define WX_PX_RR_CFG_RSC BIT(29)
|
||||
#define WX_PX_RR_CFG_SPLIT_MODE BIT(26)
|
||||
#define WX_PX_RR_CFG_MAX_RSCBUF_16 FIELD_PREP(GENMASK(24, 23), 3)
|
||||
#define WX_PX_RR_CFG_DESC_MERGE BIT(19)
|
||||
#define WX_PX_RR_CFG_RR_THER_SHIFT 16
|
||||
#define WX_PX_RR_CFG_RR_HDR_SZ GENMASK(15, 12)
|
||||
#define WX_PX_RR_CFG_RR_BUF_SZ GENMASK(11, 8)
|
||||
@@ -542,14 +554,9 @@ enum WX_MSCA_CMD_value {
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define WX_RXBUFFER_256 256 /* Used for skb receive header */
|
||||
#define WX_RXBUFFER_2K 2048
|
||||
#define WX_RXBUFFER_3K 3072
|
||||
#define WX_MAX_RXBUFFER 16384 /* largest size for single descriptor */
|
||||
|
||||
#if MAX_SKB_FRAGS < 8
|
||||
#define WX_RX_BUFSZ ALIGN(WX_MAX_RXBUFFER / MAX_SKB_FRAGS, 1024)
|
||||
#else
|
||||
#define WX_RX_BUFSZ WX_RXBUFFER_2K
|
||||
#endif
|
||||
|
||||
#define WX_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define WX_MAX_DATA_PER_TXD BIT(14)
|
||||
@@ -643,6 +650,12 @@ enum wx_l2_ptypes {
|
||||
|
||||
#define WX_RXD_PKTTYPE(_rxd) \
|
||||
((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 9) & 0xFF)
|
||||
|
||||
#define WX_RXD_RSCCNT_MASK GENMASK(20, 17)
|
||||
#define WX_RXD_RSCCNT_SHIFT 17
|
||||
#define WX_RXD_NEXTP_MASK GENMASK(19, 4)
|
||||
#define WX_RXD_NEXTP_SHIFT 4
|
||||
|
||||
/*********************** Transmit Descriptor Config Masks ****************/
|
||||
#define WX_TXD_STAT_DD BIT(0) /* Descriptor Done */
|
||||
#define WX_TXD_DTYP_DATA 0 /* Adv Data Descriptor */
|
||||
@@ -1005,6 +1018,7 @@ struct wx_tx_buffer {
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
__be16 protocol;
|
||||
u32 tx_flags;
|
||||
u32 next_eop;
|
||||
};
|
||||
|
||||
struct wx_rx_buffer {
|
||||
@@ -1029,6 +1043,8 @@ struct wx_rx_queue_stats {
|
||||
u64 csum_good_cnt;
|
||||
u64 csum_err;
|
||||
u64 alloc_rx_buff_failed;
|
||||
u64 rsc_count;
|
||||
u64 rsc_flush;
|
||||
};
|
||||
|
||||
/* iterator for handling rings in ring container */
|
||||
@@ -1056,6 +1072,8 @@ struct wx_ring {
|
||||
};
|
||||
u8 __iomem *tail;
|
||||
dma_addr_t dma; /* phys. address of descriptor ring */
|
||||
dma_addr_t headwb_dma;
|
||||
u32 *headwb_mem;
|
||||
unsigned int size; /* length in bytes */
|
||||
|
||||
u16 count; /* amount of descriptors */
|
||||
@@ -1069,6 +1087,7 @@ struct wx_ring {
|
||||
*/
|
||||
u16 next_to_use;
|
||||
u16 next_to_clean;
|
||||
u16 rx_buf_len;
|
||||
union {
|
||||
u16 next_to_alloc;
|
||||
struct {
|
||||
@@ -1225,6 +1244,7 @@ enum wx_pf_flags {
|
||||
WX_FLAG_FDIR_HASH,
|
||||
WX_FLAG_FDIR_PERFECT,
|
||||
WX_FLAG_RSC_CAPABLE,
|
||||
WX_FLAG_RSC_ENABLED,
|
||||
WX_FLAG_RX_HWTSTAMP_ENABLED,
|
||||
WX_FLAG_RX_HWTSTAMP_IN_REGISTER,
|
||||
WX_FLAG_PTP_PPS_ENABLED,
|
||||
@@ -1232,6 +1252,8 @@ enum wx_pf_flags {
|
||||
WX_FLAG_NEED_SFP_RESET,
|
||||
WX_FLAG_NEED_UPDATE_LINK,
|
||||
WX_FLAG_NEED_DO_RESET,
|
||||
WX_FLAG_RX_MERGE_ENABLED,
|
||||
WX_FLAG_TXHEAD_WB_ENABLED,
|
||||
WX_PF_FLAGS_NBITS /* must be last */
|
||||
};
|
||||
|
||||
@@ -1338,6 +1360,8 @@ struct wx {
|
||||
u64 hw_csum_rx_good;
|
||||
u64 hw_csum_rx_error;
|
||||
u64 alloc_rx_buff_failed;
|
||||
u64 rsc_count;
|
||||
u64 rsc_flush;
|
||||
unsigned int num_vfs;
|
||||
struct vf_data_storage *vfinfo;
|
||||
struct vf_macvlans vf_mvs;
|
||||
@@ -1469,4 +1493,15 @@ static inline int wx_set_state_reset(struct wx *wx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int wx_rx_pg_order(struct wx_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring->rx_buf_len == WX_RXBUFFER_3K)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define wx_rx_pg_size(_ring) (PAGE_SIZE << wx_rx_pg_order(_ring))
|
||||
|
||||
#endif /* _WX_TYPE_H_ */
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#define WX_VXRXDCTL_BUFSZ(f) FIELD_PREP(GENMASK(11, 8), f)
|
||||
#define WX_VXRXDCTL_HDRSZ_MASK GENMASK(15, 12)
|
||||
#define WX_VXRXDCTL_HDRSZ(f) FIELD_PREP(GENMASK(15, 12), f)
|
||||
#define WX_VXRXDCTL_DESC_MERGE BIT(19)
|
||||
#define WX_VXRXDCTL_RSCMAX_MASK GENMASK(24, 23)
|
||||
#define WX_VXRXDCTL_RSCMAX(f) FIELD_PREP(GENMASK(24, 23), f)
|
||||
#define WX_VXRXDCTL_RSCEN BIT(29)
|
||||
@@ -91,6 +92,9 @@
|
||||
#define WX_VXTXDCTL_PTHRESH(f) FIELD_PREP(GENMASK(11, 8), f)
|
||||
#define WX_VXTXDCTL_WTHRESH(f) FIELD_PREP(GENMASK(22, 16), f)
|
||||
#define WX_VXTXDCTL_FLUSH BIT(26)
|
||||
#define WX_VXTXDCTL_HEAD_WB BIT(27)
|
||||
#define WX_VXTXD_HEAD_ADDRL(r) (0x3028 + (0x40 * (r)))
|
||||
#define WX_VXTXD_HEAD_ADDRH(r) (0x302C + (0x40 * (r)))
|
||||
|
||||
#define WX_PFLINK_STATUS(g) FIELD_GET(BIT(0), g)
|
||||
#define WX_PFLINK_SPEED(g) FIELD_GET(GENMASK(31, 1), g)
|
||||
|
||||
@@ -132,6 +132,15 @@ static void wx_configure_tx_ring_vf(struct wx *wx, struct wx_ring *ring)
|
||||
txdctl |= WX_VXTXDCTL_BUFLEN(wx_buf_len(ring->count));
|
||||
txdctl |= WX_VXTXDCTL_ENABLE;
|
||||
|
||||
if (ring->headwb_mem) {
|
||||
wr32(wx, WX_VXTXD_HEAD_ADDRL(reg_idx),
|
||||
ring->headwb_dma & DMA_BIT_MASK(32));
|
||||
wr32(wx, WX_VXTXD_HEAD_ADDRH(reg_idx),
|
||||
upper_32_bits(ring->headwb_dma));
|
||||
|
||||
txdctl |= WX_VXTXDCTL_HEAD_WB;
|
||||
}
|
||||
|
||||
/* reinitialize tx_buffer_info */
|
||||
memset(ring->tx_buffer_info, 0,
|
||||
sizeof(struct wx_tx_buffer) * ring->count);
|
||||
@@ -272,6 +281,9 @@ void wx_configure_rx_ring_vf(struct wx *wx, struct wx_ring *ring)
|
||||
rxdctl |= WX_VXRXDCTL_RSCMAX(0);
|
||||
rxdctl |= WX_VXRXDCTL_RSCEN;
|
||||
|
||||
if (test_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags))
|
||||
rxdctl |= WX_VXRXDCTL_DESC_MERGE;
|
||||
|
||||
wr32(wx, WX_VXRXDCTL(reg_idx), rxdctl);
|
||||
|
||||
/* pf/vf reuse */
|
||||
|
||||
@@ -398,6 +398,7 @@ static int txgbe_sw_init(struct wx *wx)
|
||||
wx->configure_fdir = txgbe_configure_fdir;
|
||||
|
||||
set_bit(WX_FLAG_RSC_CAPABLE, wx->flags);
|
||||
set_bit(WX_FLAG_RSC_ENABLED, wx->flags);
|
||||
set_bit(WX_FLAG_MULTI_64_FUNC, wx->flags);
|
||||
|
||||
/* enable itr by default in dynamic mode */
|
||||
@@ -423,6 +424,8 @@ static int txgbe_sw_init(struct wx *wx)
|
||||
break;
|
||||
case wx_mac_aml:
|
||||
case wx_mac_aml40:
|
||||
set_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags);
|
||||
set_bit(WX_FLAG_TXHEAD_WB_ENABLED, wx->flags);
|
||||
set_bit(WX_FLAG_SWFW_RING, wx->flags);
|
||||
wx->swfw_index = 0;
|
||||
break;
|
||||
@@ -801,6 +804,8 @@ static int txgbe_probe(struct pci_dev *pdev,
|
||||
netdev->features |= NETIF_F_HIGHDMA;
|
||||
netdev->hw_features |= NETIF_F_GRO;
|
||||
netdev->features |= NETIF_F_GRO;
|
||||
netdev->hw_features |= NETIF_F_LRO;
|
||||
netdev->features |= NETIF_F_LRO;
|
||||
netdev->features |= NETIF_F_RX_UDP_TUNNEL_PORT;
|
||||
|
||||
netdev->priv_flags |= IFF_UNICAST_FLT;
|
||||
|
||||
@@ -157,6 +157,18 @@ static int txgbevf_sw_init(struct wx *wx)
|
||||
|
||||
wx->set_num_queues = txgbevf_set_num_queues;
|
||||
|
||||
switch (wx->mac.type) {
|
||||
case wx_mac_sp:
|
||||
break;
|
||||
case wx_mac_aml:
|
||||
case wx_mac_aml40:
|
||||
set_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags);
|
||||
set_bit(WX_FLAG_TXHEAD_WB_ENABLED, wx->flags);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_reset_hw:
|
||||
kfree(wx->vfinfo);
|
||||
|
||||
Reference in New Issue
Block a user