1*4882a593Smuzhiyun #ifndef _HFI1_SDMA_H
2*4882a593Smuzhiyun #define _HFI1_SDMA_H
3*4882a593Smuzhiyun /*
4*4882a593Smuzhiyun * Copyright(c) 2015 - 2018 Intel Corporation.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This file is provided under a dual BSD/GPLv2 license. When using or
7*4882a593Smuzhiyun * redistributing this file, you may do so under either license.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * GPL LICENSE SUMMARY
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
12*4882a593Smuzhiyun * it under the terms of version 2 of the GNU General Public License as
13*4882a593Smuzhiyun * published by the Free Software Foundation.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful, but
16*4882a593Smuzhiyun * WITHOUT ANY WARRANTY; without even the implied warranty of
17*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18*4882a593Smuzhiyun * General Public License for more details.
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * BSD LICENSE
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without
23*4882a593Smuzhiyun * modification, are permitted provided that the following conditions
24*4882a593Smuzhiyun * are met:
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * - Redistributions of source code must retain the above copyright
27*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer.
28*4882a593Smuzhiyun * - Redistributions in binary form must reproduce the above copyright
29*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in
30*4882a593Smuzhiyun * the documentation and/or other materials provided with the
31*4882a593Smuzhiyun * distribution.
32*4882a593Smuzhiyun * - Neither the name of Intel Corporation nor the names of its
33*4882a593Smuzhiyun * contributors may be used to endorse or promote products derived
34*4882a593Smuzhiyun * from this software without specific prior written permission.
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37*4882a593Smuzhiyun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38*4882a593Smuzhiyun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39*4882a593Smuzhiyun * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40*4882a593Smuzhiyun * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41*4882a593Smuzhiyun * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42*4882a593Smuzhiyun * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43*4882a593Smuzhiyun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44*4882a593Smuzhiyun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45*4882a593Smuzhiyun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46*4882a593Smuzhiyun * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun */
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #include <linux/types.h>
51*4882a593Smuzhiyun #include <linux/list.h>
52*4882a593Smuzhiyun #include <asm/byteorder.h>
53*4882a593Smuzhiyun #include <linux/workqueue.h>
54*4882a593Smuzhiyun #include <linux/rculist.h>
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #include "hfi.h"
57*4882a593Smuzhiyun #include "verbs.h"
58*4882a593Smuzhiyun #include "sdma_txreq.h"
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* Hardware limit */
61*4882a593Smuzhiyun #define MAX_DESC 64
62*4882a593Smuzhiyun /* Hardware limit for SDMA packet size */
63*4882a593Smuzhiyun #define MAX_SDMA_PKT_SIZE ((16 * 1024) - 1)
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #define SDMA_MAP_NONE 0
66*4882a593Smuzhiyun #define SDMA_MAP_SINGLE 1
67*4882a593Smuzhiyun #define SDMA_MAP_PAGE 2
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define SDMA_AHG_VALUE_MASK 0xffff
70*4882a593Smuzhiyun #define SDMA_AHG_VALUE_SHIFT 0
71*4882a593Smuzhiyun #define SDMA_AHG_INDEX_MASK 0xf
72*4882a593Smuzhiyun #define SDMA_AHG_INDEX_SHIFT 16
73*4882a593Smuzhiyun #define SDMA_AHG_FIELD_LEN_MASK 0xf
74*4882a593Smuzhiyun #define SDMA_AHG_FIELD_LEN_SHIFT 20
75*4882a593Smuzhiyun #define SDMA_AHG_FIELD_START_MASK 0x1f
76*4882a593Smuzhiyun #define SDMA_AHG_FIELD_START_SHIFT 24
77*4882a593Smuzhiyun #define SDMA_AHG_UPDATE_ENABLE_MASK 0x1
78*4882a593Smuzhiyun #define SDMA_AHG_UPDATE_ENABLE_SHIFT 31
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /* AHG modes */
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /*
83*4882a593Smuzhiyun * Be aware the ordering and values
84*4882a593Smuzhiyun * for SDMA_AHG_APPLY_UPDATE[123]
85*4882a593Smuzhiyun * are assumed in generating a skip
86*4882a593Smuzhiyun * count in submit_tx() in sdma.c
87*4882a593Smuzhiyun */
88*4882a593Smuzhiyun #define SDMA_AHG_NO_AHG 0
89*4882a593Smuzhiyun #define SDMA_AHG_COPY 1
90*4882a593Smuzhiyun #define SDMA_AHG_APPLY_UPDATE1 2
91*4882a593Smuzhiyun #define SDMA_AHG_APPLY_UPDATE2 3
92*4882a593Smuzhiyun #define SDMA_AHG_APPLY_UPDATE3 4
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /*
95*4882a593Smuzhiyun * Bits defined in the send DMA descriptor.
96*4882a593Smuzhiyun */
97*4882a593Smuzhiyun #define SDMA_DESC0_FIRST_DESC_FLAG BIT_ULL(63)
98*4882a593Smuzhiyun #define SDMA_DESC0_LAST_DESC_FLAG BIT_ULL(62)
99*4882a593Smuzhiyun #define SDMA_DESC0_BYTE_COUNT_SHIFT 48
100*4882a593Smuzhiyun #define SDMA_DESC0_BYTE_COUNT_WIDTH 14
101*4882a593Smuzhiyun #define SDMA_DESC0_BYTE_COUNT_MASK \
102*4882a593Smuzhiyun ((1ULL << SDMA_DESC0_BYTE_COUNT_WIDTH) - 1)
103*4882a593Smuzhiyun #define SDMA_DESC0_BYTE_COUNT_SMASK \
104*4882a593Smuzhiyun (SDMA_DESC0_BYTE_COUNT_MASK << SDMA_DESC0_BYTE_COUNT_SHIFT)
105*4882a593Smuzhiyun #define SDMA_DESC0_PHY_ADDR_SHIFT 0
106*4882a593Smuzhiyun #define SDMA_DESC0_PHY_ADDR_WIDTH 48
107*4882a593Smuzhiyun #define SDMA_DESC0_PHY_ADDR_MASK \
108*4882a593Smuzhiyun ((1ULL << SDMA_DESC0_PHY_ADDR_WIDTH) - 1)
109*4882a593Smuzhiyun #define SDMA_DESC0_PHY_ADDR_SMASK \
110*4882a593Smuzhiyun (SDMA_DESC0_PHY_ADDR_MASK << SDMA_DESC0_PHY_ADDR_SHIFT)
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_UPDATE1_SHIFT 32
113*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_UPDATE1_WIDTH 32
114*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_UPDATE1_MASK \
115*4882a593Smuzhiyun ((1ULL << SDMA_DESC1_HEADER_UPDATE1_WIDTH) - 1)
116*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_UPDATE1_SMASK \
117*4882a593Smuzhiyun (SDMA_DESC1_HEADER_UPDATE1_MASK << SDMA_DESC1_HEADER_UPDATE1_SHIFT)
118*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_MODE_SHIFT 13
119*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_MODE_WIDTH 3
120*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_MODE_MASK \
121*4882a593Smuzhiyun ((1ULL << SDMA_DESC1_HEADER_MODE_WIDTH) - 1)
122*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_MODE_SMASK \
123*4882a593Smuzhiyun (SDMA_DESC1_HEADER_MODE_MASK << SDMA_DESC1_HEADER_MODE_SHIFT)
124*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_INDEX_SHIFT 8
125*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_INDEX_WIDTH 5
126*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_INDEX_MASK \
127*4882a593Smuzhiyun ((1ULL << SDMA_DESC1_HEADER_INDEX_WIDTH) - 1)
128*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_INDEX_SMASK \
129*4882a593Smuzhiyun (SDMA_DESC1_HEADER_INDEX_MASK << SDMA_DESC1_HEADER_INDEX_SHIFT)
130*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_DWS_SHIFT 4
131*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_DWS_WIDTH 4
132*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_DWS_MASK \
133*4882a593Smuzhiyun ((1ULL << SDMA_DESC1_HEADER_DWS_WIDTH) - 1)
134*4882a593Smuzhiyun #define SDMA_DESC1_HEADER_DWS_SMASK \
135*4882a593Smuzhiyun (SDMA_DESC1_HEADER_DWS_MASK << SDMA_DESC1_HEADER_DWS_SHIFT)
136*4882a593Smuzhiyun #define SDMA_DESC1_GENERATION_SHIFT 2
137*4882a593Smuzhiyun #define SDMA_DESC1_GENERATION_WIDTH 2
138*4882a593Smuzhiyun #define SDMA_DESC1_GENERATION_MASK \
139*4882a593Smuzhiyun ((1ULL << SDMA_DESC1_GENERATION_WIDTH) - 1)
140*4882a593Smuzhiyun #define SDMA_DESC1_GENERATION_SMASK \
141*4882a593Smuzhiyun (SDMA_DESC1_GENERATION_MASK << SDMA_DESC1_GENERATION_SHIFT)
142*4882a593Smuzhiyun #define SDMA_DESC1_INT_REQ_FLAG BIT_ULL(1)
143*4882a593Smuzhiyun #define SDMA_DESC1_HEAD_TO_HOST_FLAG BIT_ULL(0)
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun enum sdma_states {
146*4882a593Smuzhiyun sdma_state_s00_hw_down,
147*4882a593Smuzhiyun sdma_state_s10_hw_start_up_halt_wait,
148*4882a593Smuzhiyun sdma_state_s15_hw_start_up_clean_wait,
149*4882a593Smuzhiyun sdma_state_s20_idle,
150*4882a593Smuzhiyun sdma_state_s30_sw_clean_up_wait,
151*4882a593Smuzhiyun sdma_state_s40_hw_clean_up_wait,
152*4882a593Smuzhiyun sdma_state_s50_hw_halt_wait,
153*4882a593Smuzhiyun sdma_state_s60_idle_halt_wait,
154*4882a593Smuzhiyun sdma_state_s80_hw_freeze,
155*4882a593Smuzhiyun sdma_state_s82_freeze_sw_clean,
156*4882a593Smuzhiyun sdma_state_s99_running,
157*4882a593Smuzhiyun };
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun enum sdma_events {
160*4882a593Smuzhiyun sdma_event_e00_go_hw_down,
161*4882a593Smuzhiyun sdma_event_e10_go_hw_start,
162*4882a593Smuzhiyun sdma_event_e15_hw_halt_done,
163*4882a593Smuzhiyun sdma_event_e25_hw_clean_up_done,
164*4882a593Smuzhiyun sdma_event_e30_go_running,
165*4882a593Smuzhiyun sdma_event_e40_sw_cleaned,
166*4882a593Smuzhiyun sdma_event_e50_hw_cleaned,
167*4882a593Smuzhiyun sdma_event_e60_hw_halted,
168*4882a593Smuzhiyun sdma_event_e70_go_idle,
169*4882a593Smuzhiyun sdma_event_e80_hw_freeze,
170*4882a593Smuzhiyun sdma_event_e81_hw_frozen,
171*4882a593Smuzhiyun sdma_event_e82_hw_unfreeze,
172*4882a593Smuzhiyun sdma_event_e85_link_down,
173*4882a593Smuzhiyun sdma_event_e90_sw_halted,
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun struct sdma_set_state_action {
177*4882a593Smuzhiyun unsigned op_enable:1;
178*4882a593Smuzhiyun unsigned op_intenable:1;
179*4882a593Smuzhiyun unsigned op_halt:1;
180*4882a593Smuzhiyun unsigned op_cleanup:1;
181*4882a593Smuzhiyun unsigned go_s99_running_tofalse:1;
182*4882a593Smuzhiyun unsigned go_s99_running_totrue:1;
183*4882a593Smuzhiyun };
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun struct sdma_state {
186*4882a593Smuzhiyun struct kref kref;
187*4882a593Smuzhiyun struct completion comp;
188*4882a593Smuzhiyun enum sdma_states current_state;
189*4882a593Smuzhiyun unsigned current_op;
190*4882a593Smuzhiyun unsigned go_s99_running;
191*4882a593Smuzhiyun /* debugging/development */
192*4882a593Smuzhiyun enum sdma_states previous_state;
193*4882a593Smuzhiyun unsigned previous_op;
194*4882a593Smuzhiyun enum sdma_events last_event;
195*4882a593Smuzhiyun };
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /**
198*4882a593Smuzhiyun * DOC: sdma exported routines
199*4882a593Smuzhiyun *
200*4882a593Smuzhiyun * These sdma routines fit into three categories:
201*4882a593Smuzhiyun * - The SDMA API for building and submitting packets
202*4882a593Smuzhiyun * to the ring
203*4882a593Smuzhiyun *
204*4882a593Smuzhiyun * - Initialization and tear down routines to buildup
205*4882a593Smuzhiyun * and tear down SDMA
206*4882a593Smuzhiyun *
207*4882a593Smuzhiyun * - ISR entrances to handle interrupts, state changes
208*4882a593Smuzhiyun * and errors
209*4882a593Smuzhiyun */
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /**
212*4882a593Smuzhiyun * DOC: sdma PSM/verbs API
213*4882a593Smuzhiyun *
214*4882a593Smuzhiyun * The sdma API is designed to be used by both PSM
215*4882a593Smuzhiyun * and verbs to supply packets to the SDMA ring.
216*4882a593Smuzhiyun *
217*4882a593Smuzhiyun * The usage of the API is as follows:
218*4882a593Smuzhiyun *
219*4882a593Smuzhiyun * Embed a struct iowait in the QP or
220*4882a593Smuzhiyun * PQ. The iowait should be initialized with a
221*4882a593Smuzhiyun * call to iowait_init().
222*4882a593Smuzhiyun *
223*4882a593Smuzhiyun * The user of the API should create an allocation method
224*4882a593Smuzhiyun * for their version of the txreq. slabs, pre-allocated lists,
225*4882a593Smuzhiyun * and dma pools can be used. Once the user's overload of
226*4882a593Smuzhiyun * the sdma_txreq has been allocated, the sdma_txreq member
227*4882a593Smuzhiyun * must be initialized with sdma_txinit() or sdma_txinit_ahg().
228*4882a593Smuzhiyun *
229*4882a593Smuzhiyun * The txreq must be declared with the sdma_txreq first.
230*4882a593Smuzhiyun *
231*4882a593Smuzhiyun * The tx request, once initialized, is manipulated with calls to
232*4882a593Smuzhiyun * sdma_txadd_daddr(), sdma_txadd_page(), or sdma_txadd_kvaddr()
233*4882a593Smuzhiyun * for each disjoint memory location. It is the user's responsibility
234*4882a593Smuzhiyun * to understand the packet boundaries and page boundaries to do the
235*4882a593Smuzhiyun * appropriate number of sdma_txadd_* calls.. The user
236*4882a593Smuzhiyun * must be prepared to deal with failures from these routines due to
237*4882a593Smuzhiyun * either memory allocation or dma_mapping failures.
238*4882a593Smuzhiyun *
239*4882a593Smuzhiyun * The mapping specifics for each memory location are recorded
240*4882a593Smuzhiyun * in the tx. Memory locations added with sdma_txadd_page()
241*4882a593Smuzhiyun * and sdma_txadd_kvaddr() are automatically mapped when added
242*4882a593Smuzhiyun * to the tx and nmapped as part of the progress processing in the
243*4882a593Smuzhiyun * SDMA interrupt handling.
244*4882a593Smuzhiyun *
245*4882a593Smuzhiyun * sdma_txadd_daddr() is used to add an dma_addr_t memory to the
246*4882a593Smuzhiyun * tx. An example of a use case would be a pre-allocated
247*4882a593Smuzhiyun * set of headers allocated via dma_pool_alloc() or
248*4882a593Smuzhiyun * dma_alloc_coherent(). For these memory locations, it
249*4882a593Smuzhiyun * is the responsibility of the user to handle that unmapping.
250*4882a593Smuzhiyun * (This would usually be at an unload or job termination.)
251*4882a593Smuzhiyun *
252*4882a593Smuzhiyun * The routine sdma_send_txreq() is used to submit
253*4882a593Smuzhiyun * a tx to the ring after the appropriate number of
254*4882a593Smuzhiyun * sdma_txadd_* have been done.
255*4882a593Smuzhiyun *
256*4882a593Smuzhiyun * If it is desired to send a burst of sdma_txreqs, sdma_send_txlist()
257*4882a593Smuzhiyun * can be used to submit a list of packets.
258*4882a593Smuzhiyun *
259*4882a593Smuzhiyun * The user is free to use the link overhead in the struct sdma_txreq as
260*4882a593Smuzhiyun * long as the tx isn't in flight.
261*4882a593Smuzhiyun *
262*4882a593Smuzhiyun * The extreme degenerate case of the number of descriptors
263*4882a593Smuzhiyun * exceeding the ring size is automatically handled as
264*4882a593Smuzhiyun * memory locations are added. An overflow of the descriptor
265*4882a593Smuzhiyun * array that is part of the sdma_txreq is also automatically
266*4882a593Smuzhiyun * handled.
267*4882a593Smuzhiyun *
268*4882a593Smuzhiyun */
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /**
271*4882a593Smuzhiyun * DOC: Infrastructure calls
272*4882a593Smuzhiyun *
273*4882a593Smuzhiyun * sdma_init() is used to initialize data structures and
274*4882a593Smuzhiyun * CSRs for the desired number of SDMA engines.
275*4882a593Smuzhiyun *
276*4882a593Smuzhiyun * sdma_start() is used to kick the SDMA engines initialized
277*4882a593Smuzhiyun * with sdma_init(). Interrupts must be enabled at this
278*4882a593Smuzhiyun * point since aspects of the state machine are interrupt
279*4882a593Smuzhiyun * driven.
280*4882a593Smuzhiyun *
281*4882a593Smuzhiyun * sdma_engine_error() and sdma_engine_interrupt() are
282*4882a593Smuzhiyun * entrances for interrupts.
283*4882a593Smuzhiyun *
284*4882a593Smuzhiyun * sdma_map_init() is for the management of the mapping
285*4882a593Smuzhiyun * table when the number of vls is changed.
286*4882a593Smuzhiyun *
287*4882a593Smuzhiyun */
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /*
290*4882a593Smuzhiyun * struct hw_sdma_desc - raw 128 bit SDMA descriptor
291*4882a593Smuzhiyun *
292*4882a593Smuzhiyun * This is the raw descriptor in the SDMA ring
293*4882a593Smuzhiyun */
294*4882a593Smuzhiyun struct hw_sdma_desc {
295*4882a593Smuzhiyun /* private: don't use directly */
296*4882a593Smuzhiyun __le64 qw[2];
297*4882a593Smuzhiyun };
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun /**
300*4882a593Smuzhiyun * struct sdma_engine - Data pertaining to each SDMA engine.
301*4882a593Smuzhiyun * @dd: a back-pointer to the device data
302*4882a593Smuzhiyun * @ppd: per port back-pointer
303*4882a593Smuzhiyun * @imask: mask for irq manipulation
304*4882a593Smuzhiyun * @idle_mask: mask for determining if an interrupt is due to sdma_idle
305*4882a593Smuzhiyun *
306*4882a593Smuzhiyun * This structure has the state for each sdma_engine.
307*4882a593Smuzhiyun *
308*4882a593Smuzhiyun * Accessing to non public fields are not supported
309*4882a593Smuzhiyun * since the private members are subject to change.
310*4882a593Smuzhiyun */
311*4882a593Smuzhiyun struct sdma_engine {
312*4882a593Smuzhiyun /* read mostly */
313*4882a593Smuzhiyun struct hfi1_devdata *dd;
314*4882a593Smuzhiyun struct hfi1_pportdata *ppd;
315*4882a593Smuzhiyun /* private: */
316*4882a593Smuzhiyun void __iomem *tail_csr;
317*4882a593Smuzhiyun u64 imask; /* clear interrupt mask */
318*4882a593Smuzhiyun u64 idle_mask;
319*4882a593Smuzhiyun u64 progress_mask;
320*4882a593Smuzhiyun u64 int_mask;
321*4882a593Smuzhiyun /* private: */
322*4882a593Smuzhiyun volatile __le64 *head_dma; /* DMA'ed by chip */
323*4882a593Smuzhiyun /* private: */
324*4882a593Smuzhiyun dma_addr_t head_phys;
325*4882a593Smuzhiyun /* private: */
326*4882a593Smuzhiyun struct hw_sdma_desc *descq;
327*4882a593Smuzhiyun /* private: */
328*4882a593Smuzhiyun unsigned descq_full_count;
329*4882a593Smuzhiyun struct sdma_txreq **tx_ring;
330*4882a593Smuzhiyun /* private: */
331*4882a593Smuzhiyun dma_addr_t descq_phys;
332*4882a593Smuzhiyun /* private */
333*4882a593Smuzhiyun u32 sdma_mask;
334*4882a593Smuzhiyun /* private */
335*4882a593Smuzhiyun struct sdma_state state;
336*4882a593Smuzhiyun /* private */
337*4882a593Smuzhiyun int cpu;
338*4882a593Smuzhiyun /* private: */
339*4882a593Smuzhiyun u8 sdma_shift;
340*4882a593Smuzhiyun /* private: */
341*4882a593Smuzhiyun u8 this_idx; /* zero relative engine */
342*4882a593Smuzhiyun /* protect changes to senddmactrl shadow */
343*4882a593Smuzhiyun spinlock_t senddmactrl_lock;
344*4882a593Smuzhiyun /* private: */
345*4882a593Smuzhiyun u64 p_senddmactrl; /* shadow per-engine SendDmaCtrl */
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun /* read/write using tail_lock */
348*4882a593Smuzhiyun spinlock_t tail_lock ____cacheline_aligned_in_smp;
349*4882a593Smuzhiyun #ifdef CONFIG_HFI1_DEBUG_SDMA_ORDER
350*4882a593Smuzhiyun /* private: */
351*4882a593Smuzhiyun u64 tail_sn;
352*4882a593Smuzhiyun #endif
353*4882a593Smuzhiyun /* private: */
354*4882a593Smuzhiyun u32 descq_tail;
355*4882a593Smuzhiyun /* private: */
356*4882a593Smuzhiyun unsigned long ahg_bits;
357*4882a593Smuzhiyun /* private: */
358*4882a593Smuzhiyun u16 desc_avail;
359*4882a593Smuzhiyun /* private: */
360*4882a593Smuzhiyun u16 tx_tail;
361*4882a593Smuzhiyun /* private: */
362*4882a593Smuzhiyun u16 descq_cnt;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* read/write using head_lock */
365*4882a593Smuzhiyun /* private: */
366*4882a593Smuzhiyun seqlock_t head_lock ____cacheline_aligned_in_smp;
367*4882a593Smuzhiyun #ifdef CONFIG_HFI1_DEBUG_SDMA_ORDER
368*4882a593Smuzhiyun /* private: */
369*4882a593Smuzhiyun u64 head_sn;
370*4882a593Smuzhiyun #endif
371*4882a593Smuzhiyun /* private: */
372*4882a593Smuzhiyun u32 descq_head;
373*4882a593Smuzhiyun /* private: */
374*4882a593Smuzhiyun u16 tx_head;
375*4882a593Smuzhiyun /* private: */
376*4882a593Smuzhiyun u64 last_status;
377*4882a593Smuzhiyun /* private */
378*4882a593Smuzhiyun u64 err_cnt;
379*4882a593Smuzhiyun /* private */
380*4882a593Smuzhiyun u64 sdma_int_cnt;
381*4882a593Smuzhiyun u64 idle_int_cnt;
382*4882a593Smuzhiyun u64 progress_int_cnt;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun /* private: */
385*4882a593Smuzhiyun seqlock_t waitlock;
386*4882a593Smuzhiyun struct list_head dmawait;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun /* CONFIG SDMA for now, just blindly duplicate */
389*4882a593Smuzhiyun /* private: */
390*4882a593Smuzhiyun struct tasklet_struct sdma_hw_clean_up_task
391*4882a593Smuzhiyun ____cacheline_aligned_in_smp;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun /* private: */
394*4882a593Smuzhiyun struct tasklet_struct sdma_sw_clean_up_task
395*4882a593Smuzhiyun ____cacheline_aligned_in_smp;
396*4882a593Smuzhiyun /* private: */
397*4882a593Smuzhiyun struct work_struct err_halt_worker;
398*4882a593Smuzhiyun /* private */
399*4882a593Smuzhiyun struct timer_list err_progress_check_timer;
400*4882a593Smuzhiyun u32 progress_check_head;
401*4882a593Smuzhiyun /* private: */
402*4882a593Smuzhiyun struct work_struct flush_worker;
403*4882a593Smuzhiyun /* protect flush list */
404*4882a593Smuzhiyun spinlock_t flushlist_lock;
405*4882a593Smuzhiyun /* private: */
406*4882a593Smuzhiyun struct list_head flushlist;
407*4882a593Smuzhiyun struct cpumask cpu_mask;
408*4882a593Smuzhiyun struct kobject kobj;
409*4882a593Smuzhiyun u32 msix_intr;
410*4882a593Smuzhiyun };
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun int sdma_init(struct hfi1_devdata *dd, u8 port);
413*4882a593Smuzhiyun void sdma_start(struct hfi1_devdata *dd);
414*4882a593Smuzhiyun void sdma_exit(struct hfi1_devdata *dd);
415*4882a593Smuzhiyun void sdma_clean(struct hfi1_devdata *dd, size_t num_engines);
416*4882a593Smuzhiyun void sdma_all_running(struct hfi1_devdata *dd);
417*4882a593Smuzhiyun void sdma_all_idle(struct hfi1_devdata *dd);
418*4882a593Smuzhiyun void sdma_freeze_notify(struct hfi1_devdata *dd, int go_idle);
419*4882a593Smuzhiyun void sdma_freeze(struct hfi1_devdata *dd);
420*4882a593Smuzhiyun void sdma_unfreeze(struct hfi1_devdata *dd);
421*4882a593Smuzhiyun void sdma_wait(struct hfi1_devdata *dd);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /**
424*4882a593Smuzhiyun * sdma_empty() - idle engine test
425*4882a593Smuzhiyun * @engine: sdma engine
426*4882a593Smuzhiyun *
427*4882a593Smuzhiyun * Currently used by verbs as a latency optimization.
428*4882a593Smuzhiyun *
429*4882a593Smuzhiyun * Return:
430*4882a593Smuzhiyun * 1 - empty, 0 - non-empty
431*4882a593Smuzhiyun */
sdma_empty(struct sdma_engine * sde)432*4882a593Smuzhiyun static inline int sdma_empty(struct sdma_engine *sde)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun return sde->descq_tail == sde->descq_head;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
sdma_descq_freecnt(struct sdma_engine * sde)437*4882a593Smuzhiyun static inline u16 sdma_descq_freecnt(struct sdma_engine *sde)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun return sde->descq_cnt -
440*4882a593Smuzhiyun (sde->descq_tail -
441*4882a593Smuzhiyun READ_ONCE(sde->descq_head)) - 1;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
sdma_descq_inprocess(struct sdma_engine * sde)444*4882a593Smuzhiyun static inline u16 sdma_descq_inprocess(struct sdma_engine *sde)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun return sde->descq_cnt - sdma_descq_freecnt(sde);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun /*
450*4882a593Smuzhiyun * Either head_lock or tail lock required to see
451*4882a593Smuzhiyun * a steady state.
452*4882a593Smuzhiyun */
__sdma_running(struct sdma_engine * engine)453*4882a593Smuzhiyun static inline int __sdma_running(struct sdma_engine *engine)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun return engine->state.current_state == sdma_state_s99_running;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun /**
459*4882a593Smuzhiyun * sdma_running() - state suitability test
460*4882a593Smuzhiyun * @engine: sdma engine
461*4882a593Smuzhiyun *
462*4882a593Smuzhiyun * sdma_running probes the internal state to determine if it is suitable
463*4882a593Smuzhiyun * for submitting packets.
464*4882a593Smuzhiyun *
465*4882a593Smuzhiyun * Return:
466*4882a593Smuzhiyun * 1 - ok to submit, 0 - not ok to submit
467*4882a593Smuzhiyun *
468*4882a593Smuzhiyun */
sdma_running(struct sdma_engine * engine)469*4882a593Smuzhiyun static inline int sdma_running(struct sdma_engine *engine)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun unsigned long flags;
472*4882a593Smuzhiyun int ret;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun spin_lock_irqsave(&engine->tail_lock, flags);
475*4882a593Smuzhiyun ret = __sdma_running(engine);
476*4882a593Smuzhiyun spin_unlock_irqrestore(&engine->tail_lock, flags);
477*4882a593Smuzhiyun return ret;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun void _sdma_txreq_ahgadd(
481*4882a593Smuzhiyun struct sdma_txreq *tx,
482*4882a593Smuzhiyun u8 num_ahg,
483*4882a593Smuzhiyun u8 ahg_entry,
484*4882a593Smuzhiyun u32 *ahg,
485*4882a593Smuzhiyun u8 ahg_hlen);
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun /**
488*4882a593Smuzhiyun * sdma_txinit_ahg() - initialize an sdma_txreq struct with AHG
489*4882a593Smuzhiyun * @tx: tx request to initialize
490*4882a593Smuzhiyun * @flags: flags to key last descriptor additions
491*4882a593Smuzhiyun * @tlen: total packet length (pbc + headers + data)
492*4882a593Smuzhiyun * @ahg_entry: ahg entry to use (0 - 31)
493*4882a593Smuzhiyun * @num_ahg: ahg descriptor for first descriptor (0 - 9)
494*4882a593Smuzhiyun * @ahg: array of AHG descriptors (up to 9 entries)
495*4882a593Smuzhiyun * @ahg_hlen: number of bytes from ASIC entry to use
496*4882a593Smuzhiyun * @cb: callback
497*4882a593Smuzhiyun *
498*4882a593Smuzhiyun * The allocation of the sdma_txreq and it enclosing structure is user
499*4882a593Smuzhiyun * dependent. This routine must be called to initialize the user independent
500*4882a593Smuzhiyun * fields.
501*4882a593Smuzhiyun *
502*4882a593Smuzhiyun * The currently supported flags are SDMA_TXREQ_F_URGENT,
503*4882a593Smuzhiyun * SDMA_TXREQ_F_AHG_COPY, and SDMA_TXREQ_F_USE_AHG.
504*4882a593Smuzhiyun *
505*4882a593Smuzhiyun * SDMA_TXREQ_F_URGENT is used for latency sensitive situations where the
506*4882a593Smuzhiyun * completion is desired as soon as possible.
507*4882a593Smuzhiyun *
508*4882a593Smuzhiyun * SDMA_TXREQ_F_AHG_COPY causes the header in the first descriptor to be
509*4882a593Smuzhiyun * copied to chip entry. SDMA_TXREQ_F_USE_AHG causes the code to add in
510*4882a593Smuzhiyun * the AHG descriptors into the first 1 to 3 descriptors.
511*4882a593Smuzhiyun *
512*4882a593Smuzhiyun * Completions of submitted requests can be gotten on selected
513*4882a593Smuzhiyun * txreqs by giving a completion routine callback to sdma_txinit() or
514*4882a593Smuzhiyun * sdma_txinit_ahg(). The environment in which the callback runs
515*4882a593Smuzhiyun * can be from an ISR, a tasklet, or a thread, so no sleeping
516*4882a593Smuzhiyun * kernel routines can be used. Aspects of the sdma ring may
517*4882a593Smuzhiyun * be locked so care should be taken with locking.
518*4882a593Smuzhiyun *
519*4882a593Smuzhiyun * The callback pointer can be NULL to avoid any callback for the packet
520*4882a593Smuzhiyun * being submitted. The callback will be provided this tx, a status, and a flag.
521*4882a593Smuzhiyun *
522*4882a593Smuzhiyun * The status will be one of SDMA_TXREQ_S_OK, SDMA_TXREQ_S_SENDERROR,
523*4882a593Smuzhiyun * SDMA_TXREQ_S_ABORTED, or SDMA_TXREQ_S_SHUTDOWN.
524*4882a593Smuzhiyun *
525*4882a593Smuzhiyun * The flag, if the is the iowait had been used, indicates the iowait
526*4882a593Smuzhiyun * sdma_busy count has reached zero.
527*4882a593Smuzhiyun *
528*4882a593Smuzhiyun * user data portion of tlen should be precise. The sdma_txadd_* entrances
529*4882a593Smuzhiyun * will pad with a descriptor references 1 - 3 bytes when the number of bytes
530*4882a593Smuzhiyun * specified in tlen have been supplied to the sdma_txreq.
531*4882a593Smuzhiyun *
532*4882a593Smuzhiyun * ahg_hlen is used to determine the number of on-chip entry bytes to
533*4882a593Smuzhiyun * use as the header. This is for cases where the stored header is
534*4882a593Smuzhiyun * larger than the header to be used in a packet. This is typical
535*4882a593Smuzhiyun * for verbs where an RDMA_WRITE_FIRST is larger than the packet in
536*4882a593Smuzhiyun * and RDMA_WRITE_MIDDLE.
537*4882a593Smuzhiyun *
538*4882a593Smuzhiyun */
sdma_txinit_ahg(struct sdma_txreq * tx,u16 flags,u16 tlen,u8 ahg_entry,u8 num_ahg,u32 * ahg,u8 ahg_hlen,void (* cb)(struct sdma_txreq *,int))539*4882a593Smuzhiyun static inline int sdma_txinit_ahg(
540*4882a593Smuzhiyun struct sdma_txreq *tx,
541*4882a593Smuzhiyun u16 flags,
542*4882a593Smuzhiyun u16 tlen,
543*4882a593Smuzhiyun u8 ahg_entry,
544*4882a593Smuzhiyun u8 num_ahg,
545*4882a593Smuzhiyun u32 *ahg,
546*4882a593Smuzhiyun u8 ahg_hlen,
547*4882a593Smuzhiyun void (*cb)(struct sdma_txreq *, int))
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun if (tlen == 0)
550*4882a593Smuzhiyun return -ENODATA;
551*4882a593Smuzhiyun if (tlen > MAX_SDMA_PKT_SIZE)
552*4882a593Smuzhiyun return -EMSGSIZE;
553*4882a593Smuzhiyun tx->desc_limit = ARRAY_SIZE(tx->descs);
554*4882a593Smuzhiyun tx->descp = &tx->descs[0];
555*4882a593Smuzhiyun INIT_LIST_HEAD(&tx->list);
556*4882a593Smuzhiyun tx->num_desc = 0;
557*4882a593Smuzhiyun tx->flags = flags;
558*4882a593Smuzhiyun tx->complete = cb;
559*4882a593Smuzhiyun tx->coalesce_buf = NULL;
560*4882a593Smuzhiyun tx->wait = NULL;
561*4882a593Smuzhiyun tx->packet_len = tlen;
562*4882a593Smuzhiyun tx->tlen = tx->packet_len;
563*4882a593Smuzhiyun tx->descs[0].qw[0] = SDMA_DESC0_FIRST_DESC_FLAG;
564*4882a593Smuzhiyun tx->descs[0].qw[1] = 0;
565*4882a593Smuzhiyun if (flags & SDMA_TXREQ_F_AHG_COPY)
566*4882a593Smuzhiyun tx->descs[0].qw[1] |=
567*4882a593Smuzhiyun (((u64)ahg_entry & SDMA_DESC1_HEADER_INDEX_MASK)
568*4882a593Smuzhiyun << SDMA_DESC1_HEADER_INDEX_SHIFT) |
569*4882a593Smuzhiyun (((u64)SDMA_AHG_COPY & SDMA_DESC1_HEADER_MODE_MASK)
570*4882a593Smuzhiyun << SDMA_DESC1_HEADER_MODE_SHIFT);
571*4882a593Smuzhiyun else if (flags & SDMA_TXREQ_F_USE_AHG && num_ahg)
572*4882a593Smuzhiyun _sdma_txreq_ahgadd(tx, num_ahg, ahg_entry, ahg, ahg_hlen);
573*4882a593Smuzhiyun return 0;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun /**
577*4882a593Smuzhiyun * sdma_txinit() - initialize an sdma_txreq struct (no AHG)
578*4882a593Smuzhiyun * @tx: tx request to initialize
579*4882a593Smuzhiyun * @flags: flags to key last descriptor additions
580*4882a593Smuzhiyun * @tlen: total packet length (pbc + headers + data)
581*4882a593Smuzhiyun * @cb: callback pointer
582*4882a593Smuzhiyun *
583*4882a593Smuzhiyun * The allocation of the sdma_txreq and it enclosing structure is user
584*4882a593Smuzhiyun * dependent. This routine must be called to initialize the user
585*4882a593Smuzhiyun * independent fields.
586*4882a593Smuzhiyun *
587*4882a593Smuzhiyun * The currently supported flags is SDMA_TXREQ_F_URGENT.
588*4882a593Smuzhiyun *
589*4882a593Smuzhiyun * SDMA_TXREQ_F_URGENT is used for latency sensitive situations where the
590*4882a593Smuzhiyun * completion is desired as soon as possible.
591*4882a593Smuzhiyun *
592*4882a593Smuzhiyun * Completions of submitted requests can be gotten on selected
593*4882a593Smuzhiyun * txreqs by giving a completion routine callback to sdma_txinit() or
594*4882a593Smuzhiyun * sdma_txinit_ahg(). The environment in which the callback runs
595*4882a593Smuzhiyun * can be from an ISR, a tasklet, or a thread, so no sleeping
596*4882a593Smuzhiyun * kernel routines can be used. The head size of the sdma ring may
597*4882a593Smuzhiyun * be locked so care should be taken with locking.
598*4882a593Smuzhiyun *
599*4882a593Smuzhiyun * The callback pointer can be NULL to avoid any callback for the packet
600*4882a593Smuzhiyun * being submitted.
601*4882a593Smuzhiyun *
602*4882a593Smuzhiyun * The callback, if non-NULL, will be provided this tx and a status. The
603*4882a593Smuzhiyun * status will be one of SDMA_TXREQ_S_OK, SDMA_TXREQ_S_SENDERROR,
604*4882a593Smuzhiyun * SDMA_TXREQ_S_ABORTED, or SDMA_TXREQ_S_SHUTDOWN.
605*4882a593Smuzhiyun *
606*4882a593Smuzhiyun */
sdma_txinit(struct sdma_txreq * tx,u16 flags,u16 tlen,void (* cb)(struct sdma_txreq *,int))607*4882a593Smuzhiyun static inline int sdma_txinit(
608*4882a593Smuzhiyun struct sdma_txreq *tx,
609*4882a593Smuzhiyun u16 flags,
610*4882a593Smuzhiyun u16 tlen,
611*4882a593Smuzhiyun void (*cb)(struct sdma_txreq *, int))
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun return sdma_txinit_ahg(tx, flags, tlen, 0, 0, NULL, 0, cb);
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun /* helpers - don't use */
sdma_mapping_type(struct sdma_desc * d)617*4882a593Smuzhiyun static inline int sdma_mapping_type(struct sdma_desc *d)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun return (d->qw[1] & SDMA_DESC1_GENERATION_SMASK)
620*4882a593Smuzhiyun >> SDMA_DESC1_GENERATION_SHIFT;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
sdma_mapping_len(struct sdma_desc * d)623*4882a593Smuzhiyun static inline size_t sdma_mapping_len(struct sdma_desc *d)
624*4882a593Smuzhiyun {
625*4882a593Smuzhiyun return (d->qw[0] & SDMA_DESC0_BYTE_COUNT_SMASK)
626*4882a593Smuzhiyun >> SDMA_DESC0_BYTE_COUNT_SHIFT;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
sdma_mapping_addr(struct sdma_desc * d)629*4882a593Smuzhiyun static inline dma_addr_t sdma_mapping_addr(struct sdma_desc *d)
630*4882a593Smuzhiyun {
631*4882a593Smuzhiyun return (d->qw[0] & SDMA_DESC0_PHY_ADDR_SMASK)
632*4882a593Smuzhiyun >> SDMA_DESC0_PHY_ADDR_SHIFT;
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun
make_tx_sdma_desc(struct sdma_txreq * tx,int type,dma_addr_t addr,size_t len)635*4882a593Smuzhiyun static inline void make_tx_sdma_desc(
636*4882a593Smuzhiyun struct sdma_txreq *tx,
637*4882a593Smuzhiyun int type,
638*4882a593Smuzhiyun dma_addr_t addr,
639*4882a593Smuzhiyun size_t len)
640*4882a593Smuzhiyun {
641*4882a593Smuzhiyun struct sdma_desc *desc = &tx->descp[tx->num_desc];
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun if (!tx->num_desc) {
644*4882a593Smuzhiyun /* qw[0] zero; qw[1] first, ahg mode already in from init */
645*4882a593Smuzhiyun desc->qw[1] |= ((u64)type & SDMA_DESC1_GENERATION_MASK)
646*4882a593Smuzhiyun << SDMA_DESC1_GENERATION_SHIFT;
647*4882a593Smuzhiyun } else {
648*4882a593Smuzhiyun desc->qw[0] = 0;
649*4882a593Smuzhiyun desc->qw[1] = ((u64)type & SDMA_DESC1_GENERATION_MASK)
650*4882a593Smuzhiyun << SDMA_DESC1_GENERATION_SHIFT;
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun desc->qw[0] |= (((u64)addr & SDMA_DESC0_PHY_ADDR_MASK)
653*4882a593Smuzhiyun << SDMA_DESC0_PHY_ADDR_SHIFT) |
654*4882a593Smuzhiyun (((u64)len & SDMA_DESC0_BYTE_COUNT_MASK)
655*4882a593Smuzhiyun << SDMA_DESC0_BYTE_COUNT_SHIFT);
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun /* helper to extend txreq */
659*4882a593Smuzhiyun int ext_coal_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx,
660*4882a593Smuzhiyun int type, void *kvaddr, struct page *page,
661*4882a593Smuzhiyun unsigned long offset, u16 len);
662*4882a593Smuzhiyun int _pad_sdma_tx_descs(struct hfi1_devdata *, struct sdma_txreq *);
663*4882a593Smuzhiyun void __sdma_txclean(struct hfi1_devdata *, struct sdma_txreq *);
664*4882a593Smuzhiyun
sdma_txclean(struct hfi1_devdata * dd,struct sdma_txreq * tx)665*4882a593Smuzhiyun static inline void sdma_txclean(struct hfi1_devdata *dd, struct sdma_txreq *tx)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun if (tx->num_desc)
668*4882a593Smuzhiyun __sdma_txclean(dd, tx);
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun /* helpers used by public routines */
_sdma_close_tx(struct hfi1_devdata * dd,struct sdma_txreq * tx)672*4882a593Smuzhiyun static inline void _sdma_close_tx(struct hfi1_devdata *dd,
673*4882a593Smuzhiyun struct sdma_txreq *tx)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun tx->descp[tx->num_desc].qw[0] |=
676*4882a593Smuzhiyun SDMA_DESC0_LAST_DESC_FLAG;
677*4882a593Smuzhiyun tx->descp[tx->num_desc].qw[1] |=
678*4882a593Smuzhiyun dd->default_desc1;
679*4882a593Smuzhiyun if (tx->flags & SDMA_TXREQ_F_URGENT)
680*4882a593Smuzhiyun tx->descp[tx->num_desc].qw[1] |=
681*4882a593Smuzhiyun (SDMA_DESC1_HEAD_TO_HOST_FLAG |
682*4882a593Smuzhiyun SDMA_DESC1_INT_REQ_FLAG);
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
_sdma_txadd_daddr(struct hfi1_devdata * dd,int type,struct sdma_txreq * tx,dma_addr_t addr,u16 len)685*4882a593Smuzhiyun static inline int _sdma_txadd_daddr(
686*4882a593Smuzhiyun struct hfi1_devdata *dd,
687*4882a593Smuzhiyun int type,
688*4882a593Smuzhiyun struct sdma_txreq *tx,
689*4882a593Smuzhiyun dma_addr_t addr,
690*4882a593Smuzhiyun u16 len)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun int rval = 0;
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun make_tx_sdma_desc(
695*4882a593Smuzhiyun tx,
696*4882a593Smuzhiyun type,
697*4882a593Smuzhiyun addr, len);
698*4882a593Smuzhiyun WARN_ON(len > tx->tlen);
699*4882a593Smuzhiyun tx->tlen -= len;
700*4882a593Smuzhiyun /* special cases for last */
701*4882a593Smuzhiyun if (!tx->tlen) {
702*4882a593Smuzhiyun if (tx->packet_len & (sizeof(u32) - 1)) {
703*4882a593Smuzhiyun rval = _pad_sdma_tx_descs(dd, tx);
704*4882a593Smuzhiyun if (rval)
705*4882a593Smuzhiyun return rval;
706*4882a593Smuzhiyun } else {
707*4882a593Smuzhiyun _sdma_close_tx(dd, tx);
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun tx->num_desc++;
711*4882a593Smuzhiyun return rval;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun /**
715*4882a593Smuzhiyun * sdma_txadd_page() - add a page to the sdma_txreq
716*4882a593Smuzhiyun * @dd: the device to use for mapping
717*4882a593Smuzhiyun * @tx: tx request to which the page is added
718*4882a593Smuzhiyun * @page: page to map
719*4882a593Smuzhiyun * @offset: offset within the page
720*4882a593Smuzhiyun * @len: length in bytes
721*4882a593Smuzhiyun *
722*4882a593Smuzhiyun * This is used to add a page/offset/length descriptor.
723*4882a593Smuzhiyun *
724*4882a593Smuzhiyun * The mapping/unmapping of the page/offset/len is automatically handled.
725*4882a593Smuzhiyun *
726*4882a593Smuzhiyun * Return:
727*4882a593Smuzhiyun * 0 - success, -ENOSPC - mapping fail, -ENOMEM - couldn't
728*4882a593Smuzhiyun * extend/coalesce descriptor array
729*4882a593Smuzhiyun */
sdma_txadd_page(struct hfi1_devdata * dd,struct sdma_txreq * tx,struct page * page,unsigned long offset,u16 len)730*4882a593Smuzhiyun static inline int sdma_txadd_page(
731*4882a593Smuzhiyun struct hfi1_devdata *dd,
732*4882a593Smuzhiyun struct sdma_txreq *tx,
733*4882a593Smuzhiyun struct page *page,
734*4882a593Smuzhiyun unsigned long offset,
735*4882a593Smuzhiyun u16 len)
736*4882a593Smuzhiyun {
737*4882a593Smuzhiyun dma_addr_t addr;
738*4882a593Smuzhiyun int rval;
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun if ((unlikely(tx->num_desc == tx->desc_limit))) {
741*4882a593Smuzhiyun rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_PAGE,
742*4882a593Smuzhiyun NULL, page, offset, len);
743*4882a593Smuzhiyun if (rval <= 0)
744*4882a593Smuzhiyun return rval;
745*4882a593Smuzhiyun }
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun addr = dma_map_page(
748*4882a593Smuzhiyun &dd->pcidev->dev,
749*4882a593Smuzhiyun page,
750*4882a593Smuzhiyun offset,
751*4882a593Smuzhiyun len,
752*4882a593Smuzhiyun DMA_TO_DEVICE);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) {
755*4882a593Smuzhiyun __sdma_txclean(dd, tx);
756*4882a593Smuzhiyun return -ENOSPC;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun return _sdma_txadd_daddr(
760*4882a593Smuzhiyun dd, SDMA_MAP_PAGE, tx, addr, len);
761*4882a593Smuzhiyun }
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun /**
764*4882a593Smuzhiyun * sdma_txadd_daddr() - add a dma address to the sdma_txreq
765*4882a593Smuzhiyun * @dd: the device to use for mapping
766*4882a593Smuzhiyun * @tx: sdma_txreq to which the page is added
767*4882a593Smuzhiyun * @addr: dma address mapped by caller
768*4882a593Smuzhiyun * @len: length in bytes
769*4882a593Smuzhiyun *
770*4882a593Smuzhiyun * This is used to add a descriptor for memory that is already dma mapped.
771*4882a593Smuzhiyun *
772*4882a593Smuzhiyun * In this case, there is no unmapping as part of the progress processing for
773*4882a593Smuzhiyun * this memory location.
774*4882a593Smuzhiyun *
775*4882a593Smuzhiyun * Return:
776*4882a593Smuzhiyun * 0 - success, -ENOMEM - couldn't extend descriptor array
777*4882a593Smuzhiyun */
778*4882a593Smuzhiyun
sdma_txadd_daddr(struct hfi1_devdata * dd,struct sdma_txreq * tx,dma_addr_t addr,u16 len)779*4882a593Smuzhiyun static inline int sdma_txadd_daddr(
780*4882a593Smuzhiyun struct hfi1_devdata *dd,
781*4882a593Smuzhiyun struct sdma_txreq *tx,
782*4882a593Smuzhiyun dma_addr_t addr,
783*4882a593Smuzhiyun u16 len)
784*4882a593Smuzhiyun {
785*4882a593Smuzhiyun int rval;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun if ((unlikely(tx->num_desc == tx->desc_limit))) {
788*4882a593Smuzhiyun rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_NONE,
789*4882a593Smuzhiyun NULL, NULL, 0, 0);
790*4882a593Smuzhiyun if (rval <= 0)
791*4882a593Smuzhiyun return rval;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, tx, addr, len);
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun /**
798*4882a593Smuzhiyun * sdma_txadd_kvaddr() - add a kernel virtual address to sdma_txreq
799*4882a593Smuzhiyun * @dd: the device to use for mapping
800*4882a593Smuzhiyun * @tx: sdma_txreq to which the page is added
801*4882a593Smuzhiyun * @kvaddr: the kernel virtual address
802*4882a593Smuzhiyun * @len: length in bytes
803*4882a593Smuzhiyun *
804*4882a593Smuzhiyun * This is used to add a descriptor referenced by the indicated kvaddr and
805*4882a593Smuzhiyun * len.
806*4882a593Smuzhiyun *
807*4882a593Smuzhiyun * The mapping/unmapping of the kvaddr and len is automatically handled.
808*4882a593Smuzhiyun *
809*4882a593Smuzhiyun * Return:
810*4882a593Smuzhiyun * 0 - success, -ENOSPC - mapping fail, -ENOMEM - couldn't extend/coalesce
811*4882a593Smuzhiyun * descriptor array
812*4882a593Smuzhiyun */
sdma_txadd_kvaddr(struct hfi1_devdata * dd,struct sdma_txreq * tx,void * kvaddr,u16 len)813*4882a593Smuzhiyun static inline int sdma_txadd_kvaddr(
814*4882a593Smuzhiyun struct hfi1_devdata *dd,
815*4882a593Smuzhiyun struct sdma_txreq *tx,
816*4882a593Smuzhiyun void *kvaddr,
817*4882a593Smuzhiyun u16 len)
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun dma_addr_t addr;
820*4882a593Smuzhiyun int rval;
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun if ((unlikely(tx->num_desc == tx->desc_limit))) {
823*4882a593Smuzhiyun rval = ext_coal_sdma_tx_descs(dd, tx, SDMA_MAP_SINGLE,
824*4882a593Smuzhiyun kvaddr, NULL, 0, len);
825*4882a593Smuzhiyun if (rval <= 0)
826*4882a593Smuzhiyun return rval;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun addr = dma_map_single(
830*4882a593Smuzhiyun &dd->pcidev->dev,
831*4882a593Smuzhiyun kvaddr,
832*4882a593Smuzhiyun len,
833*4882a593Smuzhiyun DMA_TO_DEVICE);
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) {
836*4882a593Smuzhiyun __sdma_txclean(dd, tx);
837*4882a593Smuzhiyun return -ENOSPC;
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun return _sdma_txadd_daddr(
841*4882a593Smuzhiyun dd, SDMA_MAP_SINGLE, tx, addr, len);
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun struct iowait_work;
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun int sdma_send_txreq(struct sdma_engine *sde,
847*4882a593Smuzhiyun struct iowait_work *wait,
848*4882a593Smuzhiyun struct sdma_txreq *tx,
849*4882a593Smuzhiyun bool pkts_sent);
850*4882a593Smuzhiyun int sdma_send_txlist(struct sdma_engine *sde,
851*4882a593Smuzhiyun struct iowait_work *wait,
852*4882a593Smuzhiyun struct list_head *tx_list,
853*4882a593Smuzhiyun u16 *count_out);
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun int sdma_ahg_alloc(struct sdma_engine *sde);
856*4882a593Smuzhiyun void sdma_ahg_free(struct sdma_engine *sde, int ahg_index);
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun /**
859*4882a593Smuzhiyun * sdma_build_ahg - build ahg descriptor
860*4882a593Smuzhiyun * @data
861*4882a593Smuzhiyun * @dwindex
862*4882a593Smuzhiyun * @startbit
863*4882a593Smuzhiyun * @bits
864*4882a593Smuzhiyun *
865*4882a593Smuzhiyun * Build and return a 32 bit descriptor.
866*4882a593Smuzhiyun */
sdma_build_ahg_descriptor(u16 data,u8 dwindex,u8 startbit,u8 bits)867*4882a593Smuzhiyun static inline u32 sdma_build_ahg_descriptor(
868*4882a593Smuzhiyun u16 data,
869*4882a593Smuzhiyun u8 dwindex,
870*4882a593Smuzhiyun u8 startbit,
871*4882a593Smuzhiyun u8 bits)
872*4882a593Smuzhiyun {
873*4882a593Smuzhiyun return (u32)(1UL << SDMA_AHG_UPDATE_ENABLE_SHIFT |
874*4882a593Smuzhiyun ((startbit & SDMA_AHG_FIELD_START_MASK) <<
875*4882a593Smuzhiyun SDMA_AHG_FIELD_START_SHIFT) |
876*4882a593Smuzhiyun ((bits & SDMA_AHG_FIELD_LEN_MASK) <<
877*4882a593Smuzhiyun SDMA_AHG_FIELD_LEN_SHIFT) |
878*4882a593Smuzhiyun ((dwindex & SDMA_AHG_INDEX_MASK) <<
879*4882a593Smuzhiyun SDMA_AHG_INDEX_SHIFT) |
880*4882a593Smuzhiyun ((data & SDMA_AHG_VALUE_MASK) <<
881*4882a593Smuzhiyun SDMA_AHG_VALUE_SHIFT));
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun /**
885*4882a593Smuzhiyun * sdma_progress - use seq number of detect head progress
886*4882a593Smuzhiyun * @sde: sdma_engine to check
887*4882a593Smuzhiyun * @seq: base seq count
888*4882a593Smuzhiyun * @tx: txreq for which we need to check descriptor availability
889*4882a593Smuzhiyun *
890*4882a593Smuzhiyun * This is used in the appropriate spot in the sleep routine
891*4882a593Smuzhiyun * to check for potential ring progress. This routine gets the
892*4882a593Smuzhiyun * seqcount before queuing the iowait structure for progress.
893*4882a593Smuzhiyun *
894*4882a593Smuzhiyun * If the seqcount indicates that progress needs to be checked,
895*4882a593Smuzhiyun * re-submission is detected by checking whether the descriptor
896*4882a593Smuzhiyun * queue has enough descriptor for the txreq.
897*4882a593Smuzhiyun */
sdma_progress(struct sdma_engine * sde,unsigned seq,struct sdma_txreq * tx)898*4882a593Smuzhiyun static inline unsigned sdma_progress(struct sdma_engine *sde, unsigned seq,
899*4882a593Smuzhiyun struct sdma_txreq *tx)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun if (read_seqretry(&sde->head_lock, seq)) {
902*4882a593Smuzhiyun sde->desc_avail = sdma_descq_freecnt(sde);
903*4882a593Smuzhiyun if (tx->num_desc > sde->desc_avail)
904*4882a593Smuzhiyun return 0;
905*4882a593Smuzhiyun return 1;
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun return 0;
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun /**
911*4882a593Smuzhiyun * sdma_iowait_schedule() - initialize wait structure
912*4882a593Smuzhiyun * @sde: sdma_engine to schedule
913*4882a593Smuzhiyun * @wait: wait struct to schedule
914*4882a593Smuzhiyun *
915*4882a593Smuzhiyun * This function initializes the iowait
916*4882a593Smuzhiyun * structure embedded in the QP or PQ.
917*4882a593Smuzhiyun *
918*4882a593Smuzhiyun */
sdma_iowait_schedule(struct sdma_engine * sde,struct iowait * wait)919*4882a593Smuzhiyun static inline void sdma_iowait_schedule(
920*4882a593Smuzhiyun struct sdma_engine *sde,
921*4882a593Smuzhiyun struct iowait *wait)
922*4882a593Smuzhiyun {
923*4882a593Smuzhiyun struct hfi1_pportdata *ppd = sde->dd->pport;
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun iowait_schedule(wait, ppd->hfi1_wq, sde->cpu);
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun /* for use by interrupt handling */
929*4882a593Smuzhiyun void sdma_engine_error(struct sdma_engine *sde, u64 status);
930*4882a593Smuzhiyun void sdma_engine_interrupt(struct sdma_engine *sde, u64 status);
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun /*
933*4882a593Smuzhiyun *
934*4882a593Smuzhiyun * The diagram below details the relationship of the mapping structures
935*4882a593Smuzhiyun *
936*4882a593Smuzhiyun * Since the mapping now allows for non-uniform engines per vl, the
937*4882a593Smuzhiyun * number of engines for a vl is either the vl_engines[vl] or
938*4882a593Smuzhiyun * a computation based on num_sdma/num_vls:
939*4882a593Smuzhiyun *
940*4882a593Smuzhiyun * For example:
941*4882a593Smuzhiyun * nactual = vl_engines ? vl_engines[vl] : num_sdma/num_vls
942*4882a593Smuzhiyun *
943*4882a593Smuzhiyun * n = roundup to next highest power of 2 using nactual
944*4882a593Smuzhiyun *
945*4882a593Smuzhiyun * In the case where there are num_sdma/num_vls doesn't divide
946*4882a593Smuzhiyun * evenly, the extras are added from the last vl downward.
947*4882a593Smuzhiyun *
948*4882a593Smuzhiyun * For the case where n > nactual, the engines are assigned
949*4882a593Smuzhiyun * in a round robin fashion wrapping back to the first engine
950*4882a593Smuzhiyun * for a particular vl.
951*4882a593Smuzhiyun *
952*4882a593Smuzhiyun * dd->sdma_map
953*4882a593Smuzhiyun * | sdma_map_elem[0]
954*4882a593Smuzhiyun * | +--------------------+
955*4882a593Smuzhiyun * v | mask |
956*4882a593Smuzhiyun * sdma_vl_map |--------------------|
957*4882a593Smuzhiyun * +--------------------------+ | sde[0] -> eng 1 |
958*4882a593Smuzhiyun * | list (RCU) | |--------------------|
959*4882a593Smuzhiyun * |--------------------------| ->| sde[1] -> eng 2 |
960*4882a593Smuzhiyun * | mask | --/ |--------------------|
961*4882a593Smuzhiyun * |--------------------------| -/ | * |
962*4882a593Smuzhiyun * | actual_vls (max 8) | -/ |--------------------|
963*4882a593Smuzhiyun * |--------------------------| --/ | sde[n-1] -> eng n |
964*4882a593Smuzhiyun * | vls (max 8) | -/ +--------------------+
965*4882a593Smuzhiyun * |--------------------------| --/
966*4882a593Smuzhiyun * | map[0] |-/
967*4882a593Smuzhiyun * |--------------------------| +---------------------+
968*4882a593Smuzhiyun * | map[1] |--- | mask |
969*4882a593Smuzhiyun * |--------------------------| \---- |---------------------|
970*4882a593Smuzhiyun * | * | \-- | sde[0] -> eng 1+n |
971*4882a593Smuzhiyun * | * | \---- |---------------------|
972*4882a593Smuzhiyun * | * | \->| sde[1] -> eng 2+n |
973*4882a593Smuzhiyun * |--------------------------| |---------------------|
974*4882a593Smuzhiyun * | map[vls - 1] |- | * |
975*4882a593Smuzhiyun * +--------------------------+ \- |---------------------|
976*4882a593Smuzhiyun * \- | sde[m-1] -> eng m+n |
977*4882a593Smuzhiyun * \ +---------------------+
978*4882a593Smuzhiyun * \-
979*4882a593Smuzhiyun * \
980*4882a593Smuzhiyun * \- +----------------------+
981*4882a593Smuzhiyun * \- | mask |
982*4882a593Smuzhiyun * \ |----------------------|
983*4882a593Smuzhiyun * \- | sde[0] -> eng 1+m+n |
984*4882a593Smuzhiyun * \- |----------------------|
985*4882a593Smuzhiyun * >| sde[1] -> eng 2+m+n |
986*4882a593Smuzhiyun * |----------------------|
987*4882a593Smuzhiyun * | * |
988*4882a593Smuzhiyun * |----------------------|
989*4882a593Smuzhiyun * | sde[o-1] -> eng o+m+n|
990*4882a593Smuzhiyun * +----------------------+
991*4882a593Smuzhiyun *
992*4882a593Smuzhiyun */
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun /**
995*4882a593Smuzhiyun * struct sdma_map_elem - mapping for a vl
996*4882a593Smuzhiyun * @mask - selector mask
997*4882a593Smuzhiyun * @sde - array of engines for this vl
998*4882a593Smuzhiyun *
999*4882a593Smuzhiyun * The mask is used to "mod" the selector
1000*4882a593Smuzhiyun * to produce index into the trailing
1001*4882a593Smuzhiyun * array of sdes.
1002*4882a593Smuzhiyun */
1003*4882a593Smuzhiyun struct sdma_map_elem {
1004*4882a593Smuzhiyun u32 mask;
1005*4882a593Smuzhiyun struct sdma_engine *sde[];
1006*4882a593Smuzhiyun };
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun /**
1009*4882a593Smuzhiyun * struct sdma_map_el - mapping for a vl
1010*4882a593Smuzhiyun * @engine_to_vl - map of an engine to a vl
1011*4882a593Smuzhiyun * @list - rcu head for free callback
1012*4882a593Smuzhiyun * @mask - vl mask to "mod" the vl to produce an index to map array
1013*4882a593Smuzhiyun * @actual_vls - number of vls
1014*4882a593Smuzhiyun * @vls - number of vls rounded to next power of 2
1015*4882a593Smuzhiyun * @map - array of sdma_map_elem entries
1016*4882a593Smuzhiyun *
1017*4882a593Smuzhiyun * This is the parent mapping structure. The trailing
1018*4882a593Smuzhiyun * members of the struct point to sdma_map_elem entries, which
1019*4882a593Smuzhiyun * in turn point to an array of sde's for that vl.
1020*4882a593Smuzhiyun */
1021*4882a593Smuzhiyun struct sdma_vl_map {
1022*4882a593Smuzhiyun s8 engine_to_vl[TXE_NUM_SDMA_ENGINES];
1023*4882a593Smuzhiyun struct rcu_head list;
1024*4882a593Smuzhiyun u32 mask;
1025*4882a593Smuzhiyun u8 actual_vls;
1026*4882a593Smuzhiyun u8 vls;
1027*4882a593Smuzhiyun struct sdma_map_elem *map[];
1028*4882a593Smuzhiyun };
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun int sdma_map_init(
1031*4882a593Smuzhiyun struct hfi1_devdata *dd,
1032*4882a593Smuzhiyun u8 port,
1033*4882a593Smuzhiyun u8 num_vls,
1034*4882a593Smuzhiyun u8 *vl_engines);
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun /* slow path */
1037*4882a593Smuzhiyun void _sdma_engine_progress_schedule(struct sdma_engine *sde);
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun /**
1040*4882a593Smuzhiyun * sdma_engine_progress_schedule() - schedule progress on engine
1041*4882a593Smuzhiyun * @sde: sdma_engine to schedule progress
1042*4882a593Smuzhiyun *
1043*4882a593Smuzhiyun * This is the fast path.
1044*4882a593Smuzhiyun *
1045*4882a593Smuzhiyun */
sdma_engine_progress_schedule(struct sdma_engine * sde)1046*4882a593Smuzhiyun static inline void sdma_engine_progress_schedule(
1047*4882a593Smuzhiyun struct sdma_engine *sde)
1048*4882a593Smuzhiyun {
1049*4882a593Smuzhiyun if (!sde || sdma_descq_inprocess(sde) < (sde->descq_cnt / 8))
1050*4882a593Smuzhiyun return;
1051*4882a593Smuzhiyun _sdma_engine_progress_schedule(sde);
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun struct sdma_engine *sdma_select_engine_sc(
1055*4882a593Smuzhiyun struct hfi1_devdata *dd,
1056*4882a593Smuzhiyun u32 selector,
1057*4882a593Smuzhiyun u8 sc5);
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun struct sdma_engine *sdma_select_engine_vl(
1060*4882a593Smuzhiyun struct hfi1_devdata *dd,
1061*4882a593Smuzhiyun u32 selector,
1062*4882a593Smuzhiyun u8 vl);
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun struct sdma_engine *sdma_select_user_engine(struct hfi1_devdata *dd,
1065*4882a593Smuzhiyun u32 selector, u8 vl);
1066*4882a593Smuzhiyun ssize_t sdma_get_cpu_to_sde_map(struct sdma_engine *sde, char *buf);
1067*4882a593Smuzhiyun ssize_t sdma_set_cpu_to_sde_map(struct sdma_engine *sde, const char *buf,
1068*4882a593Smuzhiyun size_t count);
1069*4882a593Smuzhiyun int sdma_engine_get_vl(struct sdma_engine *sde);
1070*4882a593Smuzhiyun void sdma_seqfile_dump_sde(struct seq_file *s, struct sdma_engine *);
1071*4882a593Smuzhiyun void sdma_seqfile_dump_cpu_list(struct seq_file *s, struct hfi1_devdata *dd,
1072*4882a593Smuzhiyun unsigned long cpuid);
1073*4882a593Smuzhiyun
1074*4882a593Smuzhiyun #ifdef CONFIG_SDMA_VERBOSITY
1075*4882a593Smuzhiyun void sdma_dumpstate(struct sdma_engine *);
1076*4882a593Smuzhiyun #endif
slashstrip(char * s)1077*4882a593Smuzhiyun static inline char *slashstrip(char *s)
1078*4882a593Smuzhiyun {
1079*4882a593Smuzhiyun char *r = s;
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun while (*s)
1082*4882a593Smuzhiyun if (*s++ == '/')
1083*4882a593Smuzhiyun r = s;
1084*4882a593Smuzhiyun return r;
1085*4882a593Smuzhiyun }
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun u16 sdma_get_descq_cnt(void);
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun extern uint mod_num_sdma;
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun void sdma_update_lmc(struct hfi1_devdata *dd, u64 mask, u32 lid);
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun #endif
1094