ioat_internal.h revision 300661
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: stable/10/sys/dev/ioat/ioat_internal.h 300661 2016-05-25 07:09:54Z mav $");
28
29#ifndef __IOAT_INTERNAL_H__
30#define __IOAT_INTERNAL_H__
31
32#include <sys/_task.h>
33
34#define	DEVICE2SOFTC(dev)	((struct ioat_softc *) device_get_softc(dev))
35#define	KTR_IOAT		KTR_SPARE3
36
37#define	ioat_read_chancnt(ioat) \
38	ioat_read_1((ioat), IOAT_CHANCNT_OFFSET)
39
40#define	ioat_read_xfercap(ioat) \
41	(ioat_read_1((ioat), IOAT_XFERCAP_OFFSET) & IOAT_XFERCAP_VALID_MASK)
42
43#define	ioat_write_intrctrl(ioat, value) \
44	ioat_write_1((ioat), IOAT_INTRCTRL_OFFSET, (value))
45
46#define	ioat_read_cbver(ioat) \
47	(ioat_read_1((ioat), IOAT_CBVER_OFFSET) & 0xFF)
48
49#define	ioat_read_dmacapability(ioat) \
50	ioat_read_4((ioat), IOAT_DMACAPABILITY_OFFSET)
51
52#define	ioat_write_chanctrl(ioat, value) \
53	ioat_write_2((ioat), IOAT_CHANCTRL_OFFSET, (value))
54
55static __inline uint64_t
56ioat_bus_space_read_8_lower_first(bus_space_tag_t tag,
57    bus_space_handle_t handle, bus_size_t offset)
58{
59	return (bus_space_read_4(tag, handle, offset) |
60	    ((uint64_t)bus_space_read_4(tag, handle, offset + 4)) << 32);
61}
62
63static __inline void
64ioat_bus_space_write_8_lower_first(bus_space_tag_t tag,
65    bus_space_handle_t handle, bus_size_t offset, uint64_t val)
66{
67	bus_space_write_4(tag, handle, offset, val);
68	bus_space_write_4(tag, handle, offset + 4, val >> 32);
69}
70
71#ifdef __i386__
72#define ioat_bus_space_read_8 ioat_bus_space_read_8_lower_first
73#define ioat_bus_space_write_8 ioat_bus_space_write_8_lower_first
74#else
75#define ioat_bus_space_read_8(tag, handle, offset) \
76	bus_space_read_8((tag), (handle), (offset))
77#define ioat_bus_space_write_8(tag, handle, offset, val) \
78	bus_space_write_8((tag), (handle), (offset), (val))
79#endif
80
81#define ioat_read_1(ioat, offset) \
82	bus_space_read_1((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
83	    (offset))
84
85#define ioat_read_2(ioat, offset) \
86	bus_space_read_2((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
87	    (offset))
88
89#define ioat_read_4(ioat, offset) \
90	bus_space_read_4((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
91	    (offset))
92
93#define ioat_read_8(ioat, offset) \
94	ioat_bus_space_read_8((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
95	    (offset))
96
97#define ioat_read_double_4(ioat, offset) \
98	ioat_bus_space_read_8_lower_first((ioat)->pci_bus_tag, \
99	    (ioat)->pci_bus_handle, (offset))
100
101#define ioat_write_1(ioat, offset, value) \
102	bus_space_write_1((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
103	    (offset), (value))
104
105#define ioat_write_2(ioat, offset, value) \
106	bus_space_write_2((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
107	    (offset), (value))
108
109#define ioat_write_4(ioat, offset, value) \
110	bus_space_write_4((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
111	    (offset), (value))
112
113#define ioat_write_8(ioat, offset, value) \
114	ioat_bus_space_write_8((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
115	    (offset), (value))
116
117#define ioat_write_double_4(ioat, offset, value) \
118	ioat_bus_space_write_8_lower_first((ioat)->pci_bus_tag, \
119	    (ioat)->pci_bus_handle, (offset), (value))
120
121MALLOC_DECLARE(M_IOAT);
122
123SYSCTL_DECL(_hw_ioat);
124
125extern int g_ioat_debug_level;
126
127struct generic_dma_control {
128	uint32_t int_enable:1;
129	uint32_t src_snoop_disable:1;
130	uint32_t dest_snoop_disable:1;
131	uint32_t completion_update:1;
132	uint32_t fence:1;
133	uint32_t reserved1:1;
134	uint32_t src_page_break:1;
135	uint32_t dest_page_break:1;
136	uint32_t bundle:1;
137	uint32_t dest_dca:1;
138	uint32_t hint:1;
139	uint32_t reserved2:13;
140	uint32_t op:8;
141};
142
143struct ioat_generic_hw_descriptor {
144	uint32_t size;
145	union {
146		uint32_t control_raw;
147		struct generic_dma_control control_generic;
148	} u;
149	uint64_t src_addr;
150	uint64_t dest_addr;
151	uint64_t next;
152	uint64_t reserved[4];
153};
154
155struct ioat_dma_hw_descriptor {
156	uint32_t size;
157	union {
158		uint32_t control_raw;
159		struct generic_dma_control control_generic;
160		struct {
161			uint32_t int_enable:1;
162			uint32_t src_snoop_disable:1;
163			uint32_t dest_snoop_disable:1;
164			uint32_t completion_update:1;
165			uint32_t fence:1;
166			uint32_t null:1;
167			uint32_t src_page_break:1;
168			uint32_t dest_page_break:1;
169			uint32_t bundle:1;
170			uint32_t dest_dca:1;
171			uint32_t hint:1;
172			uint32_t reserved:13;
173			#define IOAT_OP_COPY 0x00
174			uint32_t op:8;
175		} control;
176	} u;
177	uint64_t src_addr;
178	uint64_t dest_addr;
179	uint64_t next;
180	uint64_t next_src_addr;
181	uint64_t next_dest_addr;
182	uint64_t user1;
183	uint64_t user2;
184};
185
186struct ioat_fill_hw_descriptor {
187	uint32_t size;
188	union {
189		uint32_t control_raw;
190		struct generic_dma_control control_generic;
191		struct {
192			uint32_t int_enable:1;
193			uint32_t reserved:1;
194			uint32_t dest_snoop_disable:1;
195			uint32_t completion_update:1;
196			uint32_t fence:1;
197			uint32_t reserved2:2;
198			uint32_t dest_page_break:1;
199			uint32_t bundle:1;
200			uint32_t reserved3:15;
201			#define IOAT_OP_FILL 0x01
202			uint32_t op:8;
203		} control;
204	} u;
205	uint64_t src_data;
206	uint64_t dest_addr;
207	uint64_t next;
208	uint64_t reserved;
209	uint64_t next_dest_addr;
210	uint64_t user1;
211	uint64_t user2;
212};
213
214struct ioat_crc32_hw_descriptor {
215	uint32_t size;
216	union {
217		uint32_t control_raw;
218		struct generic_dma_control control_generic;
219		struct {
220			uint32_t int_enable:1;
221			uint32_t src_snoop_disable:1;
222			uint32_t dest_snoop_disable:1;
223			uint32_t completion_update:1;
224			uint32_t fence:1;
225			uint32_t reserved1:3;
226			uint32_t bundle:1;
227			uint32_t dest_dca:1;
228			uint32_t hint:1;
229			uint32_t use_seed:1;
230			/*
231			 * crc_location:
232			 * For IOAT_OP_MOVECRC_TEST and IOAT_OP_CRC_TEST:
233			 * 0: comparison value is pointed to by CRC Address
234			 *    field.
235			 * 1: comparison value follows data in wire format
236			 *    ("inverted reflected bit order") in the 4 bytes
237			 *    following the source data.
238			 *
239			 * For IOAT_OP_CRC_STORE:
240			 * 0: Result will be stored at location pointed to by
241			 *    CRC Address field (in wire format).
242			 * 1: Result will be stored directly following the
243			 *    source data.
244			 *
245			 * For IOAT_OP_MOVECRC_STORE:
246			 * 0: Result will be stored at location pointed to by
247			 *    CRC Address field (in wire format).
248			 * 1: Result will be stored directly following the
249			 *    *destination* data.
250			 */
251			uint32_t crc_location:1;
252			uint32_t reserved2:11;
253			/*
254			 * MOVECRC - Move data in the same way as standard copy
255			 * operation, but also compute CRC32.
256			 *
257			 * CRC - Only compute CRC on source data.
258			 *
259			 * There is a CRC accumulator register in the hardware.
260			 * If 'initial' is set, it is initialized to the value
261			 * in 'seed.'
262			 *
263			 * In all modes, these operators accumulate size bytes
264			 * at src_addr into the running CRC32C.
265			 *
266			 * Store mode emits the accumulated CRC, in wire
267			 * format, as specified by the crc_location bit above.
268			 *
269			 * Test mode compares the accumulated CRC against the
270			 * reference CRC, as described in crc_location above.
271			 * On failure, halts the DMA engine with a CRC error
272			 * status.
273			 */
274			#define	IOAT_OP_MOVECRC		0x41
275			#define	IOAT_OP_MOVECRC_TEST	0x42
276			#define	IOAT_OP_MOVECRC_STORE	0x43
277			#define	IOAT_OP_CRC		0x81
278			#define	IOAT_OP_CRC_TEST	0x82
279			#define	IOAT_OP_CRC_STORE	0x83
280			uint32_t op:8;
281		} control;
282	} u;
283	uint64_t src_addr;
284	uint64_t dest_addr;
285	uint64_t next;
286	uint64_t next_src_addr;
287	uint64_t next_dest_addr;
288	uint32_t seed;
289	uint32_t reserved;
290	uint64_t crc_address;
291};
292
293struct ioat_xor_hw_descriptor {
294	uint32_t size;
295	union {
296		uint32_t control_raw;
297		struct generic_dma_control control_generic;
298		struct {
299			uint32_t int_enable:1;
300			uint32_t src_snoop_disable:1;
301			uint32_t dest_snoop_disable:1;
302			uint32_t completion_update:1;
303			uint32_t fence:1;
304			uint32_t src_count:3;
305			uint32_t bundle:1;
306			uint32_t dest_dca:1;
307			uint32_t hint:1;
308			uint32_t reserved:13;
309			#define IOAT_OP_XOR 0x87
310			#define IOAT_OP_XOR_VAL 0x88
311			uint32_t op:8;
312		} control;
313	} u;
314	uint64_t src_addr;
315	uint64_t dest_addr;
316	uint64_t next;
317	uint64_t src_addr2;
318	uint64_t src_addr3;
319	uint64_t src_addr4;
320	uint64_t src_addr5;
321};
322
323struct ioat_xor_ext_hw_descriptor {
324	uint64_t src_addr6;
325	uint64_t src_addr7;
326	uint64_t src_addr8;
327	uint64_t next;
328	uint64_t reserved[4];
329};
330
331struct ioat_pq_hw_descriptor {
332	uint32_t size;
333	union {
334		uint32_t control_raw;
335		struct generic_dma_control control_generic;
336		struct {
337			uint32_t int_enable:1;
338			uint32_t src_snoop_disable:1;
339			uint32_t dest_snoop_disable:1;
340			uint32_t completion_update:1;
341			uint32_t fence:1;
342			uint32_t src_count:3;
343			uint32_t bundle:1;
344			uint32_t dest_dca:1;
345			uint32_t hint:1;
346			uint32_t p_disable:1;
347			uint32_t q_disable:1;
348			uint32_t reserved:11;
349			#define IOAT_OP_PQ 0x89
350			#define IOAT_OP_PQ_VAL 0x8a
351			uint32_t op:8;
352		} control;
353	} u;
354	uint64_t src_addr;
355	uint64_t p_addr;
356	uint64_t next;
357	uint64_t src_addr2;
358	uint64_t src_addr3;
359	uint8_t  coef[8];
360	uint64_t q_addr;
361};
362
363struct ioat_pq_ext_hw_descriptor {
364	uint64_t src_addr4;
365	uint64_t src_addr5;
366	uint64_t src_addr6;
367	uint64_t next;
368	uint64_t src_addr7;
369	uint64_t src_addr8;
370	uint64_t reserved[2];
371};
372
373struct ioat_pq_update_hw_descriptor {
374	uint32_t size;
375	union {
376		uint32_t control_raw;
377		struct generic_dma_control control_generic;
378		struct {
379			uint32_t int_enable:1;
380			uint32_t src_snoop_disable:1;
381			uint32_t dest_snoop_disable:1;
382			uint32_t completion_update:1;
383			uint32_t fence:1;
384			uint32_t src_cnt:3;
385			uint32_t bundle:1;
386			uint32_t dest_dca:1;
387			uint32_t hint:1;
388			uint32_t p_disable:1;
389			uint32_t q_disable:1;
390			uint32_t reserved:3;
391			uint32_t coef:8;
392			#define IOAT_OP_PQ_UP 0x8b
393			uint32_t op:8;
394		} control;
395	} u;
396	uint64_t src_addr;
397	uint64_t p_addr;
398	uint64_t next;
399	uint64_t src_addr2;
400	uint64_t p_src;
401	uint64_t q_src;
402	uint64_t q_addr;
403};
404
405struct ioat_raw_hw_descriptor {
406	uint64_t field[8];
407};
408
409struct bus_dmadesc {
410	bus_dmaengine_callback_t callback_fn;
411	void			 *callback_arg;
412};
413
414struct ioat_descriptor {
415	struct bus_dmadesc	bus_dmadesc;
416	union {
417		struct ioat_generic_hw_descriptor	*generic;
418		struct ioat_dma_hw_descriptor		*dma;
419		struct ioat_fill_hw_descriptor		*fill;
420		struct ioat_crc32_hw_descriptor		*crc32;
421		struct ioat_xor_hw_descriptor		*xor;
422		struct ioat_xor_ext_hw_descriptor	*xor_ext;
423		struct ioat_pq_hw_descriptor		*pq;
424		struct ioat_pq_ext_hw_descriptor	*pq_ext;
425		struct ioat_raw_hw_descriptor		*raw;
426	} u;
427	uint32_t		id;
428	bus_addr_t		hw_desc_bus_addr;
429};
430
431/* Unused by this driver at this time. */
432#define	IOAT_OP_MARKER		0x84
433
434/*
435 * Deprecated OPs -- v3 DMA generates an abort if given these.  And this driver
436 * doesn't support anything older than v3.
437 */
438#define	IOAT_OP_OLD_XOR		0x85
439#define	IOAT_OP_OLD_XOR_VAL	0x86
440
441enum ioat_ref_kind {
442	IOAT_DMAENGINE_REF = 0,
443	IOAT_ACTIVE_DESCR_REF,
444	IOAT_NUM_REF_KINDS
445};
446
447/* One of these per allocated PCI device. */
448struct ioat_softc {
449	bus_dmaengine_t		dmaengine;
450#define	to_ioat_softc(_dmaeng)						\
451({									\
452	bus_dmaengine_t *_p = (_dmaeng);				\
453	(struct ioat_softc *)((char *)_p -				\
454	    offsetof(struct ioat_softc, dmaengine));			\
455})
456
457	int			version;
458	int			chan_idx;
459
460	struct mtx		submit_lock;
461	device_t		device;
462	bus_space_tag_t		pci_bus_tag;
463	bus_space_handle_t	pci_bus_handle;
464	int			pci_resource_id;
465	struct resource		*pci_resource;
466	uint32_t		max_xfer_size;
467	uint32_t		capabilities;
468	uint16_t		intrdelay_max;
469	uint16_t		cached_intrdelay;
470
471	struct resource		*res;
472	int			rid;
473	void			*tag;
474
475	bus_dma_tag_t		hw_desc_tag;
476	bus_dmamap_t		hw_desc_map;
477
478	bus_dma_tag_t		comp_update_tag;
479	bus_dmamap_t		comp_update_map;
480	uint64_t		*comp_update;
481	bus_addr_t		comp_update_bus_addr;
482
483	struct callout		timer;
484	struct task		reset_task;
485
486	boolean_t		quiescing;
487	boolean_t		destroying;
488	boolean_t		is_resize_pending;
489	boolean_t		is_completion_pending;
490	boolean_t		is_reset_pending;
491	boolean_t		is_channel_running;
492	boolean_t		intrdelay_supported;
493
494	uint32_t		head;
495	uint32_t		tail;
496	uint32_t		hw_head;
497	uint32_t		ring_size_order;
498	bus_addr_t		last_seen;
499
500	struct ioat_descriptor	**ring;
501
502	struct mtx		cleanup_lock;
503	volatile uint32_t	refcnt;
504#ifdef INVARIANTS
505	volatile uint32_t	refkinds[IOAT_NUM_REF_KINDS];
506#endif
507
508	struct {
509		uint64_t	interrupts;
510		uint64_t	descriptors_processed;
511		uint64_t	descriptors_error;
512		uint64_t	descriptors_submitted;
513
514		uint32_t	channel_halts;
515		uint32_t	last_halt_chanerr;
516	} stats;
517};
518
519void ioat_test_attach(void);
520void ioat_test_detach(void);
521
522static inline uint64_t
523ioat_get_chansts(struct ioat_softc *ioat)
524{
525	uint64_t status;
526
527	if (ioat->version >= IOAT_VER_3_3)
528		status = ioat_read_8(ioat, IOAT_CHANSTS_OFFSET);
529	else
530		/* Must read lower 4 bytes before upper 4 bytes. */
531		status = ioat_read_double_4(ioat, IOAT_CHANSTS_OFFSET);
532	return (status);
533}
534
535static inline void
536ioat_write_chancmp(struct ioat_softc *ioat, uint64_t addr)
537{
538
539	if (ioat->version >= IOAT_VER_3_3)
540		ioat_write_8(ioat, IOAT_CHANCMP_OFFSET_LOW, addr);
541	else
542		ioat_write_double_4(ioat, IOAT_CHANCMP_OFFSET_LOW, addr);
543}
544
545static inline void
546ioat_write_chainaddr(struct ioat_softc *ioat, uint64_t addr)
547{
548
549	if (ioat->version >= IOAT_VER_3_3)
550		ioat_write_8(ioat, IOAT_CHAINADDR_OFFSET_LOW, addr);
551	else
552		ioat_write_double_4(ioat, IOAT_CHAINADDR_OFFSET_LOW, addr);
553}
554
555static inline boolean_t
556is_ioat_active(uint64_t status)
557{
558	return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_ACTIVE);
559}
560
561static inline boolean_t
562is_ioat_idle(uint64_t status)
563{
564	return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_IDLE);
565}
566
567static inline boolean_t
568is_ioat_halted(uint64_t status)
569{
570	return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_HALTED);
571}
572
573static inline boolean_t
574is_ioat_suspended(uint64_t status)
575{
576	return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_SUSPENDED);
577}
578
579static inline void
580ioat_suspend(struct ioat_softc *ioat)
581{
582	ioat_write_1(ioat, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_SUSPEND);
583}
584
585static inline void
586ioat_reset(struct ioat_softc *ioat)
587{
588	ioat_write_1(ioat, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
589}
590
591static inline boolean_t
592ioat_reset_pending(struct ioat_softc *ioat)
593{
594	uint8_t cmd;
595
596	cmd = ioat_read_1(ioat, IOAT_CHANCMD_OFFSET);
597	return ((cmd & IOAT_CHANCMD_RESET) != 0);
598}
599
600#endif /* __IOAT_INTERNAL_H__ */
601