18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/**************************************************************************** 38c2ecf20Sopenharmony_ci * Driver for Solarflare network controllers and boards 48c2ecf20Sopenharmony_ci * Copyright 2018 Solarflare Communications Inc. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it 78c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License version 2 as published 88c2ecf20Sopenharmony_ci * by the Free Software Foundation, incorporated herein by reference. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "net_driver.h" 128c2ecf20Sopenharmony_ci#include "efx.h" 138c2ecf20Sopenharmony_ci#include "nic_common.h" 148c2ecf20Sopenharmony_ci#include "tx_common.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci return DIV_ROUND_UP(tx_queue->ptr_mask + 1, 198c2ecf20Sopenharmony_ci PAGE_SIZE >> EFX_TX_CB_ORDER); 208c2ecf20Sopenharmony_ci} 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ciint efx_probe_tx_queue(struct efx_tx_queue *tx_queue) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci struct efx_nic *efx = tx_queue->efx; 258c2ecf20Sopenharmony_ci unsigned int entries; 268c2ecf20Sopenharmony_ci int rc; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci /* Create the smallest power-of-two aligned ring */ 298c2ecf20Sopenharmony_ci entries = max(roundup_pow_of_two(efx->txq_entries), EFX_MIN_DMAQ_SIZE); 308c2ecf20Sopenharmony_ci EFX_WARN_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE); 318c2ecf20Sopenharmony_ci tx_queue->ptr_mask = entries - 1; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci netif_dbg(efx, probe, efx->net_dev, 348c2ecf20Sopenharmony_ci "creating TX queue %d size %#x mask %#x\n", 358c2ecf20Sopenharmony_ci tx_queue->queue, efx->txq_entries, tx_queue->ptr_mask); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci /* Allocate software ring */ 388c2ecf20Sopenharmony_ci tx_queue->buffer = kcalloc(entries, sizeof(*tx_queue->buffer), 398c2ecf20Sopenharmony_ci GFP_KERNEL); 408c2ecf20Sopenharmony_ci if (!tx_queue->buffer) 418c2ecf20Sopenharmony_ci return -ENOMEM; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci tx_queue->cb_page = kcalloc(efx_tx_cb_page_count(tx_queue), 448c2ecf20Sopenharmony_ci sizeof(tx_queue->cb_page[0]), GFP_KERNEL); 458c2ecf20Sopenharmony_ci if (!tx_queue->cb_page) { 468c2ecf20Sopenharmony_ci rc = -ENOMEM; 478c2ecf20Sopenharmony_ci goto fail1; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci /* Allocate hardware ring, determine TXQ type */ 518c2ecf20Sopenharmony_ci rc = efx_nic_probe_tx(tx_queue); 528c2ecf20Sopenharmony_ci if (rc) 538c2ecf20Sopenharmony_ci goto fail2; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci tx_queue->channel->tx_queue_by_type[tx_queue->type] = tx_queue; 568c2ecf20Sopenharmony_ci return 0; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cifail2: 598c2ecf20Sopenharmony_ci kfree(tx_queue->cb_page); 608c2ecf20Sopenharmony_ci tx_queue->cb_page = NULL; 618c2ecf20Sopenharmony_cifail1: 628c2ecf20Sopenharmony_ci kfree(tx_queue->buffer); 638c2ecf20Sopenharmony_ci tx_queue->buffer = NULL; 648c2ecf20Sopenharmony_ci return rc; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_civoid efx_init_tx_queue(struct efx_tx_queue *tx_queue) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct efx_nic *efx = tx_queue->efx; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, 728c2ecf20Sopenharmony_ci "initialising TX queue %d\n", tx_queue->queue); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci tx_queue->insert_count = 0; 758c2ecf20Sopenharmony_ci tx_queue->notify_count = 0; 768c2ecf20Sopenharmony_ci tx_queue->write_count = 0; 778c2ecf20Sopenharmony_ci tx_queue->packet_write_count = 0; 788c2ecf20Sopenharmony_ci tx_queue->old_write_count = 0; 798c2ecf20Sopenharmony_ci tx_queue->read_count = 0; 808c2ecf20Sopenharmony_ci tx_queue->old_read_count = 0; 818c2ecf20Sopenharmony_ci tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID; 828c2ecf20Sopenharmony_ci tx_queue->xmit_pending = false; 838c2ecf20Sopenharmony_ci tx_queue->timestamping = (efx_ptp_use_mac_tx_timestamps(efx) && 848c2ecf20Sopenharmony_ci tx_queue->channel == efx_ptp_channel(efx)); 858c2ecf20Sopenharmony_ci tx_queue->completed_timestamp_major = 0; 868c2ecf20Sopenharmony_ci tx_queue->completed_timestamp_minor = 0; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci tx_queue->xdp_tx = efx_channel_is_xdp_tx(tx_queue->channel); 898c2ecf20Sopenharmony_ci tx_queue->tso_version = 0; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* Set up TX descriptor ring */ 928c2ecf20Sopenharmony_ci efx_nic_init_tx(tx_queue); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci tx_queue->initialised = true; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_civoid efx_fini_tx_queue(struct efx_tx_queue *tx_queue) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci struct efx_tx_buffer *buffer; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev, 1028c2ecf20Sopenharmony_ci "shutting down TX queue %d\n", tx_queue->queue); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (!tx_queue->buffer) 1058c2ecf20Sopenharmony_ci return; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* Free any buffers left in the ring */ 1088c2ecf20Sopenharmony_ci while (tx_queue->read_count != tx_queue->write_count) { 1098c2ecf20Sopenharmony_ci unsigned int pkts_compl = 0, bytes_compl = 0; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask]; 1128c2ecf20Sopenharmony_ci efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci ++tx_queue->read_count; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci tx_queue->xmit_pending = false; 1178c2ecf20Sopenharmony_ci netdev_tx_reset_queue(tx_queue->core_txq); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_civoid efx_remove_tx_queue(struct efx_tx_queue *tx_queue) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci int i; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (!tx_queue->buffer) 1258c2ecf20Sopenharmony_ci return; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev, 1288c2ecf20Sopenharmony_ci "destroying TX queue %d\n", tx_queue->queue); 1298c2ecf20Sopenharmony_ci efx_nic_remove_tx(tx_queue); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (tx_queue->cb_page) { 1328c2ecf20Sopenharmony_ci for (i = 0; i < efx_tx_cb_page_count(tx_queue); i++) 1338c2ecf20Sopenharmony_ci efx_nic_free_buffer(tx_queue->efx, 1348c2ecf20Sopenharmony_ci &tx_queue->cb_page[i]); 1358c2ecf20Sopenharmony_ci kfree(tx_queue->cb_page); 1368c2ecf20Sopenharmony_ci tx_queue->cb_page = NULL; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci kfree(tx_queue->buffer); 1408c2ecf20Sopenharmony_ci tx_queue->buffer = NULL; 1418c2ecf20Sopenharmony_ci tx_queue->channel->tx_queue_by_type[tx_queue->type] = NULL; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_civoid efx_dequeue_buffer(struct efx_tx_queue *tx_queue, 1458c2ecf20Sopenharmony_ci struct efx_tx_buffer *buffer, 1468c2ecf20Sopenharmony_ci unsigned int *pkts_compl, 1478c2ecf20Sopenharmony_ci unsigned int *bytes_compl) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci if (buffer->unmap_len) { 1508c2ecf20Sopenharmony_ci struct device *dma_dev = &tx_queue->efx->pci_dev->dev; 1518c2ecf20Sopenharmony_ci dma_addr_t unmap_addr = buffer->dma_addr - buffer->dma_offset; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (buffer->flags & EFX_TX_BUF_MAP_SINGLE) 1548c2ecf20Sopenharmony_ci dma_unmap_single(dma_dev, unmap_addr, buffer->unmap_len, 1558c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 1568c2ecf20Sopenharmony_ci else 1578c2ecf20Sopenharmony_ci dma_unmap_page(dma_dev, unmap_addr, buffer->unmap_len, 1588c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 1598c2ecf20Sopenharmony_ci buffer->unmap_len = 0; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (buffer->flags & EFX_TX_BUF_SKB) { 1638c2ecf20Sopenharmony_ci struct sk_buff *skb = (struct sk_buff *)buffer->skb; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci EFX_WARN_ON_PARANOID(!pkts_compl || !bytes_compl); 1668c2ecf20Sopenharmony_ci (*pkts_compl)++; 1678c2ecf20Sopenharmony_ci (*bytes_compl) += skb->len; 1688c2ecf20Sopenharmony_ci if (tx_queue->timestamping && 1698c2ecf20Sopenharmony_ci (tx_queue->completed_timestamp_major || 1708c2ecf20Sopenharmony_ci tx_queue->completed_timestamp_minor)) { 1718c2ecf20Sopenharmony_ci struct skb_shared_hwtstamps hwtstamp; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci hwtstamp.hwtstamp = 1748c2ecf20Sopenharmony_ci efx_ptp_nic_to_kernel_time(tx_queue); 1758c2ecf20Sopenharmony_ci skb_tstamp_tx(skb, &hwtstamp); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci tx_queue->completed_timestamp_major = 0; 1788c2ecf20Sopenharmony_ci tx_queue->completed_timestamp_minor = 0; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci dev_consume_skb_any((struct sk_buff *)buffer->skb); 1818c2ecf20Sopenharmony_ci netif_vdbg(tx_queue->efx, tx_done, tx_queue->efx->net_dev, 1828c2ecf20Sopenharmony_ci "TX queue %d transmission id %x complete\n", 1838c2ecf20Sopenharmony_ci tx_queue->queue, tx_queue->read_count); 1848c2ecf20Sopenharmony_ci } else if (buffer->flags & EFX_TX_BUF_XDP) { 1858c2ecf20Sopenharmony_ci xdp_return_frame_rx_napi(buffer->xdpf); 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci buffer->len = 0; 1898c2ecf20Sopenharmony_ci buffer->flags = 0; 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci/* Remove packets from the TX queue 1938c2ecf20Sopenharmony_ci * 1948c2ecf20Sopenharmony_ci * This removes packets from the TX queue, up to and including the 1958c2ecf20Sopenharmony_ci * specified index. 1968c2ecf20Sopenharmony_ci */ 1978c2ecf20Sopenharmony_cistatic void efx_dequeue_buffers(struct efx_tx_queue *tx_queue, 1988c2ecf20Sopenharmony_ci unsigned int index, 1998c2ecf20Sopenharmony_ci unsigned int *pkts_compl, 2008c2ecf20Sopenharmony_ci unsigned int *bytes_compl) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci struct efx_nic *efx = tx_queue->efx; 2038c2ecf20Sopenharmony_ci unsigned int stop_index, read_ptr; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci stop_index = (index + 1) & tx_queue->ptr_mask; 2068c2ecf20Sopenharmony_ci read_ptr = tx_queue->read_count & tx_queue->ptr_mask; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci while (read_ptr != stop_index) { 2098c2ecf20Sopenharmony_ci struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr]; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (!efx_tx_buffer_in_use(buffer)) { 2128c2ecf20Sopenharmony_ci netif_err(efx, tx_err, efx->net_dev, 2138c2ecf20Sopenharmony_ci "TX queue %d spurious TX completion id %d\n", 2148c2ecf20Sopenharmony_ci tx_queue->queue, read_ptr); 2158c2ecf20Sopenharmony_ci efx_schedule_reset(efx, RESET_TYPE_TX_SKIP); 2168c2ecf20Sopenharmony_ci return; 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci efx_dequeue_buffer(tx_queue, buffer, pkts_compl, bytes_compl); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci ++tx_queue->read_count; 2228c2ecf20Sopenharmony_ci read_ptr = tx_queue->read_count & tx_queue->ptr_mask; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_civoid efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci if ((int)(tx_queue->read_count - tx_queue->old_write_count) >= 0) { 2298c2ecf20Sopenharmony_ci tx_queue->old_write_count = READ_ONCE(tx_queue->write_count); 2308c2ecf20Sopenharmony_ci if (tx_queue->read_count == tx_queue->old_write_count) { 2318c2ecf20Sopenharmony_ci /* Ensure that read_count is flushed. */ 2328c2ecf20Sopenharmony_ci smp_mb(); 2338c2ecf20Sopenharmony_ci tx_queue->empty_read_count = 2348c2ecf20Sopenharmony_ci tx_queue->read_count | EFX_EMPTY_COUNT_VALID; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_civoid efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci unsigned int fill_level, pkts_compl = 0, bytes_compl = 0; 2428c2ecf20Sopenharmony_ci struct efx_nic *efx = tx_queue->efx; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci EFX_WARN_ON_ONCE_PARANOID(index > tx_queue->ptr_mask); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl); 2478c2ecf20Sopenharmony_ci tx_queue->pkts_compl += pkts_compl; 2488c2ecf20Sopenharmony_ci tx_queue->bytes_compl += bytes_compl; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (pkts_compl > 1) 2518c2ecf20Sopenharmony_ci ++tx_queue->merge_events; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* See if we need to restart the netif queue. This memory 2548c2ecf20Sopenharmony_ci * barrier ensures that we write read_count (inside 2558c2ecf20Sopenharmony_ci * efx_dequeue_buffers()) before reading the queue status. 2568c2ecf20Sopenharmony_ci */ 2578c2ecf20Sopenharmony_ci smp_mb(); 2588c2ecf20Sopenharmony_ci if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) && 2598c2ecf20Sopenharmony_ci likely(efx->port_enabled) && 2608c2ecf20Sopenharmony_ci likely(netif_device_present(efx->net_dev))) { 2618c2ecf20Sopenharmony_ci fill_level = efx_channel_tx_fill_level(tx_queue->channel); 2628c2ecf20Sopenharmony_ci if (fill_level <= efx->txq_wake_thresh) 2638c2ecf20Sopenharmony_ci netif_tx_wake_queue(tx_queue->core_txq); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci efx_xmit_done_check_empty(tx_queue); 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci/* Remove buffers put into a tx_queue for the current packet. 2708c2ecf20Sopenharmony_ci * None of the buffers must have an skb attached. 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_civoid efx_enqueue_unwind(struct efx_tx_queue *tx_queue, 2738c2ecf20Sopenharmony_ci unsigned int insert_count) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci struct efx_tx_buffer *buffer; 2768c2ecf20Sopenharmony_ci unsigned int bytes_compl = 0; 2778c2ecf20Sopenharmony_ci unsigned int pkts_compl = 0; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Work backwards until we hit the original insert pointer value */ 2808c2ecf20Sopenharmony_ci while (tx_queue->insert_count != insert_count) { 2818c2ecf20Sopenharmony_ci --tx_queue->insert_count; 2828c2ecf20Sopenharmony_ci buffer = __efx_tx_queue_get_insert_buffer(tx_queue); 2838c2ecf20Sopenharmony_ci efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl); 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistruct efx_tx_buffer *efx_tx_map_chunk(struct efx_tx_queue *tx_queue, 2888c2ecf20Sopenharmony_ci dma_addr_t dma_addr, size_t len) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci const struct efx_nic_type *nic_type = tx_queue->efx->type; 2918c2ecf20Sopenharmony_ci struct efx_tx_buffer *buffer; 2928c2ecf20Sopenharmony_ci unsigned int dma_len; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* Map the fragment taking account of NIC-dependent DMA limits. */ 2958c2ecf20Sopenharmony_ci do { 2968c2ecf20Sopenharmony_ci buffer = efx_tx_queue_get_insert_buffer(tx_queue); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (nic_type->tx_limit_len) 2998c2ecf20Sopenharmony_ci dma_len = nic_type->tx_limit_len(tx_queue, dma_addr, len); 3008c2ecf20Sopenharmony_ci else 3018c2ecf20Sopenharmony_ci dma_len = len; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci buffer->len = dma_len; 3048c2ecf20Sopenharmony_ci buffer->dma_addr = dma_addr; 3058c2ecf20Sopenharmony_ci buffer->flags = EFX_TX_BUF_CONT; 3068c2ecf20Sopenharmony_ci len -= dma_len; 3078c2ecf20Sopenharmony_ci dma_addr += dma_len; 3088c2ecf20Sopenharmony_ci ++tx_queue->insert_count; 3098c2ecf20Sopenharmony_ci } while (len); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return buffer; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ciint efx_tx_tso_header_length(struct sk_buff *skb) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci size_t header_len; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (skb->encapsulation) 3198c2ecf20Sopenharmony_ci header_len = skb_inner_transport_header(skb) - 3208c2ecf20Sopenharmony_ci skb->data + 3218c2ecf20Sopenharmony_ci (inner_tcp_hdr(skb)->doff << 2u); 3228c2ecf20Sopenharmony_ci else 3238c2ecf20Sopenharmony_ci header_len = skb_transport_header(skb) - skb->data + 3248c2ecf20Sopenharmony_ci (tcp_hdr(skb)->doff << 2u); 3258c2ecf20Sopenharmony_ci return header_len; 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci/* Map all data from an SKB for DMA and create descriptors on the queue. */ 3298c2ecf20Sopenharmony_ciint efx_tx_map_data(struct efx_tx_queue *tx_queue, struct sk_buff *skb, 3308c2ecf20Sopenharmony_ci unsigned int segment_count) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct efx_nic *efx = tx_queue->efx; 3338c2ecf20Sopenharmony_ci struct device *dma_dev = &efx->pci_dev->dev; 3348c2ecf20Sopenharmony_ci unsigned int frag_index, nr_frags; 3358c2ecf20Sopenharmony_ci dma_addr_t dma_addr, unmap_addr; 3368c2ecf20Sopenharmony_ci unsigned short dma_flags; 3378c2ecf20Sopenharmony_ci size_t len, unmap_len; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci nr_frags = skb_shinfo(skb)->nr_frags; 3408c2ecf20Sopenharmony_ci frag_index = 0; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* Map header data. */ 3438c2ecf20Sopenharmony_ci len = skb_headlen(skb); 3448c2ecf20Sopenharmony_ci dma_addr = dma_map_single(dma_dev, skb->data, len, DMA_TO_DEVICE); 3458c2ecf20Sopenharmony_ci dma_flags = EFX_TX_BUF_MAP_SINGLE; 3468c2ecf20Sopenharmony_ci unmap_len = len; 3478c2ecf20Sopenharmony_ci unmap_addr = dma_addr; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (unlikely(dma_mapping_error(dma_dev, dma_addr))) 3508c2ecf20Sopenharmony_ci return -EIO; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (segment_count) { 3538c2ecf20Sopenharmony_ci /* For TSO we need to put the header in to a separate 3548c2ecf20Sopenharmony_ci * descriptor. Map this separately if necessary. 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_ci size_t header_len = efx_tx_tso_header_length(skb); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (header_len != len) { 3598c2ecf20Sopenharmony_ci tx_queue->tso_long_headers++; 3608c2ecf20Sopenharmony_ci efx_tx_map_chunk(tx_queue, dma_addr, header_len); 3618c2ecf20Sopenharmony_ci len -= header_len; 3628c2ecf20Sopenharmony_ci dma_addr += header_len; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci /* Add descriptors for each fragment. */ 3678c2ecf20Sopenharmony_ci do { 3688c2ecf20Sopenharmony_ci struct efx_tx_buffer *buffer; 3698c2ecf20Sopenharmony_ci skb_frag_t *fragment; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci buffer = efx_tx_map_chunk(tx_queue, dma_addr, len); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* The final descriptor for a fragment is responsible for 3748c2ecf20Sopenharmony_ci * unmapping the whole fragment. 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_ci buffer->flags = EFX_TX_BUF_CONT | dma_flags; 3778c2ecf20Sopenharmony_ci buffer->unmap_len = unmap_len; 3788c2ecf20Sopenharmony_ci buffer->dma_offset = buffer->dma_addr - unmap_addr; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (frag_index >= nr_frags) { 3818c2ecf20Sopenharmony_ci /* Store SKB details with the final buffer for 3828c2ecf20Sopenharmony_ci * the completion. 3838c2ecf20Sopenharmony_ci */ 3848c2ecf20Sopenharmony_ci buffer->skb = skb; 3858c2ecf20Sopenharmony_ci buffer->flags = EFX_TX_BUF_SKB | dma_flags; 3868c2ecf20Sopenharmony_ci return 0; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci /* Move on to the next fragment. */ 3908c2ecf20Sopenharmony_ci fragment = &skb_shinfo(skb)->frags[frag_index++]; 3918c2ecf20Sopenharmony_ci len = skb_frag_size(fragment); 3928c2ecf20Sopenharmony_ci dma_addr = skb_frag_dma_map(dma_dev, fragment, 0, len, 3938c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 3948c2ecf20Sopenharmony_ci dma_flags = 0; 3958c2ecf20Sopenharmony_ci unmap_len = len; 3968c2ecf20Sopenharmony_ci unmap_addr = dma_addr; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (unlikely(dma_mapping_error(dma_dev, dma_addr))) 3998c2ecf20Sopenharmony_ci return -EIO; 4008c2ecf20Sopenharmony_ci } while (1); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ciunsigned int efx_tx_max_skb_descs(struct efx_nic *efx) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci /* Header and payload descriptor for each output segment, plus 4068c2ecf20Sopenharmony_ci * one for every input fragment boundary within a segment 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_ci unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* Possibly one more per segment for option descriptors */ 4118c2ecf20Sopenharmony_ci if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) 4128c2ecf20Sopenharmony_ci max_descs += EFX_TSO_MAX_SEGS; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* Possibly more for PCIe page boundaries within input fragments */ 4158c2ecf20Sopenharmony_ci if (PAGE_SIZE > EFX_PAGE_SIZE) 4168c2ecf20Sopenharmony_ci max_descs += max_t(unsigned int, MAX_SKB_FRAGS, 4178c2ecf20Sopenharmony_ci DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci return max_descs; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci/* 4238c2ecf20Sopenharmony_ci * Fallback to software TSO. 4248c2ecf20Sopenharmony_ci * 4258c2ecf20Sopenharmony_ci * This is used if we are unable to send a GSO packet through hardware TSO. 4268c2ecf20Sopenharmony_ci * This should only ever happen due to per-queue restrictions - unsupported 4278c2ecf20Sopenharmony_ci * packets should first be filtered by the feature flags. 4288c2ecf20Sopenharmony_ci * 4298c2ecf20Sopenharmony_ci * Returns 0 on success, error code otherwise. 4308c2ecf20Sopenharmony_ci */ 4318c2ecf20Sopenharmony_ciint efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci struct sk_buff *segments, *next; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci segments = skb_gso_segment(skb, 0); 4368c2ecf20Sopenharmony_ci if (IS_ERR(segments)) 4378c2ecf20Sopenharmony_ci return PTR_ERR(segments); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci dev_consume_skb_any(skb); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci skb_list_walk_safe(segments, skb, next) { 4428c2ecf20Sopenharmony_ci skb_mark_not_on_list(skb); 4438c2ecf20Sopenharmony_ci efx_enqueue_skb(tx_queue, skb); 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci return 0; 4478c2ecf20Sopenharmony_ci} 448