18c2ecf20Sopenharmony_ci#ifndef _HFI1_USER_SDMA_H 28c2ecf20Sopenharmony_ci#define _HFI1_USER_SDMA_H 38c2ecf20Sopenharmony_ci/* 48c2ecf20Sopenharmony_ci * Copyright(c) 2020 - Cornelis Networks, Inc. 58c2ecf20Sopenharmony_ci * Copyright(c) 2015 - 2018 Intel Corporation. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 88c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 138c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as 148c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 178c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 188c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 198c2ecf20Sopenharmony_ci * General Public License for more details. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * BSD LICENSE 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 248c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 258c2ecf20Sopenharmony_ci * are met: 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above copyright 288c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 298c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above copyright 308c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 318c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 328c2ecf20Sopenharmony_ci * distribution. 338c2ecf20Sopenharmony_ci * - Neither the name of Intel Corporation nor the names of its 348c2ecf20Sopenharmony_ci * contributors may be used to endorse or promote products derived 358c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 388c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 398c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 408c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 418c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 428c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 438c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 448c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 458c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 468c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 478c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ci#include <linux/device.h> 518c2ecf20Sopenharmony_ci#include <linux/wait.h> 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#include "common.h" 548c2ecf20Sopenharmony_ci#include "iowait.h" 558c2ecf20Sopenharmony_ci#include "user_exp_rcv.h" 568c2ecf20Sopenharmony_ci#include "mmu_rb.h" 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* The maximum number of Data io vectors per message/request */ 598c2ecf20Sopenharmony_ci#define MAX_VECTORS_PER_REQ 8 608c2ecf20Sopenharmony_ci/* 618c2ecf20Sopenharmony_ci * Maximum number of packet to send from each message/request 628c2ecf20Sopenharmony_ci * before moving to the next one. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ci#define MAX_PKTS_PER_QUEUE 16 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define num_pages(x) (1 + ((((x) - 1) & PAGE_MASK) >> PAGE_SHIFT)) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define req_opcode(x) \ 698c2ecf20Sopenharmony_ci (((x) >> HFI1_SDMA_REQ_OPCODE_SHIFT) & HFI1_SDMA_REQ_OPCODE_MASK) 708c2ecf20Sopenharmony_ci#define req_version(x) \ 718c2ecf20Sopenharmony_ci (((x) >> HFI1_SDMA_REQ_VERSION_SHIFT) & HFI1_SDMA_REQ_OPCODE_MASK) 728c2ecf20Sopenharmony_ci#define req_iovcnt(x) \ 738c2ecf20Sopenharmony_ci (((x) >> HFI1_SDMA_REQ_IOVCNT_SHIFT) & HFI1_SDMA_REQ_IOVCNT_MASK) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* Number of BTH.PSN bits used for sequence number in expected rcvs */ 768c2ecf20Sopenharmony_ci#define BTH_SEQ_MASK 0x7ffull 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define AHG_KDETH_INTR_SHIFT 12 798c2ecf20Sopenharmony_ci#define AHG_KDETH_SH_SHIFT 13 808c2ecf20Sopenharmony_ci#define AHG_KDETH_ARRAY_SIZE 9 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#define PBC2LRH(x) ((((x) & 0xfff) << 2) - 4) 838c2ecf20Sopenharmony_ci#define LRH2PBC(x) ((((x) >> 2) + 1) & 0xfff) 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/** 868c2ecf20Sopenharmony_ci * Build an SDMA AHG header update descriptor and save it to an array. 878c2ecf20Sopenharmony_ci * @arr - Array to save the descriptor to. 888c2ecf20Sopenharmony_ci * @idx - Index of the array at which the descriptor will be saved. 898c2ecf20Sopenharmony_ci * @array_size - Size of the array arr. 908c2ecf20Sopenharmony_ci * @dw - Update index into the header in DWs. 918c2ecf20Sopenharmony_ci * @bit - Start bit. 928c2ecf20Sopenharmony_ci * @width - Field width. 938c2ecf20Sopenharmony_ci * @value - 16 bits of immediate data to write into the field. 948c2ecf20Sopenharmony_ci * Returns -ERANGE if idx is invalid. If successful, returns the next index 958c2ecf20Sopenharmony_ci * (idx + 1) of the array to be used for the next descriptor. 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_cistatic inline int ahg_header_set(u32 *arr, int idx, size_t array_size, 988c2ecf20Sopenharmony_ci u8 dw, u8 bit, u8 width, u16 value) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci if ((size_t)idx >= array_size) 1018c2ecf20Sopenharmony_ci return -ERANGE; 1028c2ecf20Sopenharmony_ci arr[idx++] = sdma_build_ahg_descriptor(value, dw, bit, width); 1038c2ecf20Sopenharmony_ci return idx; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* Tx request flag bits */ 1078c2ecf20Sopenharmony_ci#define TXREQ_FLAGS_REQ_ACK BIT(0) /* Set the ACK bit in the header */ 1088c2ecf20Sopenharmony_ci#define TXREQ_FLAGS_REQ_DISABLE_SH BIT(1) /* Disable header suppression */ 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cienum pkt_q_sdma_state { 1118c2ecf20Sopenharmony_ci SDMA_PKT_Q_ACTIVE, 1128c2ecf20Sopenharmony_ci SDMA_PKT_Q_DEFERRED, 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci#define SDMA_IOWAIT_TIMEOUT 1000 /* in milliseconds */ 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define SDMA_DBG(req, fmt, ...) \ 1188c2ecf20Sopenharmony_ci hfi1_cdbg(SDMA, "[%u:%u:%u:%u] " fmt, (req)->pq->dd->unit, \ 1198c2ecf20Sopenharmony_ci (req)->pq->ctxt, (req)->pq->subctxt, (req)->info.comp_idx, \ 1208c2ecf20Sopenharmony_ci ##__VA_ARGS__) 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistruct hfi1_user_sdma_pkt_q { 1238c2ecf20Sopenharmony_ci u16 ctxt; 1248c2ecf20Sopenharmony_ci u16 subctxt; 1258c2ecf20Sopenharmony_ci u16 n_max_reqs; 1268c2ecf20Sopenharmony_ci atomic_t n_reqs; 1278c2ecf20Sopenharmony_ci u16 reqidx; 1288c2ecf20Sopenharmony_ci struct hfi1_devdata *dd; 1298c2ecf20Sopenharmony_ci struct kmem_cache *txreq_cache; 1308c2ecf20Sopenharmony_ci struct user_sdma_request *reqs; 1318c2ecf20Sopenharmony_ci unsigned long *req_in_use; 1328c2ecf20Sopenharmony_ci struct iowait busy; 1338c2ecf20Sopenharmony_ci enum pkt_q_sdma_state state; 1348c2ecf20Sopenharmony_ci wait_queue_head_t wait; 1358c2ecf20Sopenharmony_ci unsigned long unpinned; 1368c2ecf20Sopenharmony_ci struct mmu_rb_handler *handler; 1378c2ecf20Sopenharmony_ci atomic_t n_locked; 1388c2ecf20Sopenharmony_ci}; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistruct hfi1_user_sdma_comp_q { 1418c2ecf20Sopenharmony_ci u16 nentries; 1428c2ecf20Sopenharmony_ci struct hfi1_sdma_comp_entry *comps; 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistruct sdma_mmu_node { 1468c2ecf20Sopenharmony_ci struct mmu_rb_node rb; 1478c2ecf20Sopenharmony_ci struct hfi1_user_sdma_pkt_q *pq; 1488c2ecf20Sopenharmony_ci struct page **pages; 1498c2ecf20Sopenharmony_ci unsigned int npages; 1508c2ecf20Sopenharmony_ci}; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistruct user_sdma_iovec { 1538c2ecf20Sopenharmony_ci struct list_head list; 1548c2ecf20Sopenharmony_ci struct iovec iov; 1558c2ecf20Sopenharmony_ci /* 1568c2ecf20Sopenharmony_ci * offset into the virtual address space of the vector at 1578c2ecf20Sopenharmony_ci * which we last left off. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_ci u64 offset; 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci/* evict operation argument */ 1638c2ecf20Sopenharmony_cistruct evict_data { 1648c2ecf20Sopenharmony_ci u32 cleared; /* count evicted so far */ 1658c2ecf20Sopenharmony_ci u32 target; /* target count to evict */ 1668c2ecf20Sopenharmony_ci}; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistruct user_sdma_request { 1698c2ecf20Sopenharmony_ci /* This is the original header from user space */ 1708c2ecf20Sopenharmony_ci struct hfi1_pkt_header hdr; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* Read mostly fields */ 1738c2ecf20Sopenharmony_ci struct hfi1_user_sdma_pkt_q *pq ____cacheline_aligned_in_smp; 1748c2ecf20Sopenharmony_ci struct hfi1_user_sdma_comp_q *cq; 1758c2ecf20Sopenharmony_ci /* 1768c2ecf20Sopenharmony_ci * Pointer to the SDMA engine for this request. 1778c2ecf20Sopenharmony_ci * Since different request could be on different VLs, 1788c2ecf20Sopenharmony_ci * each request will need it's own engine pointer. 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci struct sdma_engine *sde; 1818c2ecf20Sopenharmony_ci struct sdma_req_info info; 1828c2ecf20Sopenharmony_ci /* TID array values copied from the tid_iov vector */ 1838c2ecf20Sopenharmony_ci u32 *tids; 1848c2ecf20Sopenharmony_ci /* total length of the data in the request */ 1858c2ecf20Sopenharmony_ci u32 data_len; 1868c2ecf20Sopenharmony_ci /* number of elements copied to the tids array */ 1878c2ecf20Sopenharmony_ci u16 n_tids; 1888c2ecf20Sopenharmony_ci /* 1898c2ecf20Sopenharmony_ci * We copy the iovs for this request (based on 1908c2ecf20Sopenharmony_ci * info.iovcnt). These are only the data vectors 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_ci u8 data_iovs; 1938c2ecf20Sopenharmony_ci s8 ahg_idx; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci /* Writeable fields shared with interrupt */ 1968c2ecf20Sopenharmony_ci u16 seqcomp ____cacheline_aligned_in_smp; 1978c2ecf20Sopenharmony_ci u16 seqsubmitted; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* Send side fields */ 2008c2ecf20Sopenharmony_ci struct list_head txps ____cacheline_aligned_in_smp; 2018c2ecf20Sopenharmony_ci u16 seqnum; 2028c2ecf20Sopenharmony_ci /* 2038c2ecf20Sopenharmony_ci * KDETH.OFFSET (TID) field 2048c2ecf20Sopenharmony_ci * The offset can cover multiple packets, depending on the 2058c2ecf20Sopenharmony_ci * size of the TID entry. 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ci u32 tidoffset; 2088c2ecf20Sopenharmony_ci /* 2098c2ecf20Sopenharmony_ci * KDETH.Offset (Eager) field 2108c2ecf20Sopenharmony_ci * We need to remember the initial value so the headers 2118c2ecf20Sopenharmony_ci * can be updated properly. 2128c2ecf20Sopenharmony_ci */ 2138c2ecf20Sopenharmony_ci u32 koffset; 2148c2ecf20Sopenharmony_ci u32 sent; 2158c2ecf20Sopenharmony_ci /* TID index copied from the tid_iov vector */ 2168c2ecf20Sopenharmony_ci u16 tididx; 2178c2ecf20Sopenharmony_ci /* progress index moving along the iovs array */ 2188c2ecf20Sopenharmony_ci u8 iov_idx; 2198c2ecf20Sopenharmony_ci u8 has_error; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci struct user_sdma_iovec iovs[MAX_VECTORS_PER_REQ]; 2228c2ecf20Sopenharmony_ci} ____cacheline_aligned_in_smp; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci/* 2258c2ecf20Sopenharmony_ci * A single txreq could span up to 3 physical pages when the MTU 2268c2ecf20Sopenharmony_ci * is sufficiently large (> 4K). Each of the IOV pointers also 2278c2ecf20Sopenharmony_ci * needs it's own set of flags so the vector has been handled 2288c2ecf20Sopenharmony_ci * independently of each other. 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_cistruct user_sdma_txreq { 2318c2ecf20Sopenharmony_ci /* Packet header for the txreq */ 2328c2ecf20Sopenharmony_ci struct hfi1_pkt_header hdr; 2338c2ecf20Sopenharmony_ci struct sdma_txreq txreq; 2348c2ecf20Sopenharmony_ci struct list_head list; 2358c2ecf20Sopenharmony_ci struct user_sdma_request *req; 2368c2ecf20Sopenharmony_ci u16 flags; 2378c2ecf20Sopenharmony_ci u16 seqnum; 2388c2ecf20Sopenharmony_ci}; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ciint hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, 2418c2ecf20Sopenharmony_ci struct hfi1_filedata *fd); 2428c2ecf20Sopenharmony_ciint hfi1_user_sdma_free_queues(struct hfi1_filedata *fd, 2438c2ecf20Sopenharmony_ci struct hfi1_ctxtdata *uctxt); 2448c2ecf20Sopenharmony_ciint hfi1_user_sdma_process_request(struct hfi1_filedata *fd, 2458c2ecf20Sopenharmony_ci struct iovec *iovec, unsigned long dim, 2468c2ecf20Sopenharmony_ci unsigned long *count); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistatic inline struct mm_struct *mm_from_sdma_node(struct sdma_mmu_node *node) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci return node->rb.handler->mn.mm; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci#endif /* _HFI1_USER_SDMA_H */ 254