xref: /OK3568_Linux_fs/kernel/drivers/infiniband/hw/qib/qib_sdma.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2012 Intel Corporation. All rights reserved.
3*4882a593Smuzhiyun  * Copyright (c) 2007 - 2012 QLogic Corporation. All rights reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This software is available to you under a choice of one of two
6*4882a593Smuzhiyun  * licenses.  You may choose to be licensed under the terms of the GNU
7*4882a593Smuzhiyun  * General Public License (GPL) Version 2, available from the file
8*4882a593Smuzhiyun  * COPYING in the main directory of this source tree, or the
9*4882a593Smuzhiyun  * OpenIB.org BSD license below:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  *     Redistribution and use in source and binary forms, with or
12*4882a593Smuzhiyun  *     without modification, are permitted provided that the following
13*4882a593Smuzhiyun  *     conditions are met:
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  *      - Redistributions of source code must retain the above
16*4882a593Smuzhiyun  *        copyright notice, this list of conditions and the following
17*4882a593Smuzhiyun  *        disclaimer.
18*4882a593Smuzhiyun  *
19*4882a593Smuzhiyun  *      - Redistributions in binary form must reproduce the above
20*4882a593Smuzhiyun  *        copyright notice, this list of conditions and the following
21*4882a593Smuzhiyun  *        disclaimer in the documentation and/or other materials
22*4882a593Smuzhiyun  *        provided with the distribution.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27*4882a593Smuzhiyun  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28*4882a593Smuzhiyun  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29*4882a593Smuzhiyun  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31*4882a593Smuzhiyun  * SOFTWARE.
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include <linux/spinlock.h>
35*4882a593Smuzhiyun #include <linux/netdevice.h>
36*4882a593Smuzhiyun #include <linux/moduleparam.h>
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #include "qib.h"
39*4882a593Smuzhiyun #include "qib_common.h"
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /* default pio off, sdma on */
42*4882a593Smuzhiyun static ushort sdma_descq_cnt = 256;
43*4882a593Smuzhiyun module_param_named(sdma_descq_cnt, sdma_descq_cnt, ushort, S_IRUGO);
44*4882a593Smuzhiyun MODULE_PARM_DESC(sdma_descq_cnt, "Number of SDMA descq entries");
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun  * Bits defined in the send DMA descriptor.
48*4882a593Smuzhiyun  */
49*4882a593Smuzhiyun #define SDMA_DESC_LAST          (1ULL << 11)
50*4882a593Smuzhiyun #define SDMA_DESC_FIRST         (1ULL << 12)
51*4882a593Smuzhiyun #define SDMA_DESC_DMA_HEAD      (1ULL << 13)
52*4882a593Smuzhiyun #define SDMA_DESC_USE_LARGE_BUF (1ULL << 14)
53*4882a593Smuzhiyun #define SDMA_DESC_INTR          (1ULL << 15)
54*4882a593Smuzhiyun #define SDMA_DESC_COUNT_LSB     16
55*4882a593Smuzhiyun #define SDMA_DESC_GEN_LSB       30
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /* declare all statics here rather than keep sorting */
58*4882a593Smuzhiyun static int alloc_sdma(struct qib_pportdata *);
59*4882a593Smuzhiyun static void sdma_complete(struct kref *);
60*4882a593Smuzhiyun static void sdma_finalput(struct qib_sdma_state *);
61*4882a593Smuzhiyun static void sdma_get(struct qib_sdma_state *);
62*4882a593Smuzhiyun static void sdma_put(struct qib_sdma_state *);
63*4882a593Smuzhiyun static void sdma_set_state(struct qib_pportdata *, enum qib_sdma_states);
64*4882a593Smuzhiyun static void sdma_start_sw_clean_up(struct qib_pportdata *);
65*4882a593Smuzhiyun static void sdma_sw_clean_up_task(struct tasklet_struct *);
66*4882a593Smuzhiyun static void unmap_desc(struct qib_pportdata *, unsigned);
67*4882a593Smuzhiyun 
sdma_get(struct qib_sdma_state * ss)68*4882a593Smuzhiyun static void sdma_get(struct qib_sdma_state *ss)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	kref_get(&ss->kref);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
sdma_complete(struct kref * kref)73*4882a593Smuzhiyun static void sdma_complete(struct kref *kref)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	struct qib_sdma_state *ss =
76*4882a593Smuzhiyun 		container_of(kref, struct qib_sdma_state, kref);
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	complete(&ss->comp);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
sdma_put(struct qib_sdma_state * ss)81*4882a593Smuzhiyun static void sdma_put(struct qib_sdma_state *ss)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	kref_put(&ss->kref, sdma_complete);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
sdma_finalput(struct qib_sdma_state * ss)86*4882a593Smuzhiyun static void sdma_finalput(struct qib_sdma_state *ss)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	sdma_put(ss);
89*4882a593Smuzhiyun 	wait_for_completion(&ss->comp);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun  * Complete all the sdma requests on the active list, in the correct
94*4882a593Smuzhiyun  * order, and with appropriate processing.   Called when cleaning up
95*4882a593Smuzhiyun  * after sdma shutdown, and when new sdma requests are submitted for
96*4882a593Smuzhiyun  * a link that is down.   This matches what is done for requests
97*4882a593Smuzhiyun  * that complete normally, it's just the full list.
98*4882a593Smuzhiyun  *
99*4882a593Smuzhiyun  * Must be called with sdma_lock held
100*4882a593Smuzhiyun  */
clear_sdma_activelist(struct qib_pportdata * ppd)101*4882a593Smuzhiyun static void clear_sdma_activelist(struct qib_pportdata *ppd)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	struct qib_sdma_txreq *txp, *txp_next;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	list_for_each_entry_safe(txp, txp_next, &ppd->sdma_activelist, list) {
106*4882a593Smuzhiyun 		list_del_init(&txp->list);
107*4882a593Smuzhiyun 		if (txp->flags & QIB_SDMA_TXREQ_F_FREEDESC) {
108*4882a593Smuzhiyun 			unsigned idx;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 			idx = txp->start_idx;
111*4882a593Smuzhiyun 			while (idx != txp->next_descq_idx) {
112*4882a593Smuzhiyun 				unmap_desc(ppd, idx);
113*4882a593Smuzhiyun 				if (++idx == ppd->sdma_descq_cnt)
114*4882a593Smuzhiyun 					idx = 0;
115*4882a593Smuzhiyun 			}
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 		if (txp->callback)
118*4882a593Smuzhiyun 			(*txp->callback)(txp, QIB_SDMA_TXREQ_S_ABORTED);
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
sdma_sw_clean_up_task(struct tasklet_struct * t)122*4882a593Smuzhiyun static void sdma_sw_clean_up_task(struct tasklet_struct *t)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	struct qib_pportdata *ppd = from_tasklet(ppd, t,
125*4882a593Smuzhiyun 						 sdma_sw_clean_up_task);
126*4882a593Smuzhiyun 	unsigned long flags;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	spin_lock_irqsave(&ppd->sdma_lock, flags);
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	/*
131*4882a593Smuzhiyun 	 * At this point, the following should always be true:
132*4882a593Smuzhiyun 	 * - We are halted, so no more descriptors are getting retired.
133*4882a593Smuzhiyun 	 * - We are not running, so no one is submitting new work.
134*4882a593Smuzhiyun 	 * - Only we can send the e40_sw_cleaned, so we can't start
135*4882a593Smuzhiyun 	 *   running again until we say so.  So, the active list and
136*4882a593Smuzhiyun 	 *   descq are ours to play with.
137*4882a593Smuzhiyun 	 */
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	/* Process all retired requests. */
140*4882a593Smuzhiyun 	qib_sdma_make_progress(ppd);
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	clear_sdma_activelist(ppd);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	/*
145*4882a593Smuzhiyun 	 * Resync count of added and removed.  It is VERY important that
146*4882a593Smuzhiyun 	 * sdma_descq_removed NEVER decrement - user_sdma depends on it.
147*4882a593Smuzhiyun 	 */
148*4882a593Smuzhiyun 	ppd->sdma_descq_removed = ppd->sdma_descq_added;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	/*
151*4882a593Smuzhiyun 	 * Reset our notion of head and tail.
152*4882a593Smuzhiyun 	 * Note that the HW registers will be reset when switching states
153*4882a593Smuzhiyun 	 * due to calling __qib_sdma_process_event() below.
154*4882a593Smuzhiyun 	 */
155*4882a593Smuzhiyun 	ppd->sdma_descq_tail = 0;
156*4882a593Smuzhiyun 	ppd->sdma_descq_head = 0;
157*4882a593Smuzhiyun 	ppd->sdma_head_dma[0] = 0;
158*4882a593Smuzhiyun 	ppd->sdma_generation = 0;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	__qib_sdma_process_event(ppd, qib_sdma_event_e40_sw_cleaned);
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun /*
166*4882a593Smuzhiyun  * This is called when changing to state qib_sdma_state_s10_hw_start_up_wait
167*4882a593Smuzhiyun  * as a result of send buffer errors or send DMA descriptor errors.
168*4882a593Smuzhiyun  * We want to disarm the buffers in these cases.
169*4882a593Smuzhiyun  */
sdma_hw_start_up(struct qib_pportdata * ppd)170*4882a593Smuzhiyun static void sdma_hw_start_up(struct qib_pportdata *ppd)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	struct qib_sdma_state *ss = &ppd->sdma_state;
173*4882a593Smuzhiyun 	unsigned bufno;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	for (bufno = ss->first_sendbuf; bufno < ss->last_sendbuf; ++bufno)
176*4882a593Smuzhiyun 		ppd->dd->f_sendctrl(ppd, QIB_SENDCTRL_DISARM_BUF(bufno));
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	ppd->dd->f_sdma_hw_start_up(ppd);
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun 
sdma_sw_tear_down(struct qib_pportdata * ppd)181*4882a593Smuzhiyun static void sdma_sw_tear_down(struct qib_pportdata *ppd)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	struct qib_sdma_state *ss = &ppd->sdma_state;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	/* Releasing this reference means the state machine has stopped. */
186*4882a593Smuzhiyun 	sdma_put(ss);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
sdma_start_sw_clean_up(struct qib_pportdata * ppd)189*4882a593Smuzhiyun static void sdma_start_sw_clean_up(struct qib_pportdata *ppd)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	tasklet_hi_schedule(&ppd->sdma_sw_clean_up_task);
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
sdma_set_state(struct qib_pportdata * ppd,enum qib_sdma_states next_state)194*4882a593Smuzhiyun static void sdma_set_state(struct qib_pportdata *ppd,
195*4882a593Smuzhiyun 	enum qib_sdma_states next_state)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	struct qib_sdma_state *ss = &ppd->sdma_state;
198*4882a593Smuzhiyun 	struct sdma_set_state_action *action = ss->set_state_action;
199*4882a593Smuzhiyun 	unsigned op = 0;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	/* debugging bookkeeping */
202*4882a593Smuzhiyun 	ss->previous_state = ss->current_state;
203*4882a593Smuzhiyun 	ss->previous_op = ss->current_op;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	ss->current_state = next_state;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	if (action[next_state].op_enable)
208*4882a593Smuzhiyun 		op |= QIB_SDMA_SENDCTRL_OP_ENABLE;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	if (action[next_state].op_intenable)
211*4882a593Smuzhiyun 		op |= QIB_SDMA_SENDCTRL_OP_INTENABLE;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	if (action[next_state].op_halt)
214*4882a593Smuzhiyun 		op |= QIB_SDMA_SENDCTRL_OP_HALT;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	if (action[next_state].op_drain)
217*4882a593Smuzhiyun 		op |= QIB_SDMA_SENDCTRL_OP_DRAIN;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	if (action[next_state].go_s99_running_tofalse)
220*4882a593Smuzhiyun 		ss->go_s99_running = 0;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	if (action[next_state].go_s99_running_totrue)
223*4882a593Smuzhiyun 		ss->go_s99_running = 1;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	ss->current_op = op;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	ppd->dd->f_sdma_sendctrl(ppd, ss->current_op);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
unmap_desc(struct qib_pportdata * ppd,unsigned head)230*4882a593Smuzhiyun static void unmap_desc(struct qib_pportdata *ppd, unsigned head)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	__le64 *descqp = &ppd->sdma_descq[head].qw[0];
233*4882a593Smuzhiyun 	u64 desc[2];
234*4882a593Smuzhiyun 	dma_addr_t addr;
235*4882a593Smuzhiyun 	size_t len;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	desc[0] = le64_to_cpu(descqp[0]);
238*4882a593Smuzhiyun 	desc[1] = le64_to_cpu(descqp[1]);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	addr = (desc[1] << 32) | (desc[0] >> 32);
241*4882a593Smuzhiyun 	len = (desc[0] >> 14) & (0x7ffULL << 2);
242*4882a593Smuzhiyun 	dma_unmap_single(&ppd->dd->pcidev->dev, addr, len, DMA_TO_DEVICE);
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
alloc_sdma(struct qib_pportdata * ppd)245*4882a593Smuzhiyun static int alloc_sdma(struct qib_pportdata *ppd)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	ppd->sdma_descq_cnt = sdma_descq_cnt;
248*4882a593Smuzhiyun 	if (!ppd->sdma_descq_cnt)
249*4882a593Smuzhiyun 		ppd->sdma_descq_cnt = 256;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* Allocate memory for SendDMA descriptor FIFO */
252*4882a593Smuzhiyun 	ppd->sdma_descq = dma_alloc_coherent(&ppd->dd->pcidev->dev,
253*4882a593Smuzhiyun 		ppd->sdma_descq_cnt * sizeof(u64[2]), &ppd->sdma_descq_phys,
254*4882a593Smuzhiyun 		GFP_KERNEL);
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	if (!ppd->sdma_descq) {
257*4882a593Smuzhiyun 		qib_dev_err(ppd->dd,
258*4882a593Smuzhiyun 			"failed to allocate SendDMA descriptor FIFO memory\n");
259*4882a593Smuzhiyun 		goto bail;
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	/* Allocate memory for DMA of head register to memory */
263*4882a593Smuzhiyun 	ppd->sdma_head_dma = dma_alloc_coherent(&ppd->dd->pcidev->dev,
264*4882a593Smuzhiyun 		PAGE_SIZE, &ppd->sdma_head_phys, GFP_KERNEL);
265*4882a593Smuzhiyun 	if (!ppd->sdma_head_dma) {
266*4882a593Smuzhiyun 		qib_dev_err(ppd->dd,
267*4882a593Smuzhiyun 			"failed to allocate SendDMA head memory\n");
268*4882a593Smuzhiyun 		goto cleanup_descq;
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 	ppd->sdma_head_dma[0] = 0;
271*4882a593Smuzhiyun 	return 0;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun cleanup_descq:
274*4882a593Smuzhiyun 	dma_free_coherent(&ppd->dd->pcidev->dev,
275*4882a593Smuzhiyun 		ppd->sdma_descq_cnt * sizeof(u64[2]), (void *)ppd->sdma_descq,
276*4882a593Smuzhiyun 		ppd->sdma_descq_phys);
277*4882a593Smuzhiyun 	ppd->sdma_descq = NULL;
278*4882a593Smuzhiyun 	ppd->sdma_descq_phys = 0;
279*4882a593Smuzhiyun bail:
280*4882a593Smuzhiyun 	ppd->sdma_descq_cnt = 0;
281*4882a593Smuzhiyun 	return -ENOMEM;
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
free_sdma(struct qib_pportdata * ppd)284*4882a593Smuzhiyun static void free_sdma(struct qib_pportdata *ppd)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	struct qib_devdata *dd = ppd->dd;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (ppd->sdma_head_dma) {
289*4882a593Smuzhiyun 		dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
290*4882a593Smuzhiyun 				  (void *)ppd->sdma_head_dma,
291*4882a593Smuzhiyun 				  ppd->sdma_head_phys);
292*4882a593Smuzhiyun 		ppd->sdma_head_dma = NULL;
293*4882a593Smuzhiyun 		ppd->sdma_head_phys = 0;
294*4882a593Smuzhiyun 	}
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	if (ppd->sdma_descq) {
297*4882a593Smuzhiyun 		dma_free_coherent(&dd->pcidev->dev,
298*4882a593Smuzhiyun 				  ppd->sdma_descq_cnt * sizeof(u64[2]),
299*4882a593Smuzhiyun 				  ppd->sdma_descq, ppd->sdma_descq_phys);
300*4882a593Smuzhiyun 		ppd->sdma_descq = NULL;
301*4882a593Smuzhiyun 		ppd->sdma_descq_phys = 0;
302*4882a593Smuzhiyun 	}
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun 
make_sdma_desc(struct qib_pportdata * ppd,u64 * sdmadesc,u64 addr,u64 dwlen,u64 dwoffset)305*4882a593Smuzhiyun static inline void make_sdma_desc(struct qib_pportdata *ppd,
306*4882a593Smuzhiyun 				  u64 *sdmadesc, u64 addr, u64 dwlen,
307*4882a593Smuzhiyun 				  u64 dwoffset)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	WARN_ON(addr & 3);
311*4882a593Smuzhiyun 	/* SDmaPhyAddr[47:32] */
312*4882a593Smuzhiyun 	sdmadesc[1] = addr >> 32;
313*4882a593Smuzhiyun 	/* SDmaPhyAddr[31:0] */
314*4882a593Smuzhiyun 	sdmadesc[0] = (addr & 0xfffffffcULL) << 32;
315*4882a593Smuzhiyun 	/* SDmaGeneration[1:0] */
316*4882a593Smuzhiyun 	sdmadesc[0] |= (ppd->sdma_generation & 3ULL) <<
317*4882a593Smuzhiyun 		SDMA_DESC_GEN_LSB;
318*4882a593Smuzhiyun 	/* SDmaDwordCount[10:0] */
319*4882a593Smuzhiyun 	sdmadesc[0] |= (dwlen & 0x7ffULL) << SDMA_DESC_COUNT_LSB;
320*4882a593Smuzhiyun 	/* SDmaBufOffset[12:2] */
321*4882a593Smuzhiyun 	sdmadesc[0] |= dwoffset & 0x7ffULL;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun /* sdma_lock must be held */
qib_sdma_make_progress(struct qib_pportdata * ppd)325*4882a593Smuzhiyun int qib_sdma_make_progress(struct qib_pportdata *ppd)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	struct list_head *lp = NULL;
328*4882a593Smuzhiyun 	struct qib_sdma_txreq *txp = NULL;
329*4882a593Smuzhiyun 	struct qib_devdata *dd = ppd->dd;
330*4882a593Smuzhiyun 	int progress = 0;
331*4882a593Smuzhiyun 	u16 hwhead;
332*4882a593Smuzhiyun 	u16 idx = 0;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	hwhead = dd->f_sdma_gethead(ppd);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	/* The reason for some of the complexity of this code is that
337*4882a593Smuzhiyun 	 * not all descriptors have corresponding txps.  So, we have to
338*4882a593Smuzhiyun 	 * be able to skip over descs until we wander into the range of
339*4882a593Smuzhiyun 	 * the next txp on the list.
340*4882a593Smuzhiyun 	 */
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	if (!list_empty(&ppd->sdma_activelist)) {
343*4882a593Smuzhiyun 		lp = ppd->sdma_activelist.next;
344*4882a593Smuzhiyun 		txp = list_entry(lp, struct qib_sdma_txreq, list);
345*4882a593Smuzhiyun 		idx = txp->start_idx;
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	while (ppd->sdma_descq_head != hwhead) {
349*4882a593Smuzhiyun 		/* if desc is part of this txp, unmap if needed */
350*4882a593Smuzhiyun 		if (txp && (txp->flags & QIB_SDMA_TXREQ_F_FREEDESC) &&
351*4882a593Smuzhiyun 		    (idx == ppd->sdma_descq_head)) {
352*4882a593Smuzhiyun 			unmap_desc(ppd, ppd->sdma_descq_head);
353*4882a593Smuzhiyun 			if (++idx == ppd->sdma_descq_cnt)
354*4882a593Smuzhiyun 				idx = 0;
355*4882a593Smuzhiyun 		}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 		/* increment dequed desc count */
358*4882a593Smuzhiyun 		ppd->sdma_descq_removed++;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 		/* advance head, wrap if needed */
361*4882a593Smuzhiyun 		if (++ppd->sdma_descq_head == ppd->sdma_descq_cnt)
362*4882a593Smuzhiyun 			ppd->sdma_descq_head = 0;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 		/* if now past this txp's descs, do the callback */
365*4882a593Smuzhiyun 		if (txp && txp->next_descq_idx == ppd->sdma_descq_head) {
366*4882a593Smuzhiyun 			/* remove from active list */
367*4882a593Smuzhiyun 			list_del_init(&txp->list);
368*4882a593Smuzhiyun 			if (txp->callback)
369*4882a593Smuzhiyun 				(*txp->callback)(txp, QIB_SDMA_TXREQ_S_OK);
370*4882a593Smuzhiyun 			/* see if there is another txp */
371*4882a593Smuzhiyun 			if (list_empty(&ppd->sdma_activelist))
372*4882a593Smuzhiyun 				txp = NULL;
373*4882a593Smuzhiyun 			else {
374*4882a593Smuzhiyun 				lp = ppd->sdma_activelist.next;
375*4882a593Smuzhiyun 				txp = list_entry(lp, struct qib_sdma_txreq,
376*4882a593Smuzhiyun 					list);
377*4882a593Smuzhiyun 				idx = txp->start_idx;
378*4882a593Smuzhiyun 			}
379*4882a593Smuzhiyun 		}
380*4882a593Smuzhiyun 		progress = 1;
381*4882a593Smuzhiyun 	}
382*4882a593Smuzhiyun 	if (progress)
383*4882a593Smuzhiyun 		qib_verbs_sdma_desc_avail(ppd, qib_sdma_descq_freecnt(ppd));
384*4882a593Smuzhiyun 	return progress;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun /*
388*4882a593Smuzhiyun  * This is called from interrupt context.
389*4882a593Smuzhiyun  */
qib_sdma_intr(struct qib_pportdata * ppd)390*4882a593Smuzhiyun void qib_sdma_intr(struct qib_pportdata *ppd)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	unsigned long flags;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	spin_lock_irqsave(&ppd->sdma_lock, flags);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	__qib_sdma_intr(ppd);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
__qib_sdma_intr(struct qib_pportdata * ppd)401*4882a593Smuzhiyun void __qib_sdma_intr(struct qib_pportdata *ppd)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	if (__qib_sdma_running(ppd)) {
404*4882a593Smuzhiyun 		qib_sdma_make_progress(ppd);
405*4882a593Smuzhiyun 		if (!list_empty(&ppd->sdma_userpending))
406*4882a593Smuzhiyun 			qib_user_sdma_send_desc(ppd, &ppd->sdma_userpending);
407*4882a593Smuzhiyun 	}
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
qib_setup_sdma(struct qib_pportdata * ppd)410*4882a593Smuzhiyun int qib_setup_sdma(struct qib_pportdata *ppd)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	struct qib_devdata *dd = ppd->dd;
413*4882a593Smuzhiyun 	unsigned long flags;
414*4882a593Smuzhiyun 	int ret = 0;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	ret = alloc_sdma(ppd);
417*4882a593Smuzhiyun 	if (ret)
418*4882a593Smuzhiyun 		goto bail;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	/* set consistent sdma state */
421*4882a593Smuzhiyun 	ppd->dd->f_sdma_init_early(ppd);
422*4882a593Smuzhiyun 	spin_lock_irqsave(&ppd->sdma_lock, flags);
423*4882a593Smuzhiyun 	sdma_set_state(ppd, qib_sdma_state_s00_hw_down);
424*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	/* set up reference counting */
427*4882a593Smuzhiyun 	kref_init(&ppd->sdma_state.kref);
428*4882a593Smuzhiyun 	init_completion(&ppd->sdma_state.comp);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	ppd->sdma_generation = 0;
431*4882a593Smuzhiyun 	ppd->sdma_descq_head = 0;
432*4882a593Smuzhiyun 	ppd->sdma_descq_removed = 0;
433*4882a593Smuzhiyun 	ppd->sdma_descq_added = 0;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	ppd->sdma_intrequest = 0;
436*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ppd->sdma_userpending);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ppd->sdma_activelist);
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	tasklet_setup(&ppd->sdma_sw_clean_up_task, sdma_sw_clean_up_task);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	ret = dd->f_init_sdma_regs(ppd);
443*4882a593Smuzhiyun 	if (ret)
444*4882a593Smuzhiyun 		goto bail_alloc;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	qib_sdma_process_event(ppd, qib_sdma_event_e10_go_hw_start);
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	return 0;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun bail_alloc:
451*4882a593Smuzhiyun 	qib_teardown_sdma(ppd);
452*4882a593Smuzhiyun bail:
453*4882a593Smuzhiyun 	return ret;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun 
qib_teardown_sdma(struct qib_pportdata * ppd)456*4882a593Smuzhiyun void qib_teardown_sdma(struct qib_pportdata *ppd)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	qib_sdma_process_event(ppd, qib_sdma_event_e00_go_hw_down);
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	/*
461*4882a593Smuzhiyun 	 * This waits for the state machine to exit so it is not
462*4882a593Smuzhiyun 	 * necessary to kill the sdma_sw_clean_up_task to make sure
463*4882a593Smuzhiyun 	 * it is not running.
464*4882a593Smuzhiyun 	 */
465*4882a593Smuzhiyun 	sdma_finalput(&ppd->sdma_state);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	free_sdma(ppd);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
qib_sdma_running(struct qib_pportdata * ppd)470*4882a593Smuzhiyun int qib_sdma_running(struct qib_pportdata *ppd)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun 	unsigned long flags;
473*4882a593Smuzhiyun 	int ret;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	spin_lock_irqsave(&ppd->sdma_lock, flags);
476*4882a593Smuzhiyun 	ret = __qib_sdma_running(ppd);
477*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	return ret;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun /*
483*4882a593Smuzhiyun  * Complete a request when sdma not running; likely only request
484*4882a593Smuzhiyun  * but to simplify the code, always queue it, then process the full
485*4882a593Smuzhiyun  * activelist.  We process the entire list to ensure that this particular
486*4882a593Smuzhiyun  * request does get it's callback, but in the correct order.
487*4882a593Smuzhiyun  * Must be called with sdma_lock held
488*4882a593Smuzhiyun  */
complete_sdma_err_req(struct qib_pportdata * ppd,struct qib_verbs_txreq * tx)489*4882a593Smuzhiyun static void complete_sdma_err_req(struct qib_pportdata *ppd,
490*4882a593Smuzhiyun 				  struct qib_verbs_txreq *tx)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	struct qib_qp_priv *priv = tx->qp->priv;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	atomic_inc(&priv->s_dma_busy);
495*4882a593Smuzhiyun 	/* no sdma descriptors, so no unmap_desc */
496*4882a593Smuzhiyun 	tx->txreq.start_idx = 0;
497*4882a593Smuzhiyun 	tx->txreq.next_descq_idx = 0;
498*4882a593Smuzhiyun 	list_add_tail(&tx->txreq.list, &ppd->sdma_activelist);
499*4882a593Smuzhiyun 	clear_sdma_activelist(ppd);
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun /*
503*4882a593Smuzhiyun  * This function queues one IB packet onto the send DMA queue per call.
504*4882a593Smuzhiyun  * The caller is responsible for checking:
505*4882a593Smuzhiyun  * 1) The number of send DMA descriptor entries is less than the size of
506*4882a593Smuzhiyun  *    the descriptor queue.
507*4882a593Smuzhiyun  * 2) The IB SGE addresses and lengths are 32-bit aligned
508*4882a593Smuzhiyun  *    (except possibly the last SGE's length)
509*4882a593Smuzhiyun  * 3) The SGE addresses are suitable for passing to dma_map_single().
510*4882a593Smuzhiyun  */
qib_sdma_verbs_send(struct qib_pportdata * ppd,struct rvt_sge_state * ss,u32 dwords,struct qib_verbs_txreq * tx)511*4882a593Smuzhiyun int qib_sdma_verbs_send(struct qib_pportdata *ppd,
512*4882a593Smuzhiyun 			struct rvt_sge_state *ss, u32 dwords,
513*4882a593Smuzhiyun 			struct qib_verbs_txreq *tx)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun 	unsigned long flags;
516*4882a593Smuzhiyun 	struct rvt_sge *sge;
517*4882a593Smuzhiyun 	struct rvt_qp *qp;
518*4882a593Smuzhiyun 	int ret = 0;
519*4882a593Smuzhiyun 	u16 tail;
520*4882a593Smuzhiyun 	__le64 *descqp;
521*4882a593Smuzhiyun 	u64 sdmadesc[2];
522*4882a593Smuzhiyun 	u32 dwoffset;
523*4882a593Smuzhiyun 	dma_addr_t addr;
524*4882a593Smuzhiyun 	struct qib_qp_priv *priv;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	spin_lock_irqsave(&ppd->sdma_lock, flags);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun retry:
529*4882a593Smuzhiyun 	if (unlikely(!__qib_sdma_running(ppd))) {
530*4882a593Smuzhiyun 		complete_sdma_err_req(ppd, tx);
531*4882a593Smuzhiyun 		goto unlock;
532*4882a593Smuzhiyun 	}
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	if (tx->txreq.sg_count > qib_sdma_descq_freecnt(ppd)) {
535*4882a593Smuzhiyun 		if (qib_sdma_make_progress(ppd))
536*4882a593Smuzhiyun 			goto retry;
537*4882a593Smuzhiyun 		if (ppd->dd->flags & QIB_HAS_SDMA_TIMEOUT)
538*4882a593Smuzhiyun 			ppd->dd->f_sdma_set_desc_cnt(ppd,
539*4882a593Smuzhiyun 					ppd->sdma_descq_cnt / 2);
540*4882a593Smuzhiyun 		goto busy;
541*4882a593Smuzhiyun 	}
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	dwoffset = tx->hdr_dwords;
544*4882a593Smuzhiyun 	make_sdma_desc(ppd, sdmadesc, (u64) tx->txreq.addr, dwoffset, 0);
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	sdmadesc[0] |= SDMA_DESC_FIRST;
547*4882a593Smuzhiyun 	if (tx->txreq.flags & QIB_SDMA_TXREQ_F_USELARGEBUF)
548*4882a593Smuzhiyun 		sdmadesc[0] |= SDMA_DESC_USE_LARGE_BUF;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	/* write to the descq */
551*4882a593Smuzhiyun 	tail = ppd->sdma_descq_tail;
552*4882a593Smuzhiyun 	descqp = &ppd->sdma_descq[tail].qw[0];
553*4882a593Smuzhiyun 	*descqp++ = cpu_to_le64(sdmadesc[0]);
554*4882a593Smuzhiyun 	*descqp++ = cpu_to_le64(sdmadesc[1]);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	/* increment the tail */
557*4882a593Smuzhiyun 	if (++tail == ppd->sdma_descq_cnt) {
558*4882a593Smuzhiyun 		tail = 0;
559*4882a593Smuzhiyun 		descqp = &ppd->sdma_descq[0].qw[0];
560*4882a593Smuzhiyun 		++ppd->sdma_generation;
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	tx->txreq.start_idx = tail;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	sge = &ss->sge;
566*4882a593Smuzhiyun 	while (dwords) {
567*4882a593Smuzhiyun 		u32 dw;
568*4882a593Smuzhiyun 		u32 len = rvt_get_sge_length(sge, dwords << 2);
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 		dw = (len + 3) >> 2;
571*4882a593Smuzhiyun 		addr = dma_map_single(&ppd->dd->pcidev->dev, sge->vaddr,
572*4882a593Smuzhiyun 				      dw << 2, DMA_TO_DEVICE);
573*4882a593Smuzhiyun 		if (dma_mapping_error(&ppd->dd->pcidev->dev, addr)) {
574*4882a593Smuzhiyun 			ret = -ENOMEM;
575*4882a593Smuzhiyun 			goto unmap;
576*4882a593Smuzhiyun 		}
577*4882a593Smuzhiyun 		sdmadesc[0] = 0;
578*4882a593Smuzhiyun 		make_sdma_desc(ppd, sdmadesc, (u64) addr, dw, dwoffset);
579*4882a593Smuzhiyun 		/* SDmaUseLargeBuf has to be set in every descriptor */
580*4882a593Smuzhiyun 		if (tx->txreq.flags & QIB_SDMA_TXREQ_F_USELARGEBUF)
581*4882a593Smuzhiyun 			sdmadesc[0] |= SDMA_DESC_USE_LARGE_BUF;
582*4882a593Smuzhiyun 		/* write to the descq */
583*4882a593Smuzhiyun 		*descqp++ = cpu_to_le64(sdmadesc[0]);
584*4882a593Smuzhiyun 		*descqp++ = cpu_to_le64(sdmadesc[1]);
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 		/* increment the tail */
587*4882a593Smuzhiyun 		if (++tail == ppd->sdma_descq_cnt) {
588*4882a593Smuzhiyun 			tail = 0;
589*4882a593Smuzhiyun 			descqp = &ppd->sdma_descq[0].qw[0];
590*4882a593Smuzhiyun 			++ppd->sdma_generation;
591*4882a593Smuzhiyun 		}
592*4882a593Smuzhiyun 		rvt_update_sge(ss, len, false);
593*4882a593Smuzhiyun 		dwoffset += dw;
594*4882a593Smuzhiyun 		dwords -= dw;
595*4882a593Smuzhiyun 	}
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	if (!tail)
598*4882a593Smuzhiyun 		descqp = &ppd->sdma_descq[ppd->sdma_descq_cnt].qw[0];
599*4882a593Smuzhiyun 	descqp -= 2;
600*4882a593Smuzhiyun 	descqp[0] |= cpu_to_le64(SDMA_DESC_LAST);
601*4882a593Smuzhiyun 	if (tx->txreq.flags & QIB_SDMA_TXREQ_F_HEADTOHOST)
602*4882a593Smuzhiyun 		descqp[0] |= cpu_to_le64(SDMA_DESC_DMA_HEAD);
603*4882a593Smuzhiyun 	if (tx->txreq.flags & QIB_SDMA_TXREQ_F_INTREQ)
604*4882a593Smuzhiyun 		descqp[0] |= cpu_to_le64(SDMA_DESC_INTR);
605*4882a593Smuzhiyun 	priv = tx->qp->priv;
606*4882a593Smuzhiyun 	atomic_inc(&priv->s_dma_busy);
607*4882a593Smuzhiyun 	tx->txreq.next_descq_idx = tail;
608*4882a593Smuzhiyun 	ppd->dd->f_sdma_update_tail(ppd, tail);
609*4882a593Smuzhiyun 	ppd->sdma_descq_added += tx->txreq.sg_count;
610*4882a593Smuzhiyun 	list_add_tail(&tx->txreq.list, &ppd->sdma_activelist);
611*4882a593Smuzhiyun 	goto unlock;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun unmap:
614*4882a593Smuzhiyun 	for (;;) {
615*4882a593Smuzhiyun 		if (!tail)
616*4882a593Smuzhiyun 			tail = ppd->sdma_descq_cnt - 1;
617*4882a593Smuzhiyun 		else
618*4882a593Smuzhiyun 			tail--;
619*4882a593Smuzhiyun 		if (tail == ppd->sdma_descq_tail)
620*4882a593Smuzhiyun 			break;
621*4882a593Smuzhiyun 		unmap_desc(ppd, tail);
622*4882a593Smuzhiyun 	}
623*4882a593Smuzhiyun 	qp = tx->qp;
624*4882a593Smuzhiyun 	priv = qp->priv;
625*4882a593Smuzhiyun 	qib_put_txreq(tx);
626*4882a593Smuzhiyun 	spin_lock(&qp->r_lock);
627*4882a593Smuzhiyun 	spin_lock(&qp->s_lock);
628*4882a593Smuzhiyun 	if (qp->ibqp.qp_type == IB_QPT_RC) {
629*4882a593Smuzhiyun 		/* XXX what about error sending RDMA read responses? */
630*4882a593Smuzhiyun 		if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)
631*4882a593Smuzhiyun 			rvt_error_qp(qp, IB_WC_GENERAL_ERR);
632*4882a593Smuzhiyun 	} else if (qp->s_wqe)
633*4882a593Smuzhiyun 		rvt_send_complete(qp, qp->s_wqe, IB_WC_GENERAL_ERR);
634*4882a593Smuzhiyun 	spin_unlock(&qp->s_lock);
635*4882a593Smuzhiyun 	spin_unlock(&qp->r_lock);
636*4882a593Smuzhiyun 	/* return zero to process the next send work request */
637*4882a593Smuzhiyun 	goto unlock;
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun busy:
640*4882a593Smuzhiyun 	qp = tx->qp;
641*4882a593Smuzhiyun 	priv = qp->priv;
642*4882a593Smuzhiyun 	spin_lock(&qp->s_lock);
643*4882a593Smuzhiyun 	if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) {
644*4882a593Smuzhiyun 		struct qib_ibdev *dev;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 		/*
647*4882a593Smuzhiyun 		 * If we couldn't queue the DMA request, save the info
648*4882a593Smuzhiyun 		 * and try again later rather than destroying the
649*4882a593Smuzhiyun 		 * buffer and undoing the side effects of the copy.
650*4882a593Smuzhiyun 		 */
651*4882a593Smuzhiyun 		tx->ss = ss;
652*4882a593Smuzhiyun 		tx->dwords = dwords;
653*4882a593Smuzhiyun 		priv->s_tx = tx;
654*4882a593Smuzhiyun 		dev = &ppd->dd->verbs_dev;
655*4882a593Smuzhiyun 		spin_lock(&dev->rdi.pending_lock);
656*4882a593Smuzhiyun 		if (list_empty(&priv->iowait)) {
657*4882a593Smuzhiyun 			struct qib_ibport *ibp;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 			ibp = &ppd->ibport_data;
660*4882a593Smuzhiyun 			ibp->rvp.n_dmawait++;
661*4882a593Smuzhiyun 			qp->s_flags |= RVT_S_WAIT_DMA_DESC;
662*4882a593Smuzhiyun 			list_add_tail(&priv->iowait, &dev->dmawait);
663*4882a593Smuzhiyun 		}
664*4882a593Smuzhiyun 		spin_unlock(&dev->rdi.pending_lock);
665*4882a593Smuzhiyun 		qp->s_flags &= ~RVT_S_BUSY;
666*4882a593Smuzhiyun 		spin_unlock(&qp->s_lock);
667*4882a593Smuzhiyun 		ret = -EBUSY;
668*4882a593Smuzhiyun 	} else {
669*4882a593Smuzhiyun 		spin_unlock(&qp->s_lock);
670*4882a593Smuzhiyun 		qib_put_txreq(tx);
671*4882a593Smuzhiyun 	}
672*4882a593Smuzhiyun unlock:
673*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
674*4882a593Smuzhiyun 	return ret;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun /*
678*4882a593Smuzhiyun  * sdma_lock should be acquired before calling this routine
679*4882a593Smuzhiyun  */
dump_sdma_state(struct qib_pportdata * ppd)680*4882a593Smuzhiyun void dump_sdma_state(struct qib_pportdata *ppd)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun 	struct qib_sdma_desc *descq;
683*4882a593Smuzhiyun 	struct qib_sdma_txreq *txp, *txpnext;
684*4882a593Smuzhiyun 	__le64 *descqp;
685*4882a593Smuzhiyun 	u64 desc[2];
686*4882a593Smuzhiyun 	u64 addr;
687*4882a593Smuzhiyun 	u16 gen, dwlen, dwoffset;
688*4882a593Smuzhiyun 	u16 head, tail, cnt;
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	head = ppd->sdma_descq_head;
691*4882a593Smuzhiyun 	tail = ppd->sdma_descq_tail;
692*4882a593Smuzhiyun 	cnt = qib_sdma_descq_freecnt(ppd);
693*4882a593Smuzhiyun 	descq = ppd->sdma_descq;
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	qib_dev_porterr(ppd->dd, ppd->port,
696*4882a593Smuzhiyun 		"SDMA ppd->sdma_descq_head: %u\n", head);
697*4882a593Smuzhiyun 	qib_dev_porterr(ppd->dd, ppd->port,
698*4882a593Smuzhiyun 		"SDMA ppd->sdma_descq_tail: %u\n", tail);
699*4882a593Smuzhiyun 	qib_dev_porterr(ppd->dd, ppd->port,
700*4882a593Smuzhiyun 		"SDMA sdma_descq_freecnt: %u\n", cnt);
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	/* print info for each entry in the descriptor queue */
703*4882a593Smuzhiyun 	while (head != tail) {
704*4882a593Smuzhiyun 		char flags[6] = { 'x', 'x', 'x', 'x', 'x', 0 };
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 		descqp = &descq[head].qw[0];
707*4882a593Smuzhiyun 		desc[0] = le64_to_cpu(descqp[0]);
708*4882a593Smuzhiyun 		desc[1] = le64_to_cpu(descqp[1]);
709*4882a593Smuzhiyun 		flags[0] = (desc[0] & 1<<15) ? 'I' : '-';
710*4882a593Smuzhiyun 		flags[1] = (desc[0] & 1<<14) ? 'L' : 'S';
711*4882a593Smuzhiyun 		flags[2] = (desc[0] & 1<<13) ? 'H' : '-';
712*4882a593Smuzhiyun 		flags[3] = (desc[0] & 1<<12) ? 'F' : '-';
713*4882a593Smuzhiyun 		flags[4] = (desc[0] & 1<<11) ? 'L' : '-';
714*4882a593Smuzhiyun 		addr = (desc[1] << 32) | ((desc[0] >> 32) & 0xfffffffcULL);
715*4882a593Smuzhiyun 		gen = (desc[0] >> 30) & 3ULL;
716*4882a593Smuzhiyun 		dwlen = (desc[0] >> 14) & (0x7ffULL << 2);
717*4882a593Smuzhiyun 		dwoffset = (desc[0] & 0x7ffULL) << 2;
718*4882a593Smuzhiyun 		qib_dev_porterr(ppd->dd, ppd->port,
719*4882a593Smuzhiyun 			"SDMA sdmadesc[%u]: flags:%s addr:0x%016llx gen:%u len:%u bytes offset:%u bytes\n",
720*4882a593Smuzhiyun 			 head, flags, addr, gen, dwlen, dwoffset);
721*4882a593Smuzhiyun 		if (++head == ppd->sdma_descq_cnt)
722*4882a593Smuzhiyun 			head = 0;
723*4882a593Smuzhiyun 	}
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	/* print dma descriptor indices from the TX requests */
726*4882a593Smuzhiyun 	list_for_each_entry_safe(txp, txpnext, &ppd->sdma_activelist,
727*4882a593Smuzhiyun 				 list)
728*4882a593Smuzhiyun 		qib_dev_porterr(ppd->dd, ppd->port,
729*4882a593Smuzhiyun 			"SDMA txp->start_idx: %u txp->next_descq_idx: %u\n",
730*4882a593Smuzhiyun 			txp->start_idx, txp->next_descq_idx);
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun 
qib_sdma_process_event(struct qib_pportdata * ppd,enum qib_sdma_events event)733*4882a593Smuzhiyun void qib_sdma_process_event(struct qib_pportdata *ppd,
734*4882a593Smuzhiyun 	enum qib_sdma_events event)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun 	unsigned long flags;
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	spin_lock_irqsave(&ppd->sdma_lock, flags);
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun 	__qib_sdma_process_event(ppd, event);
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	if (ppd->sdma_state.current_state == qib_sdma_state_s99_running)
743*4882a593Smuzhiyun 		qib_verbs_sdma_desc_avail(ppd, qib_sdma_descq_freecnt(ppd));
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun 
__qib_sdma_process_event(struct qib_pportdata * ppd,enum qib_sdma_events event)748*4882a593Smuzhiyun void __qib_sdma_process_event(struct qib_pportdata *ppd,
749*4882a593Smuzhiyun 	enum qib_sdma_events event)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun 	struct qib_sdma_state *ss = &ppd->sdma_state;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	switch (ss->current_state) {
754*4882a593Smuzhiyun 	case qib_sdma_state_s00_hw_down:
755*4882a593Smuzhiyun 		switch (event) {
756*4882a593Smuzhiyun 		case qib_sdma_event_e00_go_hw_down:
757*4882a593Smuzhiyun 			break;
758*4882a593Smuzhiyun 		case qib_sdma_event_e30_go_running:
759*4882a593Smuzhiyun 			/*
760*4882a593Smuzhiyun 			 * If down, but running requested (usually result
761*4882a593Smuzhiyun 			 * of link up, then we need to start up.
762*4882a593Smuzhiyun 			 * This can happen when hw down is requested while
763*4882a593Smuzhiyun 			 * bringing the link up with traffic active on
764*4882a593Smuzhiyun 			 * 7220, e.g. */
765*4882a593Smuzhiyun 			ss->go_s99_running = 1;
766*4882a593Smuzhiyun 			fallthrough;	/* and start dma engine */
767*4882a593Smuzhiyun 		case qib_sdma_event_e10_go_hw_start:
768*4882a593Smuzhiyun 			/* This reference means the state machine is started */
769*4882a593Smuzhiyun 			sdma_get(&ppd->sdma_state);
770*4882a593Smuzhiyun 			sdma_set_state(ppd,
771*4882a593Smuzhiyun 				       qib_sdma_state_s10_hw_start_up_wait);
772*4882a593Smuzhiyun 			break;
773*4882a593Smuzhiyun 		case qib_sdma_event_e20_hw_started:
774*4882a593Smuzhiyun 			break;
775*4882a593Smuzhiyun 		case qib_sdma_event_e40_sw_cleaned:
776*4882a593Smuzhiyun 			sdma_sw_tear_down(ppd);
777*4882a593Smuzhiyun 			break;
778*4882a593Smuzhiyun 		case qib_sdma_event_e50_hw_cleaned:
779*4882a593Smuzhiyun 			break;
780*4882a593Smuzhiyun 		case qib_sdma_event_e60_hw_halted:
781*4882a593Smuzhiyun 			break;
782*4882a593Smuzhiyun 		case qib_sdma_event_e70_go_idle:
783*4882a593Smuzhiyun 			break;
784*4882a593Smuzhiyun 		case qib_sdma_event_e7220_err_halted:
785*4882a593Smuzhiyun 			break;
786*4882a593Smuzhiyun 		case qib_sdma_event_e7322_err_halted:
787*4882a593Smuzhiyun 			break;
788*4882a593Smuzhiyun 		case qib_sdma_event_e90_timer_tick:
789*4882a593Smuzhiyun 			break;
790*4882a593Smuzhiyun 		}
791*4882a593Smuzhiyun 		break;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	case qib_sdma_state_s10_hw_start_up_wait:
794*4882a593Smuzhiyun 		switch (event) {
795*4882a593Smuzhiyun 		case qib_sdma_event_e00_go_hw_down:
796*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s00_hw_down);
797*4882a593Smuzhiyun 			sdma_sw_tear_down(ppd);
798*4882a593Smuzhiyun 			break;
799*4882a593Smuzhiyun 		case qib_sdma_event_e10_go_hw_start:
800*4882a593Smuzhiyun 			break;
801*4882a593Smuzhiyun 		case qib_sdma_event_e20_hw_started:
802*4882a593Smuzhiyun 			sdma_set_state(ppd, ss->go_s99_running ?
803*4882a593Smuzhiyun 				       qib_sdma_state_s99_running :
804*4882a593Smuzhiyun 				       qib_sdma_state_s20_idle);
805*4882a593Smuzhiyun 			break;
806*4882a593Smuzhiyun 		case qib_sdma_event_e30_go_running:
807*4882a593Smuzhiyun 			ss->go_s99_running = 1;
808*4882a593Smuzhiyun 			break;
809*4882a593Smuzhiyun 		case qib_sdma_event_e40_sw_cleaned:
810*4882a593Smuzhiyun 			break;
811*4882a593Smuzhiyun 		case qib_sdma_event_e50_hw_cleaned:
812*4882a593Smuzhiyun 			break;
813*4882a593Smuzhiyun 		case qib_sdma_event_e60_hw_halted:
814*4882a593Smuzhiyun 			break;
815*4882a593Smuzhiyun 		case qib_sdma_event_e70_go_idle:
816*4882a593Smuzhiyun 			ss->go_s99_running = 0;
817*4882a593Smuzhiyun 			break;
818*4882a593Smuzhiyun 		case qib_sdma_event_e7220_err_halted:
819*4882a593Smuzhiyun 			break;
820*4882a593Smuzhiyun 		case qib_sdma_event_e7322_err_halted:
821*4882a593Smuzhiyun 			break;
822*4882a593Smuzhiyun 		case qib_sdma_event_e90_timer_tick:
823*4882a593Smuzhiyun 			break;
824*4882a593Smuzhiyun 		}
825*4882a593Smuzhiyun 		break;
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	case qib_sdma_state_s20_idle:
828*4882a593Smuzhiyun 		switch (event) {
829*4882a593Smuzhiyun 		case qib_sdma_event_e00_go_hw_down:
830*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s00_hw_down);
831*4882a593Smuzhiyun 			sdma_sw_tear_down(ppd);
832*4882a593Smuzhiyun 			break;
833*4882a593Smuzhiyun 		case qib_sdma_event_e10_go_hw_start:
834*4882a593Smuzhiyun 			break;
835*4882a593Smuzhiyun 		case qib_sdma_event_e20_hw_started:
836*4882a593Smuzhiyun 			break;
837*4882a593Smuzhiyun 		case qib_sdma_event_e30_go_running:
838*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s99_running);
839*4882a593Smuzhiyun 			ss->go_s99_running = 1;
840*4882a593Smuzhiyun 			break;
841*4882a593Smuzhiyun 		case qib_sdma_event_e40_sw_cleaned:
842*4882a593Smuzhiyun 			break;
843*4882a593Smuzhiyun 		case qib_sdma_event_e50_hw_cleaned:
844*4882a593Smuzhiyun 			break;
845*4882a593Smuzhiyun 		case qib_sdma_event_e60_hw_halted:
846*4882a593Smuzhiyun 			break;
847*4882a593Smuzhiyun 		case qib_sdma_event_e70_go_idle:
848*4882a593Smuzhiyun 			break;
849*4882a593Smuzhiyun 		case qib_sdma_event_e7220_err_halted:
850*4882a593Smuzhiyun 			break;
851*4882a593Smuzhiyun 		case qib_sdma_event_e7322_err_halted:
852*4882a593Smuzhiyun 			break;
853*4882a593Smuzhiyun 		case qib_sdma_event_e90_timer_tick:
854*4882a593Smuzhiyun 			break;
855*4882a593Smuzhiyun 		}
856*4882a593Smuzhiyun 		break;
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 	case qib_sdma_state_s30_sw_clean_up_wait:
859*4882a593Smuzhiyun 		switch (event) {
860*4882a593Smuzhiyun 		case qib_sdma_event_e00_go_hw_down:
861*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s00_hw_down);
862*4882a593Smuzhiyun 			break;
863*4882a593Smuzhiyun 		case qib_sdma_event_e10_go_hw_start:
864*4882a593Smuzhiyun 			break;
865*4882a593Smuzhiyun 		case qib_sdma_event_e20_hw_started:
866*4882a593Smuzhiyun 			break;
867*4882a593Smuzhiyun 		case qib_sdma_event_e30_go_running:
868*4882a593Smuzhiyun 			ss->go_s99_running = 1;
869*4882a593Smuzhiyun 			break;
870*4882a593Smuzhiyun 		case qib_sdma_event_e40_sw_cleaned:
871*4882a593Smuzhiyun 			sdma_set_state(ppd,
872*4882a593Smuzhiyun 				       qib_sdma_state_s10_hw_start_up_wait);
873*4882a593Smuzhiyun 			sdma_hw_start_up(ppd);
874*4882a593Smuzhiyun 			break;
875*4882a593Smuzhiyun 		case qib_sdma_event_e50_hw_cleaned:
876*4882a593Smuzhiyun 			break;
877*4882a593Smuzhiyun 		case qib_sdma_event_e60_hw_halted:
878*4882a593Smuzhiyun 			break;
879*4882a593Smuzhiyun 		case qib_sdma_event_e70_go_idle:
880*4882a593Smuzhiyun 			ss->go_s99_running = 0;
881*4882a593Smuzhiyun 			break;
882*4882a593Smuzhiyun 		case qib_sdma_event_e7220_err_halted:
883*4882a593Smuzhiyun 			break;
884*4882a593Smuzhiyun 		case qib_sdma_event_e7322_err_halted:
885*4882a593Smuzhiyun 			break;
886*4882a593Smuzhiyun 		case qib_sdma_event_e90_timer_tick:
887*4882a593Smuzhiyun 			break;
888*4882a593Smuzhiyun 		}
889*4882a593Smuzhiyun 		break;
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun 	case qib_sdma_state_s40_hw_clean_up_wait:
892*4882a593Smuzhiyun 		switch (event) {
893*4882a593Smuzhiyun 		case qib_sdma_event_e00_go_hw_down:
894*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s00_hw_down);
895*4882a593Smuzhiyun 			sdma_start_sw_clean_up(ppd);
896*4882a593Smuzhiyun 			break;
897*4882a593Smuzhiyun 		case qib_sdma_event_e10_go_hw_start:
898*4882a593Smuzhiyun 			break;
899*4882a593Smuzhiyun 		case qib_sdma_event_e20_hw_started:
900*4882a593Smuzhiyun 			break;
901*4882a593Smuzhiyun 		case qib_sdma_event_e30_go_running:
902*4882a593Smuzhiyun 			ss->go_s99_running = 1;
903*4882a593Smuzhiyun 			break;
904*4882a593Smuzhiyun 		case qib_sdma_event_e40_sw_cleaned:
905*4882a593Smuzhiyun 			break;
906*4882a593Smuzhiyun 		case qib_sdma_event_e50_hw_cleaned:
907*4882a593Smuzhiyun 			sdma_set_state(ppd,
908*4882a593Smuzhiyun 				       qib_sdma_state_s30_sw_clean_up_wait);
909*4882a593Smuzhiyun 			sdma_start_sw_clean_up(ppd);
910*4882a593Smuzhiyun 			break;
911*4882a593Smuzhiyun 		case qib_sdma_event_e60_hw_halted:
912*4882a593Smuzhiyun 			break;
913*4882a593Smuzhiyun 		case qib_sdma_event_e70_go_idle:
914*4882a593Smuzhiyun 			ss->go_s99_running = 0;
915*4882a593Smuzhiyun 			break;
916*4882a593Smuzhiyun 		case qib_sdma_event_e7220_err_halted:
917*4882a593Smuzhiyun 			break;
918*4882a593Smuzhiyun 		case qib_sdma_event_e7322_err_halted:
919*4882a593Smuzhiyun 			break;
920*4882a593Smuzhiyun 		case qib_sdma_event_e90_timer_tick:
921*4882a593Smuzhiyun 			break;
922*4882a593Smuzhiyun 		}
923*4882a593Smuzhiyun 		break;
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun 	case qib_sdma_state_s50_hw_halt_wait:
926*4882a593Smuzhiyun 		switch (event) {
927*4882a593Smuzhiyun 		case qib_sdma_event_e00_go_hw_down:
928*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s00_hw_down);
929*4882a593Smuzhiyun 			sdma_start_sw_clean_up(ppd);
930*4882a593Smuzhiyun 			break;
931*4882a593Smuzhiyun 		case qib_sdma_event_e10_go_hw_start:
932*4882a593Smuzhiyun 			break;
933*4882a593Smuzhiyun 		case qib_sdma_event_e20_hw_started:
934*4882a593Smuzhiyun 			break;
935*4882a593Smuzhiyun 		case qib_sdma_event_e30_go_running:
936*4882a593Smuzhiyun 			ss->go_s99_running = 1;
937*4882a593Smuzhiyun 			break;
938*4882a593Smuzhiyun 		case qib_sdma_event_e40_sw_cleaned:
939*4882a593Smuzhiyun 			break;
940*4882a593Smuzhiyun 		case qib_sdma_event_e50_hw_cleaned:
941*4882a593Smuzhiyun 			break;
942*4882a593Smuzhiyun 		case qib_sdma_event_e60_hw_halted:
943*4882a593Smuzhiyun 			sdma_set_state(ppd,
944*4882a593Smuzhiyun 				       qib_sdma_state_s40_hw_clean_up_wait);
945*4882a593Smuzhiyun 			ppd->dd->f_sdma_hw_clean_up(ppd);
946*4882a593Smuzhiyun 			break;
947*4882a593Smuzhiyun 		case qib_sdma_event_e70_go_idle:
948*4882a593Smuzhiyun 			ss->go_s99_running = 0;
949*4882a593Smuzhiyun 			break;
950*4882a593Smuzhiyun 		case qib_sdma_event_e7220_err_halted:
951*4882a593Smuzhiyun 			break;
952*4882a593Smuzhiyun 		case qib_sdma_event_e7322_err_halted:
953*4882a593Smuzhiyun 			break;
954*4882a593Smuzhiyun 		case qib_sdma_event_e90_timer_tick:
955*4882a593Smuzhiyun 			break;
956*4882a593Smuzhiyun 		}
957*4882a593Smuzhiyun 		break;
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 	case qib_sdma_state_s99_running:
960*4882a593Smuzhiyun 		switch (event) {
961*4882a593Smuzhiyun 		case qib_sdma_event_e00_go_hw_down:
962*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s00_hw_down);
963*4882a593Smuzhiyun 			sdma_start_sw_clean_up(ppd);
964*4882a593Smuzhiyun 			break;
965*4882a593Smuzhiyun 		case qib_sdma_event_e10_go_hw_start:
966*4882a593Smuzhiyun 			break;
967*4882a593Smuzhiyun 		case qib_sdma_event_e20_hw_started:
968*4882a593Smuzhiyun 			break;
969*4882a593Smuzhiyun 		case qib_sdma_event_e30_go_running:
970*4882a593Smuzhiyun 			break;
971*4882a593Smuzhiyun 		case qib_sdma_event_e40_sw_cleaned:
972*4882a593Smuzhiyun 			break;
973*4882a593Smuzhiyun 		case qib_sdma_event_e50_hw_cleaned:
974*4882a593Smuzhiyun 			break;
975*4882a593Smuzhiyun 		case qib_sdma_event_e60_hw_halted:
976*4882a593Smuzhiyun 			sdma_set_state(ppd,
977*4882a593Smuzhiyun 				       qib_sdma_state_s30_sw_clean_up_wait);
978*4882a593Smuzhiyun 			sdma_start_sw_clean_up(ppd);
979*4882a593Smuzhiyun 			break;
980*4882a593Smuzhiyun 		case qib_sdma_event_e70_go_idle:
981*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s50_hw_halt_wait);
982*4882a593Smuzhiyun 			ss->go_s99_running = 0;
983*4882a593Smuzhiyun 			break;
984*4882a593Smuzhiyun 		case qib_sdma_event_e7220_err_halted:
985*4882a593Smuzhiyun 			sdma_set_state(ppd,
986*4882a593Smuzhiyun 				       qib_sdma_state_s30_sw_clean_up_wait);
987*4882a593Smuzhiyun 			sdma_start_sw_clean_up(ppd);
988*4882a593Smuzhiyun 			break;
989*4882a593Smuzhiyun 		case qib_sdma_event_e7322_err_halted:
990*4882a593Smuzhiyun 			sdma_set_state(ppd, qib_sdma_state_s50_hw_halt_wait);
991*4882a593Smuzhiyun 			break;
992*4882a593Smuzhiyun 		case qib_sdma_event_e90_timer_tick:
993*4882a593Smuzhiyun 			break;
994*4882a593Smuzhiyun 		}
995*4882a593Smuzhiyun 		break;
996*4882a593Smuzhiyun 	}
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun 	ss->last_event = event;
999*4882a593Smuzhiyun }
1000