162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright(c) 2023 - Cornelis Networks, Inc. 462306a36Sopenharmony_ci * Copyright(c) 2015 - 2018 Intel Corporation. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef _HFI1_USER_SDMA_H 762306a36Sopenharmony_ci#define _HFI1_USER_SDMA_H 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/device.h> 1062306a36Sopenharmony_ci#include <linux/wait.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "common.h" 1362306a36Sopenharmony_ci#include "iowait.h" 1462306a36Sopenharmony_ci#include "user_exp_rcv.h" 1562306a36Sopenharmony_ci#include "mmu_rb.h" 1662306a36Sopenharmony_ci#include "pinning.h" 1762306a36Sopenharmony_ci#include "sdma.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* The maximum number of Data io vectors per message/request */ 2062306a36Sopenharmony_ci#define MAX_VECTORS_PER_REQ 8 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * Maximum number of packet to send from each message/request 2362306a36Sopenharmony_ci * before moving to the next one. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci#define MAX_PKTS_PER_QUEUE 16 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define num_pages(x) (1 + ((((x) - 1) & PAGE_MASK) >> PAGE_SHIFT)) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define req_opcode(x) \ 3062306a36Sopenharmony_ci (((x) >> HFI1_SDMA_REQ_OPCODE_SHIFT) & HFI1_SDMA_REQ_OPCODE_MASK) 3162306a36Sopenharmony_ci#define req_version(x) \ 3262306a36Sopenharmony_ci (((x) >> HFI1_SDMA_REQ_VERSION_SHIFT) & HFI1_SDMA_REQ_OPCODE_MASK) 3362306a36Sopenharmony_ci#define req_iovcnt(x) \ 3462306a36Sopenharmony_ci (((x) >> HFI1_SDMA_REQ_IOVCNT_SHIFT) & HFI1_SDMA_REQ_IOVCNT_MASK) 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* Number of BTH.PSN bits used for sequence number in expected rcvs */ 3762306a36Sopenharmony_ci#define BTH_SEQ_MASK 0x7ffull 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define AHG_KDETH_INTR_SHIFT 12 4062306a36Sopenharmony_ci#define AHG_KDETH_SH_SHIFT 13 4162306a36Sopenharmony_ci#define AHG_KDETH_ARRAY_SIZE 9 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define PBC2LRH(x) ((((x) & 0xfff) << 2) - 4) 4462306a36Sopenharmony_ci#define LRH2PBC(x) ((((x) >> 2) + 1) & 0xfff) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/** 4762306a36Sopenharmony_ci * Build an SDMA AHG header update descriptor and save it to an array. 4862306a36Sopenharmony_ci * @arr - Array to save the descriptor to. 4962306a36Sopenharmony_ci * @idx - Index of the array at which the descriptor will be saved. 5062306a36Sopenharmony_ci * @array_size - Size of the array arr. 5162306a36Sopenharmony_ci * @dw - Update index into the header in DWs. 5262306a36Sopenharmony_ci * @bit - Start bit. 5362306a36Sopenharmony_ci * @width - Field width. 5462306a36Sopenharmony_ci * @value - 16 bits of immediate data to write into the field. 5562306a36Sopenharmony_ci * Returns -ERANGE if idx is invalid. If successful, returns the next index 5662306a36Sopenharmony_ci * (idx + 1) of the array to be used for the next descriptor. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_cistatic inline int ahg_header_set(u32 *arr, int idx, size_t array_size, 5962306a36Sopenharmony_ci u8 dw, u8 bit, u8 width, u16 value) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci if ((size_t)idx >= array_size) 6262306a36Sopenharmony_ci return -ERANGE; 6362306a36Sopenharmony_ci arr[idx++] = sdma_build_ahg_descriptor(value, dw, bit, width); 6462306a36Sopenharmony_ci return idx; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* Tx request flag bits */ 6862306a36Sopenharmony_ci#define TXREQ_FLAGS_REQ_ACK BIT(0) /* Set the ACK bit in the header */ 6962306a36Sopenharmony_ci#define TXREQ_FLAGS_REQ_DISABLE_SH BIT(1) /* Disable header suppression */ 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cienum pkt_q_sdma_state { 7262306a36Sopenharmony_ci SDMA_PKT_Q_ACTIVE, 7362306a36Sopenharmony_ci SDMA_PKT_Q_DEFERRED, 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define SDMA_IOWAIT_TIMEOUT 1000 /* in milliseconds */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define SDMA_DBG(req, fmt, ...) \ 7962306a36Sopenharmony_ci hfi1_cdbg(SDMA, "[%u:%u:%u:%u] " fmt, (req)->pq->dd->unit, \ 8062306a36Sopenharmony_ci (req)->pq->ctxt, (req)->pq->subctxt, (req)->info.comp_idx, \ 8162306a36Sopenharmony_ci ##__VA_ARGS__) 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistruct hfi1_user_sdma_pkt_q { 8462306a36Sopenharmony_ci u16 ctxt; 8562306a36Sopenharmony_ci u16 subctxt; 8662306a36Sopenharmony_ci u16 n_max_reqs; 8762306a36Sopenharmony_ci atomic_t n_reqs; 8862306a36Sopenharmony_ci u16 reqidx; 8962306a36Sopenharmony_ci struct hfi1_devdata *dd; 9062306a36Sopenharmony_ci struct kmem_cache *txreq_cache; 9162306a36Sopenharmony_ci struct user_sdma_request *reqs; 9262306a36Sopenharmony_ci unsigned long *req_in_use; 9362306a36Sopenharmony_ci struct iowait busy; 9462306a36Sopenharmony_ci enum pkt_q_sdma_state state; 9562306a36Sopenharmony_ci wait_queue_head_t wait; 9662306a36Sopenharmony_ci unsigned long unpinned; 9762306a36Sopenharmony_ci struct mmu_rb_handler *handler; 9862306a36Sopenharmony_ci atomic_t n_locked; 9962306a36Sopenharmony_ci}; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistruct hfi1_user_sdma_comp_q { 10262306a36Sopenharmony_ci u16 nentries; 10362306a36Sopenharmony_ci struct hfi1_sdma_comp_entry *comps; 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistruct user_sdma_iovec { 10762306a36Sopenharmony_ci struct list_head list; 10862306a36Sopenharmony_ci struct iovec iov; 10962306a36Sopenharmony_ci /* 11062306a36Sopenharmony_ci * offset into the virtual address space of the vector at 11162306a36Sopenharmony_ci * which we last left off. 11262306a36Sopenharmony_ci */ 11362306a36Sopenharmony_ci u64 offset; 11462306a36Sopenharmony_ci}; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/* evict operation argument */ 11762306a36Sopenharmony_cistruct evict_data { 11862306a36Sopenharmony_ci u32 cleared; /* count evicted so far */ 11962306a36Sopenharmony_ci u32 target; /* target count to evict */ 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistruct user_sdma_request { 12362306a36Sopenharmony_ci /* This is the original header from user space */ 12462306a36Sopenharmony_ci struct hfi1_pkt_header hdr; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* Read mostly fields */ 12762306a36Sopenharmony_ci struct hfi1_user_sdma_pkt_q *pq ____cacheline_aligned_in_smp; 12862306a36Sopenharmony_ci struct hfi1_user_sdma_comp_q *cq; 12962306a36Sopenharmony_ci /* 13062306a36Sopenharmony_ci * Pointer to the SDMA engine for this request. 13162306a36Sopenharmony_ci * Since different request could be on different VLs, 13262306a36Sopenharmony_ci * each request will need it's own engine pointer. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci struct sdma_engine *sde; 13562306a36Sopenharmony_ci struct sdma_req_info info; 13662306a36Sopenharmony_ci /* TID array values copied from the tid_iov vector */ 13762306a36Sopenharmony_ci u32 *tids; 13862306a36Sopenharmony_ci /* total length of the data in the request */ 13962306a36Sopenharmony_ci u32 data_len; 14062306a36Sopenharmony_ci /* number of elements copied to the tids array */ 14162306a36Sopenharmony_ci u16 n_tids; 14262306a36Sopenharmony_ci /* 14362306a36Sopenharmony_ci * We copy the iovs for this request (based on 14462306a36Sopenharmony_ci * info.iovcnt). These are only the data vectors 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_ci u8 data_iovs; 14762306a36Sopenharmony_ci s8 ahg_idx; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* Writeable fields shared with interrupt */ 15062306a36Sopenharmony_ci u16 seqcomp ____cacheline_aligned_in_smp; 15162306a36Sopenharmony_ci u16 seqsubmitted; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* Send side fields */ 15462306a36Sopenharmony_ci struct list_head txps ____cacheline_aligned_in_smp; 15562306a36Sopenharmony_ci u16 seqnum; 15662306a36Sopenharmony_ci /* 15762306a36Sopenharmony_ci * KDETH.OFFSET (TID) field 15862306a36Sopenharmony_ci * The offset can cover multiple packets, depending on the 15962306a36Sopenharmony_ci * size of the TID entry. 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci u32 tidoffset; 16262306a36Sopenharmony_ci /* 16362306a36Sopenharmony_ci * KDETH.Offset (Eager) field 16462306a36Sopenharmony_ci * We need to remember the initial value so the headers 16562306a36Sopenharmony_ci * can be updated properly. 16662306a36Sopenharmony_ci */ 16762306a36Sopenharmony_ci u32 koffset; 16862306a36Sopenharmony_ci u32 sent; 16962306a36Sopenharmony_ci /* TID index copied from the tid_iov vector */ 17062306a36Sopenharmony_ci u16 tididx; 17162306a36Sopenharmony_ci /* progress index moving along the iovs array */ 17262306a36Sopenharmony_ci u8 iov_idx; 17362306a36Sopenharmony_ci u8 has_error; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci struct user_sdma_iovec iovs[MAX_VECTORS_PER_REQ]; 17662306a36Sopenharmony_ci} ____cacheline_aligned_in_smp; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/* 17962306a36Sopenharmony_ci * A single txreq could span up to 3 physical pages when the MTU 18062306a36Sopenharmony_ci * is sufficiently large (> 4K). Each of the IOV pointers also 18162306a36Sopenharmony_ci * needs it's own set of flags so the vector has been handled 18262306a36Sopenharmony_ci * independently of each other. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_cistruct user_sdma_txreq { 18562306a36Sopenharmony_ci /* Packet header for the txreq */ 18662306a36Sopenharmony_ci struct hfi1_pkt_header hdr; 18762306a36Sopenharmony_ci struct sdma_txreq txreq; 18862306a36Sopenharmony_ci struct list_head list; 18962306a36Sopenharmony_ci struct user_sdma_request *req; 19062306a36Sopenharmony_ci u16 flags; 19162306a36Sopenharmony_ci u16 seqnum; 19262306a36Sopenharmony_ci}; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ciint hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, 19562306a36Sopenharmony_ci struct hfi1_filedata *fd); 19662306a36Sopenharmony_ciint hfi1_user_sdma_free_queues(struct hfi1_filedata *fd, 19762306a36Sopenharmony_ci struct hfi1_ctxtdata *uctxt); 19862306a36Sopenharmony_ciint hfi1_user_sdma_process_request(struct hfi1_filedata *fd, 19962306a36Sopenharmony_ci struct iovec *iovec, unsigned long dim, 20062306a36Sopenharmony_ci unsigned long *count); 20162306a36Sopenharmony_ci#endif /* _HFI1_USER_SDMA_H */ 202