| /* |
| * Copyright (c) 2021, The Linux Foundation. All rights reserved. |
| * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| #ifndef __EDMA_RX_H__ |
| #define __EDMA_RX_H__ |
| |
| #define EDMA_RXFILL_RING_PER_CORE_MAX 1 |
| #define EDMA_RXDESC_RING_PER_CORE_MAX 1 |
| |
| #define EDMA_RX_MAX_PROCESS 32 /* Max Rx processing without |
| replenishing RxFill ring */ |
| #define EDMA_RX_SKB_HEADROOM 128 |
| |
| #define EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[(i)])) |
| #define EDMA_GET_PDESC(R, i, type) (&(((type *)((R)->pdesc))[(i)])) |
| #define EDMA_GET_SDESC(R, i, type) (&(((type *)((R)->sdesc))[(i)])) |
| #define EDMA_RXFILL_DESC(R, i) EDMA_GET_DESC(R, i, struct edma_rxfill_desc) |
| #define EDMA_RXDESC_PRI_DESC(R, i) EDMA_GET_PDESC(R, i, struct edma_rxdesc_desc) |
| #define EDMA_RXDESC_SEC_DESC(R, i) EDMA_GET_SDESC(R, i, struct edma_rxdesc_sec_desc) |
| |
| #define EDMA_RX_RING_SIZE 256 |
| #define EDMA_RX_RING_SIZE_MASK (EDMA_RX_RING_SIZE - 1) |
| #define EDMA_RX_RING_ID_MASK 0x1F |
| #define EDMA_MAX_RXDESC_RINGS 24 /* Max RxDesc rings */ |
| #define EDMA_MAX_RXFILL_RINGS 8 /* Max RxFill rings */ |
| #define EDMA_RX_MAX_PRIORITY_LEVEL 1 |
| |
| #define EDMA_RX_PID_IPV4_MAX 0x3 |
| #define EDMA_RX_PID_IPV6 0x4 |
| #define EDMA_RX_PID_IS_IPV4(pid) (!((pid) & (~EDMA_RX_PID_IPV4_MAX))) |
| #define EDMA_RX_PID_IS_IPV6(pid) (!(!((pid) & EDMA_RX_PID_IPV6))) |
| |
| #define EDMA_RXDESC_BUFFER_ADDR_GET(desc) ((uint32_t)((desc)->word0)) |
| #define EDMA_RXDESC_OPAQUE_GET(desc) ((uintptr_t)((uint64_t)((desc)->word2) | \ |
| ((uint64_t)((desc)->word3) << 0x20))) |
| #define EDMA_RXDESC_SRCINFO_TYPE_PORTID 0x2000 |
| #define EDMA_RXDESC_SRCINFO_TYPE_SHIFT 8 |
| #define EDMA_RXDESC_SRCINFO_TYPE_MASK 0xF000 |
| #define EDMA_RXDESC_L3CSUM_STATUS_MASK 0x2000 |
| #define EDMA_RXDESC_L4CSUM_STATUS_MASK 0x1000 |
| #define EDMA_RXDESC_PORTNUM_BITS 0x0FFF |
| |
| #define EDMA_RXDESC_PACKET_LEN_MASK 0x3FFFF |
| #define EDMA_RXDESC_PACKET_LEN_GET(desc) (((desc)->word5) & \ |
| EDMA_RXDESC_PACKET_LEN_MASK) |
| #define EDMA_RXDESC_MORE_BIT_MASK 0x40000000 |
| #define EDMA_RXDESC_MORE_BIT_GET(desc) (((desc)->word1) & \ |
| EDMA_RXDESC_MORE_BIT_MASK) |
| #define EDMA_RXDESC_SRC_INFO_GET(desc) (((desc)->word4) & 0xFFFF) |
| #define EDMA_RXDESC_L3CSUM_STATUS_GET(desc) (((desc)->word6) & \ |
| EDMA_RXDESC_L3CSUM_STATUS_MASK) |
| #define EDMA_RXDESC_L4CSUM_STATUS_GET(desc) (((desc)->word6) & \ |
| EDMA_RXDESC_L4CSUM_STATUS_MASK) |
| #define EDMA_RXDESC_SERVICE_CODE_GET(desc) (((desc)->word7) & 0x1FF) |
| #define EDMA_RXDESC_PID_GET(desc) (((desc)->word7) & 0x7000) >> 0x0C |
| |
| #define EDMA_RXFILL_BUF_SIZE_MASK 0xFFFF |
| #define EDMA_RXFILL_BUF_SIZE_SHIFT 16 |
| #define EDMA_RXFILL_OPAQUE_LO_SET(desc, ptr) (((desc)->word2) = (uint32_t)(uintptr_t)(ptr)) |
| #define EDMA_RXFILL_OPAQUE_HI_SET(desc, ptr) (((desc)->word3) = (uint32_t)((uint64_t)(ptr) >> 0x20)) |
| #define EDMA_RXFILL_OPAQUE_GET(desc) ((uintptr_t)((uint64_t)((desc)->word2) | \ |
| ((uint64_t)((desc)->word3) << 0x20))) |
| #define EDMA_RXFILL_PACKET_LEN_SET(desc, len) (((desc)->word1) = (uint32_t)\ |
| ((((uint32_t)len) << \ |
| EDMA_RXFILL_BUF_SIZE_SHIFT) & 0xFFFF0000)) |
| #define EDMA_RXFILL_BUFFER_ADDR_SET(desc, addr) (((desc)->word0) = (uint32_t)(addr)) |
| |
| /* |
| * edma_rx_stats |
| * EDMA RX per cpu stats |
| */ |
| struct edma_rx_stats { |
| uint64_t rx_pkts; |
| uint64_t rx_bytes; |
| uint64_t rx_drops; |
| uint64_t rx_nr_frag_pkts; |
| uint64_t rx_fraglist_pkts; |
| uint64_t rx_nr_frag_headroom_err; |
| struct u64_stats_sync syncp; |
| }; |
| |
| /* |
| * edma_rx_desc_stats |
| * RX descriptor ring stats data structure |
| */ |
| struct edma_rx_desc_stats { |
| uint64_t src_port_inval; /* Invalid source port number */ |
| uint64_t src_port_inval_type; /* Source type is not PORT ID */ |
| uint64_t src_port_inval_netdev; /* Invalid net device for the source port */ |
| struct u64_stats_sync syncp; /* Synchronization pointer */ |
| }; |
| |
| /* |
| * edma_rx_fill_stats |
| * Rx fill descriptor ring stats data structure |
| */ |
| struct edma_rx_fill_stats { |
| uint64_t alloc_failed; /* Buffer allocation failure count */ |
| uint64_t page_alloc_failed; /* Page allocation failure count for page mode */ |
| struct u64_stats_sync syncp; /* Synchronization pointer */ |
| }; |
| |
| /* |
| * Rx descriptor |
| */ |
| struct edma_rxdesc_desc { |
| uint32_t word0; /* Contains buffer address */ |
| uint32_t word1; /* Contains more bit, priority bit, service code */ |
| uint32_t word2; /* Contains opaque */ |
| uint32_t word3; /* Contains opaque high bits */ |
| uint32_t word4; /* Contains destination and source information */ |
| uint32_t word5; /* Contains WiFi QoS, data length */ |
| uint32_t word6; /* Contains hash value, check sum status */ |
| uint32_t word7; /* Contains DSCP, packet offsets */ |
| }; |
| |
| /* |
| * Rx secondary descriptor |
| */ |
| struct edma_rxdesc_sec_desc { |
| uint32_t word0; /* Contains timestamp */ |
| uint32_t word1; /* Contains secondary checksum status */ |
| uint32_t word2; /* Contains QoS tag */ |
| uint32_t word3; /* Contains flow index details */ |
| uint32_t word4; /* Contains secondary packet offsets */ |
| uint32_t word5; /* Contains multicast bit, checksum */ |
| uint32_t word6; /* Contains SVLAN, CVLAN */ |
| uint32_t word7; /* Contains secondary SVLAN, CVLAN */ |
| }; |
| |
| /* |
| * RxFill descriptor |
| */ |
| struct edma_rxfill_desc { |
| uint32_t word0; /* Contains buffer address */ |
| uint32_t word1; /* Contains buffer size */ |
| uint32_t word2; /* Contains opaque */ |
| uint32_t word3; /* Contains opaque high bits */ |
| }; |
| |
| /* |
| * RxFill ring |
| */ |
| struct edma_rxfill_ring { |
| uint32_t ring_id; /* RXFILL ring number */ |
| uint32_t count; /* number of descriptors in the ring */ |
| uint32_t prod_idx; /* Ring producer index */ |
| uint32_t alloc_size; /* Buffer size to allocate */ |
| struct edma_rxfill_desc *desc; /* descriptor ring virtual address */ |
| dma_addr_t dma; /* descriptor ring physical address */ |
| uint32_t buf_len; /* Buffer length for rxfill descriptor */ |
| bool page_mode; /* Page mode for Rx processing */ |
| struct edma_rx_fill_stats rx_fill_stats; |
| /* Rx fill ring statistics */ |
| }; |
| |
| /* |
| * RxDesc ring |
| */ |
| struct edma_rxdesc_ring { |
| struct napi_struct napi; /* Napi structure */ |
| uint32_t ring_id; /* RXDESC ring number */ |
| uint32_t count; /* number of descriptors in the ring */ |
| uint32_t work_leftover; /* Leftover descriptors to be processed */ |
| uint32_t cons_idx; /* Ring consumer index */ |
| struct edma_rxdesc_desc *pdesc; |
| /* Primary descriptor ring virtual address */ |
| struct edma_rxdesc_sec_desc *sdesc; |
| /* Secondary descriptor ring virtual address */ |
| struct edma_rx_desc_stats rx_desc_stats; |
| /* Rx descriptor ring statistics */ |
| struct edma_rxfill_ring *rxfill; |
| /* RXFILL ring used */ |
| bool napi_added; /* Flag to indicate NAPI add status */ |
| dma_addr_t pdma; /* Primary descriptor ring physical address */ |
| dma_addr_t sdma; /* Secondary descriptor ring physical address */ |
| struct sk_buff *head; /* Head of the skb list in case of scatter-gather frame */ |
| struct sk_buff *last; /* Last skb of the skb list in case of scatter-gather frame */ |
| }; |
| |
| irqreturn_t edma_rx_handle_irq(int irq, void *ctx); |
| int edma_rx_alloc_buffer(struct edma_rxfill_ring *rxfill_ring, int alloc_count); |
| int edma_rx_napi_poll(struct napi_struct *napi, int budget); |
| |
| #endif /* __EDMA_RX_H__ */ |