]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ioat/ioat_internal.h
ntb: Revert r290130 now that r290156 has landed
[FreeBSD/FreeBSD.git] / sys / dev / ioat / ioat_internal.h
1 /*-
2  * Copyright (C) 2012 Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 __FBSDID("$FreeBSD$");
28
29 #ifndef __IOAT_INTERNAL_H__
30 #define __IOAT_INTERNAL_H__
31
32 #define DEVICE2SOFTC(dev)       ((struct ioat_softc *) device_get_softc(dev))
33 #define KTR_IOAT                KTR_SPARE3
34
35 #define ioat_read_chancnt(ioat) \
36         ioat_read_1((ioat), IOAT_CHANCNT_OFFSET)
37
38 #define ioat_read_xfercap(ioat) \
39         (ioat_read_1((ioat), IOAT_XFERCAP_OFFSET) & IOAT_XFERCAP_VALID_MASK)
40
41 #define ioat_write_intrctrl(ioat, value) \
42         ioat_write_1((ioat), IOAT_INTRCTRL_OFFSET, (value))
43
44 #define ioat_read_cbver(ioat) \
45         (ioat_read_1((ioat), IOAT_CBVER_OFFSET) & 0xFF)
46
47 #define ioat_read_dmacapability(ioat) \
48         ioat_read_4((ioat), IOAT_DMACAPABILITY_OFFSET)
49
50 #define ioat_write_chanctrl(ioat, value) \
51         ioat_write_2((ioat), IOAT_CHANCTRL_OFFSET, (value))
52
53 static __inline uint64_t
54 ioat_bus_space_read_8_lower_first(bus_space_tag_t tag,
55     bus_space_handle_t handle, bus_size_t offset)
56 {
57         return (bus_space_read_4(tag, handle, offset) |
58             ((uint64_t)bus_space_read_4(tag, handle, offset + 4)) << 32);
59 }
60
61 static __inline void
62 ioat_bus_space_write_8_lower_first(bus_space_tag_t tag,
63     bus_space_handle_t handle, bus_size_t offset, uint64_t val)
64 {
65         bus_space_write_4(tag, handle, offset, val);
66         bus_space_write_4(tag, handle, offset + 4, val >> 32);
67 }
68
69 #ifdef __i386__
70 #define ioat_bus_space_read_8 ioat_bus_space_read_8_lower_first
71 #define ioat_bus_space_write_8 ioat_bus_space_write_8_lower_first
72 #else
73 #define ioat_bus_space_read_8(tag, handle, offset) \
74         bus_space_read_8((tag), (handle), (offset))
75 #define ioat_bus_space_write_8(tag, handle, offset, val) \
76         bus_space_write_8((tag), (handle), (offset), (val))
77 #endif
78
79 #define ioat_read_1(ioat, offset) \
80         bus_space_read_1((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
81             (offset))
82
83 #define ioat_read_2(ioat, offset) \
84         bus_space_read_2((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
85             (offset))
86
87 #define ioat_read_4(ioat, offset) \
88         bus_space_read_4((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
89             (offset))
90
91 #define ioat_read_8(ioat, offset) \
92         ioat_bus_space_read_8((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
93             (offset))
94
95 #define ioat_read_double_4(ioat, offset) \
96         ioat_bus_space_read_8_lower_first((ioat)->pci_bus_tag, \
97             (ioat)->pci_bus_handle, (offset))
98
99 #define ioat_write_1(ioat, offset, value) \
100         bus_space_write_1((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
101             (offset), (value))
102
103 #define ioat_write_2(ioat, offset, value) \
104         bus_space_write_2((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
105             (offset), (value))
106
107 #define ioat_write_4(ioat, offset, value) \
108         bus_space_write_4((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
109             (offset), (value))
110
111 #define ioat_write_8(ioat, offset, value) \
112         ioat_bus_space_write_8((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
113             (offset), (value))
114
115 #define ioat_write_double_4(ioat, offset, value) \
116         ioat_bus_space_write_8_lower_first((ioat)->pci_bus_tag, \
117             (ioat)->pci_bus_handle, (offset), (value))
118
119 MALLOC_DECLARE(M_IOAT);
120
121 SYSCTL_DECL(_hw_ioat);
122
123 extern int g_ioat_debug_level;
124
125 struct generic_dma_control {
126         uint32_t int_enable:1;
127         uint32_t src_snoop_disable:1;
128         uint32_t dest_snoop_disable:1;
129         uint32_t completion_update:1;
130         uint32_t fence:1;
131         uint32_t reserved1:1;
132         uint32_t src_page_break:1;
133         uint32_t dest_page_break:1;
134         uint32_t bundle:1;
135         uint32_t dest_dca:1;
136         uint32_t hint:1;
137         uint32_t reserved2:13;
138         uint32_t op:8;
139 };
140
141 struct ioat_generic_hw_descriptor {
142         uint32_t size;
143         union {
144                 uint32_t control_raw;
145                 struct generic_dma_control control_generic;
146         } u;
147         uint64_t src_addr;
148         uint64_t dest_addr;
149         uint64_t next;
150         uint64_t reserved[4];
151 };
152
153 struct ioat_dma_hw_descriptor {
154         uint32_t size;
155         union {
156                 uint32_t control_raw;
157                 struct generic_dma_control control_generic;
158                 struct {
159                         uint32_t int_enable:1;
160                         uint32_t src_snoop_disable:1;
161                         uint32_t dest_snoop_disable:1;
162                         uint32_t completion_update:1;
163                         uint32_t fence:1;
164                         uint32_t null:1;
165                         uint32_t src_page_break:1;
166                         uint32_t dest_page_break:1;
167                         uint32_t bundle:1;
168                         uint32_t dest_dca:1;
169                         uint32_t hint:1;
170                         uint32_t reserved:13;
171                         #define IOAT_OP_COPY 0x00
172                         uint32_t op:8;
173                 } control;
174         } u;
175         uint64_t src_addr;
176         uint64_t dest_addr;
177         uint64_t next;
178         uint64_t reserved;
179         uint64_t reserved2;
180         uint64_t user1;
181         uint64_t user2;
182 };
183
184 struct ioat_fill_hw_descriptor {
185         uint32_t size;
186         union {
187                 uint32_t control_raw;
188                 struct generic_dma_control control_generic;
189                 struct {
190                         uint32_t int_enable:1;
191                         uint32_t reserved:1;
192                         uint32_t dest_snoop_disable:1;
193                         uint32_t completion_update:1;
194                         uint32_t fence:1;
195                         uint32_t reserved2:2;
196                         uint32_t dest_page_break:1;
197                         uint32_t bundle:1;
198                         uint32_t reserved3:15;
199                         #define IOAT_OP_FILL 0x01
200                         uint32_t op:8;
201                 } control;
202         } u;
203         uint64_t src_data;
204         uint64_t dest_addr;
205         uint64_t next;
206         uint64_t reserved;
207         uint64_t next_dest_addr;
208         uint64_t user1;
209         uint64_t user2;
210 };
211
212 struct ioat_xor_hw_descriptor {
213         uint32_t size;
214         union {
215                 uint32_t control_raw;
216                 struct generic_dma_control control_generic;
217                 struct {
218                         uint32_t int_enable:1;
219                         uint32_t src_snoop_disable:1;
220                         uint32_t dest_snoop_disable:1;
221                         uint32_t completion_update:1;
222                         uint32_t fence:1;
223                         uint32_t src_count:3;
224                         uint32_t bundle:1;
225                         uint32_t dest_dca:1;
226                         uint32_t hint:1;
227                         uint32_t reserved:13;
228                         #define IOAT_OP_XOR 0x87
229                         #define IOAT_OP_XOR_VAL 0x88
230                         uint32_t op:8;
231                 } control;
232         } u;
233         uint64_t src_addr;
234         uint64_t dest_addr;
235         uint64_t next;
236         uint64_t src_addr2;
237         uint64_t src_addr3;
238         uint64_t src_addr4;
239         uint64_t src_addr5;
240 };
241
242 struct ioat_xor_ext_hw_descriptor {
243         uint64_t src_addr6;
244         uint64_t src_addr7;
245         uint64_t src_addr8;
246         uint64_t next;
247         uint64_t reserved[4];
248 };
249
250 struct ioat_pq_hw_descriptor {
251         uint32_t size;
252         union {
253                 uint32_t control_raw;
254                 struct generic_dma_control control_generic;
255                 struct {
256                         uint32_t int_enable:1;
257                         uint32_t src_snoop_disable:1;
258                         uint32_t dest_snoop_disable:1;
259                         uint32_t completion_update:1;
260                         uint32_t fence:1;
261                         uint32_t src_count:3;
262                         uint32_t bundle:1;
263                         uint32_t dest_dca:1;
264                         uint32_t hint:1;
265                         uint32_t p_disable:1;
266                         uint32_t q_disable:1;
267                         uint32_t reserved:11;
268                         #define IOAT_OP_PQ 0x89
269                         #define IOAT_OP_PQ_VAL 0x8a
270                         uint32_t op:8;
271                 } control;
272         } u;
273         uint64_t src_addr;
274         uint64_t p_addr;
275         uint64_t next;
276         uint64_t src_addr2;
277         uint64_t src_addr3;
278         uint8_t  coef[8];
279         uint64_t q_addr;
280 };
281
282 struct ioat_pq_ext_hw_descriptor {
283         uint64_t src_addr4;
284         uint64_t src_addr5;
285         uint64_t src_addr6;
286         uint64_t next;
287         uint64_t src_addr7;
288         uint64_t src_addr8;
289         uint64_t reserved[2];
290 };
291
292 struct ioat_pq_update_hw_descriptor {
293         uint32_t size;
294         union {
295                 uint32_t control_raw;
296                 struct generic_dma_control control_generic;
297                 struct {
298                         uint32_t int_enable:1;
299                         uint32_t src_snoop_disable:1;
300                         uint32_t dest_snoop_disable:1;
301                         uint32_t completion_update:1;
302                         uint32_t fence:1;
303                         uint32_t src_cnt:3;
304                         uint32_t bundle:1;
305                         uint32_t dest_dca:1;
306                         uint32_t hint:1;
307                         uint32_t p_disable:1;
308                         uint32_t q_disable:1;
309                         uint32_t reserved:3;
310                         uint32_t coef:8;
311                         #define IOAT_OP_PQ_UP 0x8b
312                         uint32_t op:8;
313                 } control;
314         } u;
315         uint64_t src_addr;
316         uint64_t p_addr;
317         uint64_t next;
318         uint64_t src_addr2;
319         uint64_t p_src;
320         uint64_t q_src;
321         uint64_t q_addr;
322 };
323
324 struct ioat_raw_hw_descriptor {
325         uint64_t field[8];
326 };
327
328 struct bus_dmadesc {
329         bus_dmaengine_callback_t callback_fn;
330         void                     *callback_arg;
331 };
332
333 struct ioat_descriptor {
334         struct bus_dmadesc      bus_dmadesc;
335         union {
336                 struct ioat_generic_hw_descriptor       *generic;
337                 struct ioat_dma_hw_descriptor           *dma;
338                 struct ioat_fill_hw_descriptor          *fill;
339                 struct ioat_xor_hw_descriptor           *xor;
340                 struct ioat_xor_ext_hw_descriptor       *xor_ext;
341                 struct ioat_pq_hw_descriptor            *pq;
342                 struct ioat_pq_ext_hw_descriptor        *pq_ext;
343                 struct ioat_raw_hw_descriptor           *raw;
344         } u;
345         uint32_t                id;
346         uint32_t                length;
347         enum validate_flags     *validate_result;
348         bus_addr_t              hw_desc_bus_addr;
349 };
350
351 enum ioat_ref_kind {
352         IOAT_DMAENGINE_REF = 0,
353         IOAT_ACTIVE_DESCR_REF,
354         IOAT_NUM_REF_KINDS
355 };
356
357 /* One of these per allocated PCI device. */
358 struct ioat_softc {
359         bus_dmaengine_t         dmaengine;
360 #define to_ioat_softc(_dmaeng)                                          \
361 ({                                                                      \
362         bus_dmaengine_t *_p = (_dmaeng);                                \
363         (struct ioat_softc *)((char *)_p -                              \
364             offsetof(struct ioat_softc, dmaengine));                    \
365 })
366
367         int                     version;
368         int                     chan_idx;
369
370         struct mtx              submit_lock;
371         device_t                device;
372         bus_space_tag_t         pci_bus_tag;
373         bus_space_handle_t      pci_bus_handle;
374         int                     pci_resource_id;
375         struct resource         *pci_resource;
376         uint32_t                max_xfer_size;
377         uint32_t                capabilities;
378
379         struct resource         *res;
380         int                     rid;
381         void                    *tag;
382
383         bus_dma_tag_t           hw_desc_tag;
384         bus_dmamap_t            hw_desc_map;
385
386         bus_dma_tag_t           comp_update_tag;
387         bus_dmamap_t            comp_update_map;
388         uint64_t                *comp_update;
389         bus_addr_t              comp_update_bus_addr;
390
391         struct callout          timer;
392
393         boolean_t               quiescing;
394         boolean_t               is_resize_pending;
395         boolean_t               is_completion_pending;
396         boolean_t               is_reset_pending;
397         boolean_t               is_channel_running;
398
399         uint32_t                head;
400         uint32_t                tail;
401         uint32_t                hw_head;
402         uint32_t                ring_size_order;
403         bus_addr_t              last_seen;
404
405         struct ioat_descriptor  **ring;
406
407         struct mtx              cleanup_lock;
408         volatile uint32_t       refcnt;
409 #ifdef INVARIANTS
410         volatile uint32_t       refkinds[IOAT_NUM_REF_KINDS];
411 #endif
412 };
413
414 void ioat_test_attach(void);
415 void ioat_test_detach(void);
416
417 static inline uint64_t
418 ioat_get_chansts(struct ioat_softc *ioat)
419 {
420         uint64_t status;
421
422         if (ioat->version >= IOAT_VER_3_3)
423                 status = ioat_read_8(ioat, IOAT_CHANSTS_OFFSET);
424         else
425                 /* Must read lower 4 bytes before upper 4 bytes. */
426                 status = ioat_read_double_4(ioat, IOAT_CHANSTS_OFFSET);
427         return (status);
428 }
429
430 static inline void
431 ioat_write_chancmp(struct ioat_softc *ioat, uint64_t addr)
432 {
433
434         if (ioat->version >= IOAT_VER_3_3)
435                 ioat_write_8(ioat, IOAT_CHANCMP_OFFSET_LOW, addr);
436         else
437                 ioat_write_double_4(ioat, IOAT_CHANCMP_OFFSET_LOW, addr);
438 }
439
440 static inline void
441 ioat_write_chainaddr(struct ioat_softc *ioat, uint64_t addr)
442 {
443
444         if (ioat->version >= IOAT_VER_3_3)
445                 ioat_write_8(ioat, IOAT_CHAINADDR_OFFSET_LOW, addr);
446         else
447                 ioat_write_double_4(ioat, IOAT_CHAINADDR_OFFSET_LOW, addr);
448 }
449
450 static inline boolean_t
451 is_ioat_active(uint64_t status)
452 {
453         return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_ACTIVE);
454 }
455
456 static inline boolean_t
457 is_ioat_idle(uint64_t status)
458 {
459         return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_IDLE);
460 }
461
462 static inline boolean_t
463 is_ioat_halted(uint64_t status)
464 {
465         return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_HALTED);
466 }
467
468 static inline boolean_t
469 is_ioat_suspended(uint64_t status)
470 {
471         return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_SUSPENDED);
472 }
473
474 static inline void
475 ioat_suspend(struct ioat_softc *ioat)
476 {
477         ioat_write_1(ioat, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_SUSPEND);
478 }
479
480 static inline void
481 ioat_reset(struct ioat_softc *ioat)
482 {
483         ioat_write_1(ioat, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
484 }
485
486 static inline boolean_t
487 ioat_reset_pending(struct ioat_softc *ioat)
488 {
489         uint8_t cmd;
490
491         cmd = ioat_read_1(ioat, IOAT_CHANCMD_OFFSET);
492         return ((cmd & IOAT_CHANCMD_RESET) != 0);
493 }
494
495 #endif /* __IOAT_INTERNAL_H__ */