162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/**************************************************************************** 362306a36Sopenharmony_ci * Driver for Solarflare network controllers and boards 462306a36Sopenharmony_ci * Copyright 2005-2006 Fen Systems Ltd. 562306a36Sopenharmony_ci * Copyright 2005-2013 Solarflare Communications Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/pci.h> 962306a36Sopenharmony_ci#include <linux/tcp.h> 1062306a36Sopenharmony_ci#include <linux/ip.h> 1162306a36Sopenharmony_ci#include <linux/in.h> 1262306a36Sopenharmony_ci#include <linux/ipv6.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <net/ipv6.h> 1562306a36Sopenharmony_ci#include <linux/if_ether.h> 1662306a36Sopenharmony_ci#include <linux/highmem.h> 1762306a36Sopenharmony_ci#include <linux/cache.h> 1862306a36Sopenharmony_ci#include "net_driver.h" 1962306a36Sopenharmony_ci#include "efx.h" 2062306a36Sopenharmony_ci#include "io.h" 2162306a36Sopenharmony_ci#include "nic.h" 2262306a36Sopenharmony_ci#include "tx.h" 2362306a36Sopenharmony_ci#include "workarounds.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic inline u8 *ef4_tx_get_copy_buffer(struct ef4_tx_queue *tx_queue, 2662306a36Sopenharmony_ci struct ef4_tx_buffer *buffer) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci unsigned int index = ef4_tx_queue_get_insert_index(tx_queue); 2962306a36Sopenharmony_ci struct ef4_buffer *page_buf = 3062306a36Sopenharmony_ci &tx_queue->cb_page[index >> (PAGE_SHIFT - EF4_TX_CB_ORDER)]; 3162306a36Sopenharmony_ci unsigned int offset = 3262306a36Sopenharmony_ci ((index << EF4_TX_CB_ORDER) + NET_IP_ALIGN) & (PAGE_SIZE - 1); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci if (unlikely(!page_buf->addr) && 3562306a36Sopenharmony_ci ef4_nic_alloc_buffer(tx_queue->efx, page_buf, PAGE_SIZE, 3662306a36Sopenharmony_ci GFP_ATOMIC)) 3762306a36Sopenharmony_ci return NULL; 3862306a36Sopenharmony_ci buffer->dma_addr = page_buf->dma_addr + offset; 3962306a36Sopenharmony_ci buffer->unmap_len = 0; 4062306a36Sopenharmony_ci return (u8 *)page_buf->addr + offset; 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciu8 *ef4_tx_get_copy_buffer_limited(struct ef4_tx_queue *tx_queue, 4462306a36Sopenharmony_ci struct ef4_tx_buffer *buffer, size_t len) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci if (len > EF4_TX_CB_SIZE) 4762306a36Sopenharmony_ci return NULL; 4862306a36Sopenharmony_ci return ef4_tx_get_copy_buffer(tx_queue, buffer); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic void ef4_dequeue_buffer(struct ef4_tx_queue *tx_queue, 5262306a36Sopenharmony_ci struct ef4_tx_buffer *buffer, 5362306a36Sopenharmony_ci unsigned int *pkts_compl, 5462306a36Sopenharmony_ci unsigned int *bytes_compl) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci if (buffer->unmap_len) { 5762306a36Sopenharmony_ci struct device *dma_dev = &tx_queue->efx->pci_dev->dev; 5862306a36Sopenharmony_ci dma_addr_t unmap_addr = buffer->dma_addr - buffer->dma_offset; 5962306a36Sopenharmony_ci if (buffer->flags & EF4_TX_BUF_MAP_SINGLE) 6062306a36Sopenharmony_ci dma_unmap_single(dma_dev, unmap_addr, buffer->unmap_len, 6162306a36Sopenharmony_ci DMA_TO_DEVICE); 6262306a36Sopenharmony_ci else 6362306a36Sopenharmony_ci dma_unmap_page(dma_dev, unmap_addr, buffer->unmap_len, 6462306a36Sopenharmony_ci DMA_TO_DEVICE); 6562306a36Sopenharmony_ci buffer->unmap_len = 0; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if (buffer->flags & EF4_TX_BUF_SKB) { 6962306a36Sopenharmony_ci (*pkts_compl)++; 7062306a36Sopenharmony_ci (*bytes_compl) += buffer->skb->len; 7162306a36Sopenharmony_ci dev_consume_skb_any((struct sk_buff *)buffer->skb); 7262306a36Sopenharmony_ci netif_vdbg(tx_queue->efx, tx_done, tx_queue->efx->net_dev, 7362306a36Sopenharmony_ci "TX queue %d transmission id %x complete\n", 7462306a36Sopenharmony_ci tx_queue->queue, tx_queue->read_count); 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci buffer->len = 0; 7862306a36Sopenharmony_ci buffer->flags = 0; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciunsigned int ef4_tx_max_skb_descs(struct ef4_nic *efx) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci /* This is probably too much since we don't have any TSO support; 8462306a36Sopenharmony_ci * it's a left-over from when we had Software TSO. But it's safer 8562306a36Sopenharmony_ci * to leave it as-is than try to determine a new bound. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci /* Header and payload descriptor for each output segment, plus 8862306a36Sopenharmony_ci * one for every input fragment boundary within a segment 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_ci unsigned int max_descs = EF4_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* Possibly one more per segment for the alignment workaround, 9362306a36Sopenharmony_ci * or for option descriptors 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci if (EF4_WORKAROUND_5391(efx)) 9662306a36Sopenharmony_ci max_descs += EF4_TSO_MAX_SEGS; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci /* Possibly more for PCIe page boundaries within input fragments */ 9962306a36Sopenharmony_ci if (PAGE_SIZE > EF4_PAGE_SIZE) 10062306a36Sopenharmony_ci max_descs += max_t(unsigned int, MAX_SKB_FRAGS, 10162306a36Sopenharmony_ci DIV_ROUND_UP(GSO_LEGACY_MAX_SIZE, 10262306a36Sopenharmony_ci EF4_PAGE_SIZE)); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return max_descs; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void ef4_tx_maybe_stop_queue(struct ef4_tx_queue *txq1) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci /* We need to consider both queues that the net core sees as one */ 11062306a36Sopenharmony_ci struct ef4_tx_queue *txq2 = ef4_tx_queue_partner(txq1); 11162306a36Sopenharmony_ci struct ef4_nic *efx = txq1->efx; 11262306a36Sopenharmony_ci unsigned int fill_level; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci fill_level = max(txq1->insert_count - txq1->old_read_count, 11562306a36Sopenharmony_ci txq2->insert_count - txq2->old_read_count); 11662306a36Sopenharmony_ci if (likely(fill_level < efx->txq_stop_thresh)) 11762306a36Sopenharmony_ci return; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* We used the stale old_read_count above, which gives us a 12062306a36Sopenharmony_ci * pessimistic estimate of the fill level (which may even 12162306a36Sopenharmony_ci * validly be >= efx->txq_entries). Now try again using 12262306a36Sopenharmony_ci * read_count (more likely to be a cache miss). 12362306a36Sopenharmony_ci * 12462306a36Sopenharmony_ci * If we read read_count and then conditionally stop the 12562306a36Sopenharmony_ci * queue, it is possible for the completion path to race with 12662306a36Sopenharmony_ci * us and complete all outstanding descriptors in the middle, 12762306a36Sopenharmony_ci * after which there will be no more completions to wake it. 12862306a36Sopenharmony_ci * Therefore we stop the queue first, then read read_count 12962306a36Sopenharmony_ci * (with a memory barrier to ensure the ordering), then 13062306a36Sopenharmony_ci * restart the queue if the fill level turns out to be low 13162306a36Sopenharmony_ci * enough. 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_ci netif_tx_stop_queue(txq1->core_txq); 13462306a36Sopenharmony_ci smp_mb(); 13562306a36Sopenharmony_ci txq1->old_read_count = READ_ONCE(txq1->read_count); 13662306a36Sopenharmony_ci txq2->old_read_count = READ_ONCE(txq2->read_count); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci fill_level = max(txq1->insert_count - txq1->old_read_count, 13962306a36Sopenharmony_ci txq2->insert_count - txq2->old_read_count); 14062306a36Sopenharmony_ci EF4_BUG_ON_PARANOID(fill_level >= efx->txq_entries); 14162306a36Sopenharmony_ci if (likely(fill_level < efx->txq_stop_thresh)) { 14262306a36Sopenharmony_ci smp_mb(); 14362306a36Sopenharmony_ci if (likely(!efx->loopback_selftest)) 14462306a36Sopenharmony_ci netif_tx_start_queue(txq1->core_txq); 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic int ef4_enqueue_skb_copy(struct ef4_tx_queue *tx_queue, 14962306a36Sopenharmony_ci struct sk_buff *skb) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci unsigned int min_len = tx_queue->tx_min_size; 15262306a36Sopenharmony_ci unsigned int copy_len = skb->len; 15362306a36Sopenharmony_ci struct ef4_tx_buffer *buffer; 15462306a36Sopenharmony_ci u8 *copy_buffer; 15562306a36Sopenharmony_ci int rc; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci EF4_BUG_ON_PARANOID(copy_len > EF4_TX_CB_SIZE); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci buffer = ef4_tx_queue_get_insert_buffer(tx_queue); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci copy_buffer = ef4_tx_get_copy_buffer(tx_queue, buffer); 16262306a36Sopenharmony_ci if (unlikely(!copy_buffer)) 16362306a36Sopenharmony_ci return -ENOMEM; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci rc = skb_copy_bits(skb, 0, copy_buffer, copy_len); 16662306a36Sopenharmony_ci EF4_WARN_ON_PARANOID(rc); 16762306a36Sopenharmony_ci if (unlikely(copy_len < min_len)) { 16862306a36Sopenharmony_ci memset(copy_buffer + copy_len, 0, min_len - copy_len); 16962306a36Sopenharmony_ci buffer->len = min_len; 17062306a36Sopenharmony_ci } else { 17162306a36Sopenharmony_ci buffer->len = copy_len; 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci buffer->skb = skb; 17562306a36Sopenharmony_ci buffer->flags = EF4_TX_BUF_SKB; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci ++tx_queue->insert_count; 17862306a36Sopenharmony_ci return rc; 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic struct ef4_tx_buffer *ef4_tx_map_chunk(struct ef4_tx_queue *tx_queue, 18262306a36Sopenharmony_ci dma_addr_t dma_addr, 18362306a36Sopenharmony_ci size_t len) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci const struct ef4_nic_type *nic_type = tx_queue->efx->type; 18662306a36Sopenharmony_ci struct ef4_tx_buffer *buffer; 18762306a36Sopenharmony_ci unsigned int dma_len; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* Map the fragment taking account of NIC-dependent DMA limits. */ 19062306a36Sopenharmony_ci do { 19162306a36Sopenharmony_ci buffer = ef4_tx_queue_get_insert_buffer(tx_queue); 19262306a36Sopenharmony_ci dma_len = nic_type->tx_limit_len(tx_queue, dma_addr, len); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci buffer->len = dma_len; 19562306a36Sopenharmony_ci buffer->dma_addr = dma_addr; 19662306a36Sopenharmony_ci buffer->flags = EF4_TX_BUF_CONT; 19762306a36Sopenharmony_ci len -= dma_len; 19862306a36Sopenharmony_ci dma_addr += dma_len; 19962306a36Sopenharmony_ci ++tx_queue->insert_count; 20062306a36Sopenharmony_ci } while (len); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return buffer; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci/* Map all data from an SKB for DMA and create descriptors on the queue. 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_cistatic int ef4_tx_map_data(struct ef4_tx_queue *tx_queue, struct sk_buff *skb) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci struct ef4_nic *efx = tx_queue->efx; 21062306a36Sopenharmony_ci struct device *dma_dev = &efx->pci_dev->dev; 21162306a36Sopenharmony_ci unsigned int frag_index, nr_frags; 21262306a36Sopenharmony_ci dma_addr_t dma_addr, unmap_addr; 21362306a36Sopenharmony_ci unsigned short dma_flags; 21462306a36Sopenharmony_ci size_t len, unmap_len; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci nr_frags = skb_shinfo(skb)->nr_frags; 21762306a36Sopenharmony_ci frag_index = 0; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci /* Map header data. */ 22062306a36Sopenharmony_ci len = skb_headlen(skb); 22162306a36Sopenharmony_ci dma_addr = dma_map_single(dma_dev, skb->data, len, DMA_TO_DEVICE); 22262306a36Sopenharmony_ci dma_flags = EF4_TX_BUF_MAP_SINGLE; 22362306a36Sopenharmony_ci unmap_len = len; 22462306a36Sopenharmony_ci unmap_addr = dma_addr; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (unlikely(dma_mapping_error(dma_dev, dma_addr))) 22762306a36Sopenharmony_ci return -EIO; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Add descriptors for each fragment. */ 23062306a36Sopenharmony_ci do { 23162306a36Sopenharmony_ci struct ef4_tx_buffer *buffer; 23262306a36Sopenharmony_ci skb_frag_t *fragment; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci buffer = ef4_tx_map_chunk(tx_queue, dma_addr, len); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* The final descriptor for a fragment is responsible for 23762306a36Sopenharmony_ci * unmapping the whole fragment. 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_ci buffer->flags = EF4_TX_BUF_CONT | dma_flags; 24062306a36Sopenharmony_ci buffer->unmap_len = unmap_len; 24162306a36Sopenharmony_ci buffer->dma_offset = buffer->dma_addr - unmap_addr; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (frag_index >= nr_frags) { 24462306a36Sopenharmony_ci /* Store SKB details with the final buffer for 24562306a36Sopenharmony_ci * the completion. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci buffer->skb = skb; 24862306a36Sopenharmony_ci buffer->flags = EF4_TX_BUF_SKB | dma_flags; 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* Move on to the next fragment. */ 25362306a36Sopenharmony_ci fragment = &skb_shinfo(skb)->frags[frag_index++]; 25462306a36Sopenharmony_ci len = skb_frag_size(fragment); 25562306a36Sopenharmony_ci dma_addr = skb_frag_dma_map(dma_dev, fragment, 25662306a36Sopenharmony_ci 0, len, DMA_TO_DEVICE); 25762306a36Sopenharmony_ci dma_flags = 0; 25862306a36Sopenharmony_ci unmap_len = len; 25962306a36Sopenharmony_ci unmap_addr = dma_addr; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (unlikely(dma_mapping_error(dma_dev, dma_addr))) 26262306a36Sopenharmony_ci return -EIO; 26362306a36Sopenharmony_ci } while (1); 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci/* Remove buffers put into a tx_queue. None of the buffers must have 26762306a36Sopenharmony_ci * an skb attached. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_cistatic void ef4_enqueue_unwind(struct ef4_tx_queue *tx_queue) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct ef4_tx_buffer *buffer; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* Work backwards until we hit the original insert pointer value */ 27462306a36Sopenharmony_ci while (tx_queue->insert_count != tx_queue->write_count) { 27562306a36Sopenharmony_ci --tx_queue->insert_count; 27662306a36Sopenharmony_ci buffer = __ef4_tx_queue_get_insert_buffer(tx_queue); 27762306a36Sopenharmony_ci ef4_dequeue_buffer(tx_queue, buffer, NULL, NULL); 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/* 28262306a36Sopenharmony_ci * Add a socket buffer to a TX queue 28362306a36Sopenharmony_ci * 28462306a36Sopenharmony_ci * This maps all fragments of a socket buffer for DMA and adds them to 28562306a36Sopenharmony_ci * the TX queue. The queue's insert pointer will be incremented by 28662306a36Sopenharmony_ci * the number of fragments in the socket buffer. 28762306a36Sopenharmony_ci * 28862306a36Sopenharmony_ci * If any DMA mapping fails, any mapped fragments will be unmapped, 28962306a36Sopenharmony_ci * the queue's insert pointer will be restored to its original value. 29062306a36Sopenharmony_ci * 29162306a36Sopenharmony_ci * This function is split out from ef4_hard_start_xmit to allow the 29262306a36Sopenharmony_ci * loopback test to direct packets via specific TX queues. 29362306a36Sopenharmony_ci * 29462306a36Sopenharmony_ci * Returns NETDEV_TX_OK. 29562306a36Sopenharmony_ci * You must hold netif_tx_lock() to call this function. 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_cinetdev_tx_t ef4_enqueue_skb(struct ef4_tx_queue *tx_queue, struct sk_buff *skb) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci bool data_mapped = false; 30062306a36Sopenharmony_ci unsigned int skb_len; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci skb_len = skb->len; 30362306a36Sopenharmony_ci EF4_WARN_ON_PARANOID(skb_is_gso(skb)); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci if (skb_len < tx_queue->tx_min_size || 30662306a36Sopenharmony_ci (skb->data_len && skb_len <= EF4_TX_CB_SIZE)) { 30762306a36Sopenharmony_ci /* Pad short packets or coalesce short fragmented packets. */ 30862306a36Sopenharmony_ci if (ef4_enqueue_skb_copy(tx_queue, skb)) 30962306a36Sopenharmony_ci goto err; 31062306a36Sopenharmony_ci tx_queue->cb_packets++; 31162306a36Sopenharmony_ci data_mapped = true; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* Map for DMA and create descriptors if we haven't done so already. */ 31562306a36Sopenharmony_ci if (!data_mapped && (ef4_tx_map_data(tx_queue, skb))) 31662306a36Sopenharmony_ci goto err; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci /* Update BQL */ 31962306a36Sopenharmony_ci netdev_tx_sent_queue(tx_queue->core_txq, skb_len); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* Pass off to hardware */ 32262306a36Sopenharmony_ci if (!netdev_xmit_more() || netif_xmit_stopped(tx_queue->core_txq)) { 32362306a36Sopenharmony_ci struct ef4_tx_queue *txq2 = ef4_tx_queue_partner(tx_queue); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* There could be packets left on the partner queue if those 32662306a36Sopenharmony_ci * SKBs had skb->xmit_more set. If we do not push those they 32762306a36Sopenharmony_ci * could be left for a long time and cause a netdev watchdog. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci if (txq2->xmit_more_available) 33062306a36Sopenharmony_ci ef4_nic_push_buffers(txq2); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci ef4_nic_push_buffers(tx_queue); 33362306a36Sopenharmony_ci } else { 33462306a36Sopenharmony_ci tx_queue->xmit_more_available = netdev_xmit_more(); 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci tx_queue->tx_packets++; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci ef4_tx_maybe_stop_queue(tx_queue); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci return NETDEV_TX_OK; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cierr: 34562306a36Sopenharmony_ci ef4_enqueue_unwind(tx_queue); 34662306a36Sopenharmony_ci dev_kfree_skb_any(skb); 34762306a36Sopenharmony_ci return NETDEV_TX_OK; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci/* Remove packets from the TX queue 35162306a36Sopenharmony_ci * 35262306a36Sopenharmony_ci * This removes packets from the TX queue, up to and including the 35362306a36Sopenharmony_ci * specified index. 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_cistatic void ef4_dequeue_buffers(struct ef4_tx_queue *tx_queue, 35662306a36Sopenharmony_ci unsigned int index, 35762306a36Sopenharmony_ci unsigned int *pkts_compl, 35862306a36Sopenharmony_ci unsigned int *bytes_compl) 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci struct ef4_nic *efx = tx_queue->efx; 36162306a36Sopenharmony_ci unsigned int stop_index, read_ptr; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci stop_index = (index + 1) & tx_queue->ptr_mask; 36462306a36Sopenharmony_ci read_ptr = tx_queue->read_count & tx_queue->ptr_mask; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci while (read_ptr != stop_index) { 36762306a36Sopenharmony_ci struct ef4_tx_buffer *buffer = &tx_queue->buffer[read_ptr]; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (!(buffer->flags & EF4_TX_BUF_OPTION) && 37062306a36Sopenharmony_ci unlikely(buffer->len == 0)) { 37162306a36Sopenharmony_ci netif_err(efx, tx_err, efx->net_dev, 37262306a36Sopenharmony_ci "TX queue %d spurious TX completion id %x\n", 37362306a36Sopenharmony_ci tx_queue->queue, read_ptr); 37462306a36Sopenharmony_ci ef4_schedule_reset(efx, RESET_TYPE_TX_SKIP); 37562306a36Sopenharmony_ci return; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci ef4_dequeue_buffer(tx_queue, buffer, pkts_compl, bytes_compl); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci ++tx_queue->read_count; 38162306a36Sopenharmony_ci read_ptr = tx_queue->read_count & tx_queue->ptr_mask; 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/* Initiate a packet transmission. We use one channel per CPU 38662306a36Sopenharmony_ci * (sharing when we have more CPUs than channels). On Falcon, the TX 38762306a36Sopenharmony_ci * completion events will be directed back to the CPU that transmitted 38862306a36Sopenharmony_ci * the packet, which should be cache-efficient. 38962306a36Sopenharmony_ci * 39062306a36Sopenharmony_ci * Context: non-blocking. 39162306a36Sopenharmony_ci * Note that returning anything other than NETDEV_TX_OK will cause the 39262306a36Sopenharmony_ci * OS to free the skb. 39362306a36Sopenharmony_ci */ 39462306a36Sopenharmony_cinetdev_tx_t ef4_hard_start_xmit(struct sk_buff *skb, 39562306a36Sopenharmony_ci struct net_device *net_dev) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci struct ef4_nic *efx = netdev_priv(net_dev); 39862306a36Sopenharmony_ci struct ef4_tx_queue *tx_queue; 39962306a36Sopenharmony_ci unsigned index, type; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci EF4_WARN_ON_PARANOID(!netif_device_present(net_dev)); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci index = skb_get_queue_mapping(skb); 40462306a36Sopenharmony_ci type = skb->ip_summed == CHECKSUM_PARTIAL ? EF4_TXQ_TYPE_OFFLOAD : 0; 40562306a36Sopenharmony_ci if (index >= efx->n_tx_channels) { 40662306a36Sopenharmony_ci index -= efx->n_tx_channels; 40762306a36Sopenharmony_ci type |= EF4_TXQ_TYPE_HIGHPRI; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci tx_queue = ef4_get_tx_queue(efx, index, type); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci return ef4_enqueue_skb(tx_queue, skb); 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_civoid ef4_init_tx_queue_core_txq(struct ef4_tx_queue *tx_queue) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci struct ef4_nic *efx = tx_queue->efx; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /* Must be inverse of queue lookup in ef4_hard_start_xmit() */ 41962306a36Sopenharmony_ci tx_queue->core_txq = 42062306a36Sopenharmony_ci netdev_get_tx_queue(efx->net_dev, 42162306a36Sopenharmony_ci tx_queue->queue / EF4_TXQ_TYPES + 42262306a36Sopenharmony_ci ((tx_queue->queue & EF4_TXQ_TYPE_HIGHPRI) ? 42362306a36Sopenharmony_ci efx->n_tx_channels : 0)); 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ciint ef4_setup_tc(struct net_device *net_dev, enum tc_setup_type type, 42762306a36Sopenharmony_ci void *type_data) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci struct ef4_nic *efx = netdev_priv(net_dev); 43062306a36Sopenharmony_ci struct tc_mqprio_qopt *mqprio = type_data; 43162306a36Sopenharmony_ci struct ef4_channel *channel; 43262306a36Sopenharmony_ci struct ef4_tx_queue *tx_queue; 43362306a36Sopenharmony_ci unsigned tc, num_tc; 43462306a36Sopenharmony_ci int rc; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci if (type != TC_SETUP_QDISC_MQPRIO) 43762306a36Sopenharmony_ci return -EOPNOTSUPP; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci num_tc = mqprio->num_tc; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if (ef4_nic_rev(efx) < EF4_REV_FALCON_B0 || num_tc > EF4_MAX_TX_TC) 44262306a36Sopenharmony_ci return -EINVAL; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (num_tc == net_dev->num_tc) 44762306a36Sopenharmony_ci return 0; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci for (tc = 0; tc < num_tc; tc++) { 45062306a36Sopenharmony_ci net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels; 45162306a36Sopenharmony_ci net_dev->tc_to_txq[tc].count = efx->n_tx_channels; 45262306a36Sopenharmony_ci } 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (num_tc > net_dev->num_tc) { 45562306a36Sopenharmony_ci /* Initialise high-priority queues as necessary */ 45662306a36Sopenharmony_ci ef4_for_each_channel(channel, efx) { 45762306a36Sopenharmony_ci ef4_for_each_possible_channel_tx_queue(tx_queue, 45862306a36Sopenharmony_ci channel) { 45962306a36Sopenharmony_ci if (!(tx_queue->queue & EF4_TXQ_TYPE_HIGHPRI)) 46062306a36Sopenharmony_ci continue; 46162306a36Sopenharmony_ci if (!tx_queue->buffer) { 46262306a36Sopenharmony_ci rc = ef4_probe_tx_queue(tx_queue); 46362306a36Sopenharmony_ci if (rc) 46462306a36Sopenharmony_ci return rc; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci if (!tx_queue->initialised) 46762306a36Sopenharmony_ci ef4_init_tx_queue(tx_queue); 46862306a36Sopenharmony_ci ef4_init_tx_queue_core_txq(tx_queue); 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci } else { 47262306a36Sopenharmony_ci /* Reduce number of classes before number of queues */ 47362306a36Sopenharmony_ci net_dev->num_tc = num_tc; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci rc = netif_set_real_num_tx_queues(net_dev, 47762306a36Sopenharmony_ci max_t(int, num_tc, 1) * 47862306a36Sopenharmony_ci efx->n_tx_channels); 47962306a36Sopenharmony_ci if (rc) 48062306a36Sopenharmony_ci return rc; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* Do not destroy high-priority queues when they become 48362306a36Sopenharmony_ci * unused. We would have to flush them first, and it is 48462306a36Sopenharmony_ci * fairly difficult to flush a subset of TX queues. Leave 48562306a36Sopenharmony_ci * it to ef4_fini_channels(). 48662306a36Sopenharmony_ci */ 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci net_dev->num_tc = num_tc; 48962306a36Sopenharmony_ci return 0; 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_civoid ef4_xmit_done(struct ef4_tx_queue *tx_queue, unsigned int index) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci unsigned fill_level; 49562306a36Sopenharmony_ci struct ef4_nic *efx = tx_queue->efx; 49662306a36Sopenharmony_ci struct ef4_tx_queue *txq2; 49762306a36Sopenharmony_ci unsigned int pkts_compl = 0, bytes_compl = 0; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci EF4_BUG_ON_PARANOID(index > tx_queue->ptr_mask); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci ef4_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl); 50262306a36Sopenharmony_ci tx_queue->pkts_compl += pkts_compl; 50362306a36Sopenharmony_ci tx_queue->bytes_compl += bytes_compl; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci if (pkts_compl > 1) 50662306a36Sopenharmony_ci ++tx_queue->merge_events; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* See if we need to restart the netif queue. This memory 50962306a36Sopenharmony_ci * barrier ensures that we write read_count (inside 51062306a36Sopenharmony_ci * ef4_dequeue_buffers()) before reading the queue status. 51162306a36Sopenharmony_ci */ 51262306a36Sopenharmony_ci smp_mb(); 51362306a36Sopenharmony_ci if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) && 51462306a36Sopenharmony_ci likely(efx->port_enabled) && 51562306a36Sopenharmony_ci likely(netif_device_present(efx->net_dev))) { 51662306a36Sopenharmony_ci txq2 = ef4_tx_queue_partner(tx_queue); 51762306a36Sopenharmony_ci fill_level = max(tx_queue->insert_count - tx_queue->read_count, 51862306a36Sopenharmony_ci txq2->insert_count - txq2->read_count); 51962306a36Sopenharmony_ci if (fill_level <= efx->txq_wake_thresh) 52062306a36Sopenharmony_ci netif_tx_wake_queue(tx_queue->core_txq); 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci /* Check whether the hardware queue is now empty */ 52462306a36Sopenharmony_ci if ((int)(tx_queue->read_count - tx_queue->old_write_count) >= 0) { 52562306a36Sopenharmony_ci tx_queue->old_write_count = READ_ONCE(tx_queue->write_count); 52662306a36Sopenharmony_ci if (tx_queue->read_count == tx_queue->old_write_count) { 52762306a36Sopenharmony_ci smp_mb(); 52862306a36Sopenharmony_ci tx_queue->empty_read_count = 52962306a36Sopenharmony_ci tx_queue->read_count | EF4_EMPTY_COUNT_VALID; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci} 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_cistatic unsigned int ef4_tx_cb_page_count(struct ef4_tx_queue *tx_queue) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci return DIV_ROUND_UP(tx_queue->ptr_mask + 1, PAGE_SIZE >> EF4_TX_CB_ORDER); 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ciint ef4_probe_tx_queue(struct ef4_tx_queue *tx_queue) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci struct ef4_nic *efx = tx_queue->efx; 54262306a36Sopenharmony_ci unsigned int entries; 54362306a36Sopenharmony_ci int rc; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci /* Create the smallest power-of-two aligned ring */ 54662306a36Sopenharmony_ci entries = max(roundup_pow_of_two(efx->txq_entries), EF4_MIN_DMAQ_SIZE); 54762306a36Sopenharmony_ci EF4_BUG_ON_PARANOID(entries > EF4_MAX_DMAQ_SIZE); 54862306a36Sopenharmony_ci tx_queue->ptr_mask = entries - 1; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci netif_dbg(efx, probe, efx->net_dev, 55162306a36Sopenharmony_ci "creating TX queue %d size %#x mask %#x\n", 55262306a36Sopenharmony_ci tx_queue->queue, efx->txq_entries, tx_queue->ptr_mask); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci /* Allocate software ring */ 55562306a36Sopenharmony_ci tx_queue->buffer = kcalloc(entries, sizeof(*tx_queue->buffer), 55662306a36Sopenharmony_ci GFP_KERNEL); 55762306a36Sopenharmony_ci if (!tx_queue->buffer) 55862306a36Sopenharmony_ci return -ENOMEM; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci tx_queue->cb_page = kcalloc(ef4_tx_cb_page_count(tx_queue), 56162306a36Sopenharmony_ci sizeof(tx_queue->cb_page[0]), GFP_KERNEL); 56262306a36Sopenharmony_ci if (!tx_queue->cb_page) { 56362306a36Sopenharmony_ci rc = -ENOMEM; 56462306a36Sopenharmony_ci goto fail1; 56562306a36Sopenharmony_ci } 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci /* Allocate hardware ring */ 56862306a36Sopenharmony_ci rc = ef4_nic_probe_tx(tx_queue); 56962306a36Sopenharmony_ci if (rc) 57062306a36Sopenharmony_ci goto fail2; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci return 0; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cifail2: 57562306a36Sopenharmony_ci kfree(tx_queue->cb_page); 57662306a36Sopenharmony_ci tx_queue->cb_page = NULL; 57762306a36Sopenharmony_cifail1: 57862306a36Sopenharmony_ci kfree(tx_queue->buffer); 57962306a36Sopenharmony_ci tx_queue->buffer = NULL; 58062306a36Sopenharmony_ci return rc; 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_civoid ef4_init_tx_queue(struct ef4_tx_queue *tx_queue) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci struct ef4_nic *efx = tx_queue->efx; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, 58862306a36Sopenharmony_ci "initialising TX queue %d\n", tx_queue->queue); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci tx_queue->insert_count = 0; 59162306a36Sopenharmony_ci tx_queue->write_count = 0; 59262306a36Sopenharmony_ci tx_queue->old_write_count = 0; 59362306a36Sopenharmony_ci tx_queue->read_count = 0; 59462306a36Sopenharmony_ci tx_queue->old_read_count = 0; 59562306a36Sopenharmony_ci tx_queue->empty_read_count = 0 | EF4_EMPTY_COUNT_VALID; 59662306a36Sopenharmony_ci tx_queue->xmit_more_available = false; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* Some older hardware requires Tx writes larger than 32. */ 59962306a36Sopenharmony_ci tx_queue->tx_min_size = EF4_WORKAROUND_15592(efx) ? 33 : 0; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci /* Set up TX descriptor ring */ 60262306a36Sopenharmony_ci ef4_nic_init_tx(tx_queue); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci tx_queue->initialised = true; 60562306a36Sopenharmony_ci} 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_civoid ef4_fini_tx_queue(struct ef4_tx_queue *tx_queue) 60862306a36Sopenharmony_ci{ 60962306a36Sopenharmony_ci struct ef4_tx_buffer *buffer; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev, 61262306a36Sopenharmony_ci "shutting down TX queue %d\n", tx_queue->queue); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (!tx_queue->buffer) 61562306a36Sopenharmony_ci return; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci /* Free any buffers left in the ring */ 61862306a36Sopenharmony_ci while (tx_queue->read_count != tx_queue->write_count) { 61962306a36Sopenharmony_ci unsigned int pkts_compl = 0, bytes_compl = 0; 62062306a36Sopenharmony_ci buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask]; 62162306a36Sopenharmony_ci ef4_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci ++tx_queue->read_count; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci tx_queue->xmit_more_available = false; 62662306a36Sopenharmony_ci netdev_tx_reset_queue(tx_queue->core_txq); 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_civoid ef4_remove_tx_queue(struct ef4_tx_queue *tx_queue) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci int i; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci if (!tx_queue->buffer) 63462306a36Sopenharmony_ci return; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev, 63762306a36Sopenharmony_ci "destroying TX queue %d\n", tx_queue->queue); 63862306a36Sopenharmony_ci ef4_nic_remove_tx(tx_queue); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (tx_queue->cb_page) { 64162306a36Sopenharmony_ci for (i = 0; i < ef4_tx_cb_page_count(tx_queue); i++) 64262306a36Sopenharmony_ci ef4_nic_free_buffer(tx_queue->efx, 64362306a36Sopenharmony_ci &tx_queue->cb_page[i]); 64462306a36Sopenharmony_ci kfree(tx_queue->cb_page); 64562306a36Sopenharmony_ci tx_queue->cb_page = NULL; 64662306a36Sopenharmony_ci } 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci kfree(tx_queue->buffer); 64962306a36Sopenharmony_ci tx_queue->buffer = NULL; 65062306a36Sopenharmony_ci} 651