1 #ifndef _HFI1_IOWAIT_H
2 #define _HFI1_IOWAIT_H
3 /*
4  * Copyright(c) 2015, 2016 Intel Corporation.
5  *
6  * This file is provided under a dual BSD/GPLv2 license.  When using or
7  * redistributing this file, you may do so under either license.
8  *
9  * GPL LICENSE SUMMARY
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of version 2 of the GNU General Public License as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * BSD LICENSE
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  *
26  *  - Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  *  - Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in
30  *    the documentation and/or other materials provided with the
31  *    distribution.
32  *  - Neither the name of Intel Corporation nor the names of its
33  *    contributors may be used to endorse or promote products derived
34  *    from this software without specific prior written permission.
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  *
48  */
49 
50 #include <linux/list.h>
51 #include <linux/workqueue.h>
52 #include <linux/sched.h>
53 
54 #include "sdma_txreq.h"
55 
56 /*
57  * typedef (*restart_t)() - restart callback
58  * @work: pointer to work structure
59  */
60 typedef void (*restart_t)(struct work_struct *work);
61 
62 struct sdma_txreq;
63 struct sdma_engine;
64 /**
65  * struct iowait - linkage for delayed progress/waiting
66  * @list: used to add/insert into QP/PQ wait lists
67  * @lock: uses to record the list head lock
68  * @tx_head: overflow list of sdma_txreq's
69  * @sleep: no space callback
70  * @wakeup: space callback wakeup
71  * @sdma_drained: sdma count drained
72  * @iowork: workqueue overhead
73  * @wait_dma: wait for sdma_busy == 0
74  * @wait_pio: wait for pio_busy == 0
75  * @sdma_busy: # of packets in flight
76  * @count: total number of descriptors in tx_head'ed list
77  * @tx_limit: limit for overflow queuing
78  * @tx_count: number of tx entry's in tx_head'ed list
79  *
80  * This is to be embedded in user's state structure
81  * (QP or PQ).
82  *
83  * The sleep and wakeup members are a
84  * bit misnamed.   They do not strictly
85  * speaking sleep or wake up, but they
86  * are callbacks for the ULP to implement
87  * what ever queuing/dequeuing of
88  * the embedded iowait and its containing struct
89  * when a resource shortage like SDMA ring space is seen.
90  *
91  * Both potentially have locks help
92  * so sleeping is not allowed.
93  *
94  * The wait_dma member along with the iow
95  *
96  * The lock field is used by waiters to record
97  * the seqlock_t that guards the list head.
98  * Waiters explicity know that, but the destroy
99  * code that unwaits QPs does not.
100  */
101 
102 struct iowait {
103 	struct list_head list;
104 	struct list_head tx_head;
105 	int (*sleep)(
106 		struct sdma_engine *sde,
107 		struct iowait *wait,
108 		struct sdma_txreq *tx,
109 		unsigned seq);
110 	void (*wakeup)(struct iowait *wait, int reason);
111 	void (*sdma_drained)(struct iowait *wait);
112 	seqlock_t *lock;
113 	struct work_struct iowork;
114 	wait_queue_head_t wait_dma;
115 	wait_queue_head_t wait_pio;
116 	atomic_t sdma_busy;
117 	atomic_t pio_busy;
118 	u32 count;
119 	u32 tx_limit;
120 	u32 tx_count;
121 };
122 
123 #define SDMA_AVAIL_REASON 0
124 
125 /**
126  * iowait_init() - initialize wait structure
127  * @wait: wait struct to initialize
128  * @tx_limit: limit for overflow queuing
129  * @func: restart function for workqueue
130  * @sleep: sleep function for no space
131  * @resume: wakeup function for no space
132  *
133  * This function initializes the iowait
134  * structure embedded in the QP or PQ.
135  *
136  */
137 
138 static inline void iowait_init(
139 	struct iowait *wait,
140 	u32 tx_limit,
141 	void (*func)(struct work_struct *work),
142 	int (*sleep)(
143 		struct sdma_engine *sde,
144 		struct iowait *wait,
145 		struct sdma_txreq *tx,
146 		unsigned seq),
147 	void (*wakeup)(struct iowait *wait, int reason),
148 	void (*sdma_drained)(struct iowait *wait))
149 {
150 	wait->count = 0;
151 	wait->lock = NULL;
152 	INIT_LIST_HEAD(&wait->list);
153 	INIT_LIST_HEAD(&wait->tx_head);
154 	INIT_WORK(&wait->iowork, func);
155 	init_waitqueue_head(&wait->wait_dma);
156 	init_waitqueue_head(&wait->wait_pio);
157 	atomic_set(&wait->sdma_busy, 0);
158 	atomic_set(&wait->pio_busy, 0);
159 	wait->tx_limit = tx_limit;
160 	wait->sleep = sleep;
161 	wait->wakeup = wakeup;
162 	wait->sdma_drained = sdma_drained;
163 }
164 
165 /**
166  * iowait_schedule() - initialize wait structure
167  * @wait: wait struct to schedule
168  * @wq: workqueue for schedule
169  * @cpu: cpu
170  */
171 static inline void iowait_schedule(
172 	struct iowait *wait,
173 	struct workqueue_struct *wq,
174 	int cpu)
175 {
176 	queue_work_on(cpu, wq, &wait->iowork);
177 }
178 
179 /**
180  * iowait_sdma_drain() - wait for DMAs to drain
181  *
182  * @wait: iowait structure
183  *
184  * This will delay until the iowait sdmas have
185  * completed.
186  */
187 static inline void iowait_sdma_drain(struct iowait *wait)
188 {
189 	wait_event(wait->wait_dma, !atomic_read(&wait->sdma_busy));
190 }
191 
192 /**
193  * iowait_sdma_pending() - return sdma pending count
194  *
195  * @wait: iowait structure
196  *
197  */
198 static inline int iowait_sdma_pending(struct iowait *wait)
199 {
200 	return atomic_read(&wait->sdma_busy);
201 }
202 
203 /**
204  * iowait_sdma_inc - note sdma io pending
205  * @wait: iowait structure
206  */
207 static inline void iowait_sdma_inc(struct iowait *wait)
208 {
209 	atomic_inc(&wait->sdma_busy);
210 }
211 
212 /**
213  * iowait_sdma_add - add count to pending
214  * @wait: iowait structure
215  */
216 static inline void iowait_sdma_add(struct iowait *wait, int count)
217 {
218 	atomic_add(count, &wait->sdma_busy);
219 }
220 
221 /**
222  * iowait_sdma_dec - note sdma complete
223  * @wait: iowait structure
224  */
225 static inline int iowait_sdma_dec(struct iowait *wait)
226 {
227 	return atomic_dec_and_test(&wait->sdma_busy);
228 }
229 
230 /**
231  * iowait_pio_drain() - wait for pios to drain
232  *
233  * @wait: iowait structure
234  *
235  * This will delay until the iowait pios have
236  * completed.
237  */
238 static inline void iowait_pio_drain(struct iowait *wait)
239 {
240 	wait_event_timeout(wait->wait_pio,
241 			   !atomic_read(&wait->pio_busy),
242 			   HZ);
243 }
244 
245 /**
246  * iowait_pio_pending() - return pio pending count
247  *
248  * @wait: iowait structure
249  *
250  */
251 static inline int iowait_pio_pending(struct iowait *wait)
252 {
253 	return atomic_read(&wait->pio_busy);
254 }
255 
256 /**
257  * iowait_pio_inc - note pio pending
258  * @wait: iowait structure
259  */
260 static inline void iowait_pio_inc(struct iowait *wait)
261 {
262 	atomic_inc(&wait->pio_busy);
263 }
264 
265 /**
266  * iowait_sdma_dec - note pio complete
267  * @wait: iowait structure
268  */
269 static inline int iowait_pio_dec(struct iowait *wait)
270 {
271 	return atomic_dec_and_test(&wait->pio_busy);
272 }
273 
274 /**
275  * iowait_drain_wakeup() - trigger iowait_drain() waiter
276  *
277  * @wait: iowait structure
278  *
279  * This will trigger any waiters.
280  */
281 static inline void iowait_drain_wakeup(struct iowait *wait)
282 {
283 	wake_up(&wait->wait_dma);
284 	wake_up(&wait->wait_pio);
285 	if (wait->sdma_drained)
286 		wait->sdma_drained(wait);
287 }
288 
289 /**
290  * iowait_get_txhead() - get packet off of iowait list
291  *
292  * @wait wait struture
293  */
294 static inline struct sdma_txreq *iowait_get_txhead(struct iowait *wait)
295 {
296 	struct sdma_txreq *tx = NULL;
297 
298 	if (!list_empty(&wait->tx_head)) {
299 		tx = list_first_entry(
300 			&wait->tx_head,
301 			struct sdma_txreq,
302 			list);
303 		list_del_init(&tx->list);
304 	}
305 	return tx;
306 }
307 
308 #endif
309