xref: /titanic_51/usr/src/uts/i86pc/io/ioat/ioat_chan.c (revision 5aefaa163415ab092e00dfb2b1f5c2d0c9ead376)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/errno.h>
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/kmem.h>
31 #include <sys/ddi.h>
32 #include <sys/stat.h>
33 #include <sys/sunddi.h>
34 #include <sys/file.h>
35 #include <sys/open.h>
36 #include <sys/modctl.h>
37 #include <sys/ddi_impldefs.h>
38 #include <sys/sysmacros.h>
39 #include <vm/hat.h>
40 #include <vm/as.h>
41 #include <sys/mach_mmu.h>
42 #ifdef __xpv
43 #include <sys/hypervisor.h>
44 #endif
45 
46 #include <sys/ioat.h>
47 
48 
49 extern ddi_device_acc_attr_t ioat_acc_attr;
50 
51 /* dma attr for the descriptor rings */
52 ddi_dma_attr_t ioat_desc_dma_attr = {
53 	DMA_ATTR_V0,		/* dma_attr_version */
54 	0x0,			/* dma_attr_addr_lo */
55 	0xffffffffffffffff,	/* dma_attr_addr_hi */
56 	0xffffffff,		/* dma_attr_count_max */
57 	0x1000,			/* dma_attr_align */
58 	0x1,			/* dma_attr_burstsizes */
59 	0x1,			/* dma_attr_minxfer */
60 	0xffffffff,		/* dma_attr_maxxfer */
61 	0xffffffff,		/* dma_attr_seg */
62 	0x1,			/* dma_attr_sgllen */
63 	0x1,			/* dma_attr_granular */
64 	0x0,			/* dma_attr_flags */
65 };
66 
67 /* dma attr for the completion buffers */
68 ddi_dma_attr_t ioat_cmpl_dma_attr = {
69 	DMA_ATTR_V0,		/* dma_attr_version */
70 	0x0,			/* dma_attr_addr_lo */
71 	0xffffffffffffffff,	/* dma_attr_addr_hi */
72 	0xffffffff,		/* dma_attr_count_max */
73 	0x40,			/* dma_attr_align */
74 	0x1,			/* dma_attr_burstsizes */
75 	0x1,			/* dma_attr_minxfer */
76 	0xffffffff,		/* dma_attr_maxxfer */
77 	0xffffffff,		/* dma_attr_seg */
78 	0x1,			/* dma_attr_sgllen */
79 	0x1,			/* dma_attr_granular */
80 	0x0,			/* dma_attr_flags */
81 };
82 
83 static int ioat_completion_alloc(ioat_channel_t channel);
84 static void ioat_completion_free(ioat_channel_t channel);
85 static void ioat_channel_start(ioat_channel_t channel);
86 static void ioat_channel_reset(ioat_channel_t channel);
87 
88 int ioat_ring_alloc(ioat_channel_t channel, uint_t desc_cnt);
89 void ioat_ring_free(ioat_channel_t channel);
90 void ioat_ring_seed(ioat_channel_t channel, ioat_chan_dma_desc_t *desc);
91 int ioat_ring_reserve(ioat_channel_t channel, ioat_channel_ring_t *ring,
92     dcopy_cmd_t cmd);
93 
94 static void ioat_cmd_post_copy(ioat_channel_ring_t *ring, uint64_t src_addr,
95     uint64_t dest_addr, uint32_t size, uint32_t ctrl);
96 static void ioat_cmd_post_dca(ioat_channel_ring_t *ring, uint32_t dca_id);
97 
98 
99 /*
100  * ioat_channel_init()
101  */
102 int
103 ioat_channel_init(ioat_state_t *state)
104 {
105 	int i;
106 
107 	/*
108 	 * initialize each dma channel's state which doesn't change across
109 	 * channel alloc/free.
110 	 */
111 	state->is_chansize = sizeof (struct ioat_channel_s) *
112 	    state->is_num_channels;
113 	state->is_channel = kmem_zalloc(state->is_chansize, KM_SLEEP);
114 	for (i = 0; i < state->is_num_channels; i++) {
115 		state->is_channel[i].ic_state = state;
116 		state->is_channel[i].ic_regs = (uint8_t *)
117 		    ((uintptr_t)state->is_genregs +
118 		    (uintptr_t)(IOAT_CHANNELREG_OFFSET * (i + 1)));
119 	}
120 
121 	/* initial the allocator (from 0 to state->is_num_channels) */
122 	ioat_rs_init(state, 0, state->is_num_channels, &state->is_channel_rs);
123 
124 	return (DDI_SUCCESS);
125 }
126 
127 
128 /*
129  * ioat_channel_fini()
130  */
131 void
132 ioat_channel_fini(ioat_state_t *state)
133 {
134 	ioat_rs_fini(&state->is_channel_rs);
135 	kmem_free(state->is_channel, state->is_chansize);
136 }
137 
138 
139 /*
140  * ioat_channel_alloc()
141  *   NOTE: We intentionaly don't handle DCOPY_SLEEP (if no channels are
142  *	available)
143  */
144 /*ARGSUSED*/
145 int
146 ioat_channel_alloc(void *device_private, dcopy_handle_t handle, int flags,
147     uint_t size, dcopy_query_channel_t *info, void *channel_private)
148 {
149 #define	CHANSTRSIZE	20
150 	struct ioat_channel_s *channel;
151 	char chanstr[CHANSTRSIZE];
152 	ioat_channel_t *chan;
153 	ioat_state_t *state;
154 	size_t cmd_size;
155 	uint_t chan_num;
156 	uint32_t estat;
157 	int e;
158 
159 
160 	state = (ioat_state_t *)device_private;
161 	chan = (ioat_channel_t *)channel_private;
162 
163 	/* allocate a H/W channel */
164 	e = ioat_rs_alloc(state->is_channel_rs, &chan_num);
165 	if (e != DDI_SUCCESS) {
166 		return (DCOPY_NORESOURCES);
167 	}
168 
169 	channel = &state->is_channel[chan_num];
170 	channel->ic_inuse = B_TRUE;
171 	channel->ic_chan_num = chan_num;
172 	channel->ic_ver = state->is_ver;
173 	channel->ic_dca_active = B_FALSE;
174 	channel->ic_channel_state = IOAT_CHANNEL_OK;
175 	channel->ic_dcopy_handle = handle;
176 
177 #ifdef	DEBUG
178 	{
179 		/* if we're cbv2, verify that the V2 compatibility bit is set */
180 		uint16_t reg;
181 		if (channel->ic_ver == IOAT_CBv2) {
182 			reg = ddi_get16(state->is_reg_handle,
183 			    (uint16_t *)&channel->ic_regs[IOAT_CHAN_COMP]);
184 			ASSERT(reg & 0x2);
185 		}
186 	}
187 #endif
188 
189 	/*
190 	 * Configure DMA channel
191 	 *   Channel In Use
192 	 *   Error Interrupt Enable
193 	 *   Any Error Abort Enable
194 	 *   Error Completion Enable
195 	 */
196 	ddi_put16(state->is_reg_handle,
197 	    (uint16_t *)&channel->ic_regs[IOAT_CHAN_CTL], 0x011C);
198 
199 	/* check channel error register, clear any errors */
200 	estat = ddi_get32(state->is_reg_handle,
201 	    (uint32_t *)&channel->ic_regs[IOAT_CHAN_ERR]);
202 	if (estat != 0) {
203 #ifdef	DEBUG
204 		cmn_err(CE_CONT, "cleared errors (0x%x) before channel (%d) "
205 		    "enable\n", estat, channel->ic_chan_num);
206 #endif
207 		ddi_put32(state->is_reg_handle,
208 		    (uint32_t *)&channel->ic_regs[IOAT_CHAN_ERR], estat);
209 	}
210 
211 	/* allocate and initialize the descriptor buf */
212 	e = ioat_ring_alloc(channel, size);
213 	if (e != DDI_SUCCESS) {
214 		goto chinitfail_desc_alloc;
215 	}
216 
217 	/* allocate and initialize the completion space */
218 	e = ioat_completion_alloc(channel);
219 	if (e != DDI_SUCCESS) {
220 		goto chinitfail_completion_alloc;
221 	}
222 
223 	/* setup kmem_cache for commands */
224 	cmd_size = sizeof (struct dcopy_cmd_s) +
225 	    sizeof (struct dcopy_cmd_priv_s) +
226 	    sizeof (struct ioat_cmd_private_s);
227 	(void) snprintf(chanstr, CHANSTRSIZE, "ioat%dchan%dcmd",
228 	    state->is_instance, channel->ic_chan_num);
229 	channel->ic_cmd_cache = kmem_cache_create(chanstr, cmd_size, 64,
230 	    NULL, NULL, NULL, NULL, NULL, 0);
231 	if (channel->ic_cmd_cache == NULL) {
232 		goto chinitfail_kmem_cache;
233 	}
234 
235 	/* start-up the channel */
236 	ioat_channel_start(channel);
237 
238 	/* fill in the channel info returned to dcopy */
239 	info->qc_version = DCOPY_QUERY_CHANNEL_V0;
240 	info->qc_id = state->is_deviceinfo.di_id;
241 	info->qc_capabilities = (uint64_t)state->is_capabilities;
242 	info->qc_channel_size = (uint64_t)size;
243 	info->qc_chan_num = (uint64_t)channel->ic_chan_num;
244 	if (channel->ic_ver == IOAT_CBv1) {
245 		info->qc_dca_supported = B_FALSE;
246 	} else {
247 		if (info->qc_capabilities & IOAT_DMACAP_DCA) {
248 			info->qc_dca_supported = B_TRUE;
249 		} else {
250 			info->qc_dca_supported = B_FALSE;
251 		}
252 	}
253 
254 	*chan = channel;
255 
256 	return (DCOPY_SUCCESS);
257 
258 chinitfail_kmem_cache:
259 	ioat_completion_free(channel);
260 chinitfail_completion_alloc:
261 	ioat_ring_free(channel);
262 chinitfail_desc_alloc:
263 	return (DCOPY_FAILURE);
264 }
265 
266 
267 /*
268  * ioat_channel_suspend()
269  */
270 /*ARGSUSED*/
271 void
272 ioat_channel_suspend(ioat_state_t *state)
273 {
274 	/*
275 	 * normally you would disable interrupts and reset the H/W here. But
276 	 * since the suspend framework doesn't know who is using us, it may
277 	 * not suspend their I/O before us.  Since we won't actively be doing
278 	 * any DMA or interrupts unless someone asks us to, it's safe to not
279 	 * do anything here.
280 	 */
281 }
282 
283 
284 /*
285  * ioat_channel_resume()
286  */
287 int
288 ioat_channel_resume(ioat_state_t *state)
289 {
290 	ioat_channel_ring_t *ring;
291 	ioat_channel_t channel;
292 	uint32_t estat;
293 	int i;
294 
295 
296 	for (i = 0; i < state->is_num_channels; i++) {
297 		channel = &state->is_channel[i];
298 		ring = channel->ic_ring;
299 
300 		if (!channel->ic_inuse) {
301 			continue;
302 		}
303 
304 		/*
305 		 * Configure DMA channel
306 		 *   Channel In Use
307 		 *   Error Interrupt Enable
308 		 *   Any Error Abort Enable
309 		 *   Error Completion Enable
310 		 */
311 		ddi_put16(state->is_reg_handle,
312 		    (uint16_t *)&channel->ic_regs[IOAT_CHAN_CTL], 0x011C);
313 
314 		/* check channel error register, clear any errors */
315 		estat = ddi_get32(state->is_reg_handle,
316 		    (uint32_t *)&channel->ic_regs[IOAT_CHAN_ERR]);
317 		if (estat != 0) {
318 #ifdef	DEBUG
319 			cmn_err(CE_CONT, "cleared errors (0x%x) before channel"
320 			    " (%d) enable\n", estat, channel->ic_chan_num);
321 #endif
322 			ddi_put32(state->is_reg_handle,
323 			    (uint32_t *)&channel->ic_regs[IOAT_CHAN_ERR],
324 			    estat);
325 		}
326 
327 		/* Re-initialize the ring */
328 		bzero(ring->cr_desc, channel->ic_desc_alloc_size);
329 		/* write the physical address into the chain address register */
330 		if (channel->ic_ver == IOAT_CBv1) {
331 			ddi_put32(state->is_reg_handle,
332 			    (uint32_t *)&channel->ic_regs[IOAT_V1_CHAN_ADDR_LO],
333 			    (uint32_t)(ring->cr_phys_desc & 0xffffffff));
334 			ddi_put32(state->is_reg_handle,
335 			    (uint32_t *)&channel->ic_regs[IOAT_V1_CHAN_ADDR_HI],
336 			    (uint32_t)(ring->cr_phys_desc >> 32));
337 		} else {
338 			ASSERT(channel->ic_ver == IOAT_CBv2);
339 			ddi_put32(state->is_reg_handle,
340 			    (uint32_t *)&channel->ic_regs[IOAT_V2_CHAN_ADDR_LO],
341 			    (uint32_t)(ring->cr_phys_desc & 0xffffffff));
342 			ddi_put32(state->is_reg_handle,
343 			    (uint32_t *)&channel->ic_regs[IOAT_V2_CHAN_ADDR_HI],
344 			    (uint32_t)(ring->cr_phys_desc >> 32));
345 		}
346 
347 		/* re-initialize the completion buffer */
348 		bzero((void *)channel->ic_cmpl, channel->ic_cmpl_alloc_size);
349 		/* write the phys addr into the completion address register */
350 		ddi_put32(state->is_reg_handle,
351 		    (uint32_t *)&channel->ic_regs[IOAT_CHAN_CMPL_LO],
352 		    (uint32_t)(channel->ic_phys_cmpl & 0xffffffff));
353 		ddi_put32(state->is_reg_handle,
354 		    (uint32_t *)&channel->ic_regs[IOAT_CHAN_CMPL_HI],
355 		    (uint32_t)(channel->ic_phys_cmpl >> 32));
356 
357 		/* start-up the channel */
358 		ioat_channel_start(channel);
359 
360 	}
361 
362 	return (DDI_SUCCESS);
363 }
364 
365 /*
366  * quiesce(9E) entry point.
367  *
368  * This function is called when the system is single-threaded at high
369  * PIL with preemption disabled. Therefore, this function must not be
370  * blocked.
371  *
372  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
373  * DDI_FAILURE indicates an error condition and should almost never happen.
374  */
375 void
376 ioat_channel_quiesce(ioat_state_t *state)
377 {
378 	int i;
379 
380 	/*
381 	 * Walk through all channels and quiesce
382 	 */
383 	for (i = 0; i < state->is_num_channels; i++) {
384 
385 		ioat_channel_t	channel = state->is_channel + i;
386 
387 		if (!channel->ic_inuse)
388 			continue;
389 
390 		/* disable the interrupts */
391 		ddi_put16(state->is_reg_handle,
392 		    (uint16_t *)&channel->ic_regs[IOAT_CHAN_CTL],
393 		    0x0);
394 
395 		ioat_channel_reset(channel);
396 	}
397 }
398 
399 
400 /*
401  * ioat_channel_free()
402  */
403 void
404 ioat_channel_free(void *channel_private)
405 {
406 	struct ioat_channel_s *channel;
407 	ioat_channel_t *chan;
408 	ioat_state_t *state;
409 	uint_t chan_num;
410 
411 
412 	chan = (ioat_channel_t *)channel_private;
413 	channel = *chan;
414 
415 	state = channel->ic_state;
416 	chan_num = channel->ic_chan_num;
417 
418 	/* disable the interrupts */
419 	ddi_put16(state->is_reg_handle,
420 	    (uint16_t *)&channel->ic_regs[IOAT_CHAN_CTL], 0x0);
421 
422 	ioat_channel_reset(channel);
423 
424 	/* cleanup command cache */
425 	kmem_cache_destroy(channel->ic_cmd_cache);
426 
427 	/* clean-up/free-up the completion space and descriptors */
428 	ioat_completion_free(channel);
429 	ioat_ring_free(channel);
430 
431 	channel->ic_inuse = B_FALSE;
432 
433 	/* free the H/W DMA engine */
434 	ioat_rs_free(state->is_channel_rs, chan_num);
435 
436 	*chan = NULL;
437 }
438 
439 
440 /*
441  * ioat_channel_intr()
442  */
443 void
444 ioat_channel_intr(ioat_channel_t channel)
445 {
446 	ioat_state_t *state;
447 	uint16_t chanctrl;
448 	uint32_t chanerr;
449 	uint32_t status;
450 
451 
452 	state = channel->ic_state;
453 
454 	if (channel->ic_ver == IOAT_CBv1) {
455 		status = ddi_get32(state->is_reg_handle,
456 		    (uint32_t *)&channel->ic_regs[IOAT_V1_CHAN_STS_LO]);
457 	} else {
458 		ASSERT(channel->ic_ver == IOAT_CBv2);
459 		status = ddi_get32(state->is_reg_handle,
460 		    (uint32_t *)&channel->ic_regs[IOAT_V2_CHAN_STS_LO]);
461 	}
462 
463 	/* if that status isn't ACTIVE or IDLE, the channel has failed */
464 	if (status & IOAT_CHAN_STS_FAIL_MASK) {
465 		chanerr = ddi_get32(state->is_reg_handle,
466 		    (uint32_t *)&channel->ic_regs[IOAT_CHAN_ERR]);
467 		cmn_err(CE_WARN, "channel(%d) fatal failure! "
468 		    "chanstat_lo=0x%X; chanerr=0x%X\n",
469 		    channel->ic_chan_num, status, chanerr);
470 		channel->ic_channel_state = IOAT_CHANNEL_IN_FAILURE;
471 		ioat_channel_reset(channel);
472 
473 		return;
474 	}
475 
476 	/*
477 	 * clear interrupt disable bit if set (it's a RW1C). Read it back to
478 	 * ensure the write completes.
479 	 */
480 	chanctrl = ddi_get16(state->is_reg_handle,
481 	    (uint16_t *)&channel->ic_regs[IOAT_CHAN_CTL]);
482 	ddi_put16(state->is_reg_handle,
483 	    (uint16_t *)&channel->ic_regs[IOAT_CHAN_CTL], chanctrl);
484 	(void) ddi_get16(state->is_reg_handle,
485 	    (uint16_t *)&channel->ic_regs[IOAT_CHAN_CTL]);
486 
487 	/* tell dcopy we have seen a completion on this channel */
488 	dcopy_device_channel_notify(channel->ic_dcopy_handle, DCOPY_COMPLETION);
489 }
490 
491 
492 /*
493  * ioat_channel_start()
494  */
495 void
496 ioat_channel_start(ioat_channel_t channel)
497 {
498 	ioat_chan_dma_desc_t desc;
499 
500 	/* set the first descriptor up as a NULL descriptor */
501 	bzero(&desc, sizeof (desc));
502 	desc.dd_size = 0;
503 	desc.dd_ctrl = IOAT_DESC_CTRL_OP_DMA | IOAT_DESC_DMACTRL_NULL |
504 	    IOAT_DESC_CTRL_CMPL;
505 	desc.dd_next_desc = 0x0;
506 
507 	/* setup the very first descriptor */
508 	ioat_ring_seed(channel, &desc);
509 }
510 
511 
512 /*
513  * ioat_channel_reset()
514  */
515 void
516 ioat_channel_reset(ioat_channel_t channel)
517 {
518 	ioat_state_t *state;
519 
520 	state = channel->ic_state;
521 
522 	/* hit the reset bit */
523 	if (channel->ic_ver == IOAT_CBv1) {
524 		ddi_put8(state->is_reg_handle,
525 		    &channel->ic_regs[IOAT_V1_CHAN_CMD], 0x20);
526 	} else {
527 		ASSERT(channel->ic_ver == IOAT_CBv2);
528 		ddi_put8(state->is_reg_handle,
529 		    &channel->ic_regs[IOAT_V2_CHAN_CMD], 0x20);
530 	}
531 }
532 
533 
534 /*
535  * ioat_completion_alloc()
536  */
537 int
538 ioat_completion_alloc(ioat_channel_t channel)
539 {
540 	ioat_state_t *state;
541 	size_t real_length;
542 	uint_t cookie_cnt;
543 	int e;
544 
545 
546 	state = channel->ic_state;
547 
548 	/*
549 	 * allocate memory for the completion status, zero it out, and get
550 	 * the paddr. We'll allocate a physically contiguous cache line.
551 	 */
552 	e = ddi_dma_alloc_handle(state->is_dip, &ioat_cmpl_dma_attr,
553 	    DDI_DMA_SLEEP, NULL, &channel->ic_cmpl_dma_handle);
554 	if (e != DDI_SUCCESS) {
555 		goto cmplallocfail_alloc_handle;
556 	}
557 	channel->ic_cmpl_alloc_size = 64;
558 	e = ddi_dma_mem_alloc(channel->ic_cmpl_dma_handle,
559 	    channel->ic_cmpl_alloc_size, &ioat_acc_attr,
560 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
561 	    (caddr_t *)&channel->ic_cmpl, &real_length,
562 	    &channel->ic_cmpl_handle);
563 	if (e != DDI_SUCCESS) {
564 		goto cmplallocfail_mem_alloc;
565 	}
566 	bzero((void *)channel->ic_cmpl, channel->ic_cmpl_alloc_size);
567 	e = ddi_dma_addr_bind_handle(channel->ic_cmpl_dma_handle, NULL,
568 	    (caddr_t)channel->ic_cmpl, channel->ic_cmpl_alloc_size,
569 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
570 	    &channel->ic_cmpl_cookie, &cookie_cnt);
571 	if (e != DDI_SUCCESS) {
572 		goto cmplallocfail_addr_bind;
573 	}
574 	ASSERT(cookie_cnt == 1);
575 	ASSERT(channel->ic_cmpl_cookie.dmac_size ==
576 	    channel->ic_cmpl_alloc_size);
577 	channel->ic_phys_cmpl = channel->ic_cmpl_cookie.dmac_laddress;
578 
579 	/* write the physical address into the completion address register */
580 	ddi_put32(state->is_reg_handle,
581 	    (uint32_t *)&channel->ic_regs[IOAT_CHAN_CMPL_LO],
582 	    (uint32_t)(channel->ic_phys_cmpl & 0xffffffff));
583 	ddi_put32(state->is_reg_handle,
584 	    (uint32_t *)&channel->ic_regs[IOAT_CHAN_CMPL_HI],
585 	    (uint32_t)(channel->ic_phys_cmpl >> 32));
586 
587 	return (DDI_SUCCESS);
588 
589 cmplallocfail_addr_bind:
590 	ddi_dma_mem_free(&channel->ic_desc_handle);
591 cmplallocfail_mem_alloc:
592 	ddi_dma_free_handle(&channel->ic_desc_dma_handle);
593 cmplallocfail_alloc_handle:
594 	return (DDI_FAILURE);
595 }
596 
597 
598 /*
599  * ioat_completion_free()
600  */
601 void
602 ioat_completion_free(ioat_channel_t channel)
603 {
604 	ioat_state_t *state;
605 
606 	state = channel->ic_state;
607 
608 	/* reset the completion address register */
609 	ddi_put32(state->is_reg_handle,
610 	    (uint32_t *)&channel->ic_regs[IOAT_CHAN_CMPL_LO], 0x0);
611 	ddi_put32(state->is_reg_handle,
612 	    (uint32_t *)&channel->ic_regs[IOAT_CHAN_CMPL_HI], 0x0);
613 
614 	/* unbind, then free up the memory, dma handle */
615 	(void) ddi_dma_unbind_handle(channel->ic_cmpl_dma_handle);
616 	ddi_dma_mem_free(&channel->ic_cmpl_handle);
617 	ddi_dma_free_handle(&channel->ic_cmpl_dma_handle);
618 }
619 
620 /*
621  * ioat_ring_alloc()
622  */
623 int
624 ioat_ring_alloc(ioat_channel_t channel, uint_t desc_cnt)
625 {
626 	ioat_channel_ring_t *ring;
627 	ioat_state_t *state;
628 	size_t real_length;
629 	uint_t cookie_cnt;
630 	int e;
631 
632 
633 	state = channel->ic_state;
634 
635 	ring = kmem_zalloc(sizeof (ioat_channel_ring_t), KM_SLEEP);
636 	channel->ic_ring = ring;
637 	ring->cr_chan = channel;
638 	ring->cr_post_cnt = 0;
639 
640 	mutex_init(&ring->cr_cmpl_mutex, NULL, MUTEX_DRIVER,
641 	    channel->ic_state->is_iblock_cookie);
642 	mutex_init(&ring->cr_desc_mutex, NULL, MUTEX_DRIVER,
643 	    channel->ic_state->is_iblock_cookie);
644 
645 	/*
646 	 * allocate memory for the ring, zero it out, and get the paddr.
647 	 * We'll allocate a physically contiguous chunck of memory  which
648 	 * simplifies the completion logic.
649 	 */
650 	e = ddi_dma_alloc_handle(state->is_dip, &ioat_desc_dma_attr,
651 	    DDI_DMA_SLEEP, NULL, &channel->ic_desc_dma_handle);
652 	if (e != DDI_SUCCESS) {
653 		goto ringallocfail_alloc_handle;
654 	}
655 	/*
656 	 * allocate one extra descriptor so we can simplify the empty/full
657 	 * logic. Then round that number up to a whole multiple of 4.
658 	 */
659 	channel->ic_chan_desc_cnt = ((desc_cnt + 1) + 3) & ~0x3;
660 	ring->cr_desc_last = channel->ic_chan_desc_cnt - 1;
661 	channel->ic_desc_alloc_size = channel->ic_chan_desc_cnt *
662 	    sizeof (ioat_chan_desc_t);
663 	e = ddi_dma_mem_alloc(channel->ic_desc_dma_handle,
664 	    channel->ic_desc_alloc_size, &ioat_acc_attr,
665 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
666 	    (caddr_t *)&ring->cr_desc, &real_length, &channel->ic_desc_handle);
667 	if (e != DDI_SUCCESS) {
668 		goto ringallocfail_mem_alloc;
669 	}
670 	bzero(ring->cr_desc, channel->ic_desc_alloc_size);
671 	e = ddi_dma_addr_bind_handle(channel->ic_desc_dma_handle, NULL,
672 	    (caddr_t)ring->cr_desc, channel->ic_desc_alloc_size,
673 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
674 	    &channel->ic_desc_cookies, &cookie_cnt);
675 	if (e != DDI_SUCCESS) {
676 		goto ringallocfail_addr_bind;
677 	}
678 	ASSERT(cookie_cnt == 1);
679 	ASSERT(channel->ic_desc_cookies.dmac_size ==
680 	    channel->ic_desc_alloc_size);
681 	ring->cr_phys_desc = channel->ic_desc_cookies.dmac_laddress;
682 
683 	/* write the physical address into the chain address register */
684 	if (channel->ic_ver == IOAT_CBv1) {
685 		ddi_put32(state->is_reg_handle,
686 		    (uint32_t *)&channel->ic_regs[IOAT_V1_CHAN_ADDR_LO],
687 		    (uint32_t)(ring->cr_phys_desc & 0xffffffff));
688 		ddi_put32(state->is_reg_handle,
689 		    (uint32_t *)&channel->ic_regs[IOAT_V1_CHAN_ADDR_HI],
690 		    (uint32_t)(ring->cr_phys_desc >> 32));
691 	} else {
692 		ASSERT(channel->ic_ver == IOAT_CBv2);
693 		ddi_put32(state->is_reg_handle,
694 		    (uint32_t *)&channel->ic_regs[IOAT_V2_CHAN_ADDR_LO],
695 		    (uint32_t)(ring->cr_phys_desc & 0xffffffff));
696 		ddi_put32(state->is_reg_handle,
697 		    (uint32_t *)&channel->ic_regs[IOAT_V2_CHAN_ADDR_HI],
698 		    (uint32_t)(ring->cr_phys_desc >> 32));
699 	}
700 
701 	return (DCOPY_SUCCESS);
702 
703 ringallocfail_addr_bind:
704 	ddi_dma_mem_free(&channel->ic_desc_handle);
705 ringallocfail_mem_alloc:
706 	ddi_dma_free_handle(&channel->ic_desc_dma_handle);
707 ringallocfail_alloc_handle:
708 	mutex_destroy(&ring->cr_desc_mutex);
709 	mutex_destroy(&ring->cr_cmpl_mutex);
710 	kmem_free(channel->ic_ring, sizeof (ioat_channel_ring_t));
711 
712 	return (DCOPY_FAILURE);
713 }
714 
715 
716 /*
717  * ioat_ring_free()
718  */
719 void
720 ioat_ring_free(ioat_channel_t channel)
721 {
722 	ioat_state_t *state;
723 
724 
725 	state = channel->ic_state;
726 
727 	/* reset the chain address register */
728 	if (channel->ic_ver == IOAT_CBv1) {
729 		ddi_put32(state->is_reg_handle,
730 		    (uint32_t *)&channel->ic_regs[IOAT_V1_CHAN_ADDR_LO], 0x0);
731 		ddi_put32(state->is_reg_handle,
732 		    (uint32_t *)&channel->ic_regs[IOAT_V1_CHAN_ADDR_HI], 0x0);
733 	} else {
734 		ASSERT(channel->ic_ver == IOAT_CBv2);
735 		ddi_put32(state->is_reg_handle,
736 		    (uint32_t *)&channel->ic_regs[IOAT_V2_CHAN_ADDR_LO], 0x0);
737 		ddi_put32(state->is_reg_handle,
738 		    (uint32_t *)&channel->ic_regs[IOAT_V2_CHAN_ADDR_HI], 0x0);
739 	}
740 
741 	/* unbind, then free up the memory, dma handle */
742 	(void) ddi_dma_unbind_handle(channel->ic_desc_dma_handle);
743 	ddi_dma_mem_free(&channel->ic_desc_handle);
744 	ddi_dma_free_handle(&channel->ic_desc_dma_handle);
745 
746 	mutex_destroy(&channel->ic_ring->cr_desc_mutex);
747 	mutex_destroy(&channel->ic_ring->cr_cmpl_mutex);
748 	kmem_free(channel->ic_ring, sizeof (ioat_channel_ring_t));
749 
750 }
751 
752 
753 /*
754  * ioat_ring_seed()
755  *    write the first descriptor in the ring.
756  */
757 void
758 ioat_ring_seed(ioat_channel_t channel, ioat_chan_dma_desc_t *in_desc)
759 {
760 	ioat_channel_ring_t *ring;
761 	ioat_chan_dma_desc_t *desc;
762 	ioat_chan_dma_desc_t *prev;
763 	ioat_state_t *state;
764 
765 
766 	state = channel->ic_state;
767 	ring = channel->ic_ring;
768 
769 	/* init the completion state */
770 	ring->cr_cmpl_gen = 0x0;
771 	ring->cr_cmpl_last = 0x0;
772 
773 	/* write in the descriptor and init the descriptor state */
774 	ring->cr_post_cnt++;
775 	channel->ic_ring->cr_desc[0] = *(ioat_chan_desc_t *)in_desc;
776 	ring->cr_desc_gen = 0;
777 	ring->cr_desc_prev = 0;
778 	ring->cr_desc_next = 1;
779 
780 	if (channel->ic_ver == IOAT_CBv1) {
781 		/* hit the start bit */
782 		ddi_put8(state->is_reg_handle,
783 		    &channel->ic_regs[IOAT_V1_CHAN_CMD], 0x1);
784 	} else {
785 		/*
786 		 * if this is CBv2, link the descriptor to an empty
787 		 * descriptor
788 		 */
789 		ASSERT(ring->cr_chan->ic_ver == IOAT_CBv2);
790 		desc = (ioat_chan_dma_desc_t *)
791 		    &ring->cr_desc[ring->cr_desc_next];
792 		prev = (ioat_chan_dma_desc_t *)
793 		    &ring->cr_desc[ring->cr_desc_prev];
794 
795 		desc->dd_ctrl = 0;
796 		desc->dd_next_desc = 0x0;
797 
798 		prev->dd_next_desc = ring->cr_phys_desc +
799 		    (ring->cr_desc_next << 6);
800 
801 		ddi_put16(state->is_reg_handle,
802 		    (uint16_t *)&channel->ic_regs[IOAT_V2_CHAN_CNT],
803 		    (uint16_t)1);
804 	}
805 
806 }
807 
808 
809 /*
810  * ioat_cmd_alloc()
811  */
812 int
813 ioat_cmd_alloc(void *private, int flags, dcopy_cmd_t *cmd)
814 {
815 	ioat_cmd_private_t *priv;
816 	ioat_channel_t channel;
817 	dcopy_cmd_t oldcmd;
818 	int kmflag;
819 
820 
821 	channel = (ioat_channel_t)private;
822 
823 	if (flags & DCOPY_NOSLEEP) {
824 		kmflag = KM_NOSLEEP;
825 	} else {
826 		kmflag = KM_SLEEP;
827 	}
828 
829 	/* save the command passed incase DCOPY_ALLOC_LINK is set */
830 	oldcmd = *cmd;
831 
832 	*cmd = kmem_cache_alloc(channel->ic_cmd_cache, kmflag);
833 	if (*cmd == NULL) {
834 		return (DCOPY_NORESOURCES);
835 	}
836 
837 	/* setup the dcopy and ioat private state pointers */
838 	(*cmd)->dp_version = DCOPY_CMD_V0;
839 	(*cmd)->dp_cmd = 0;
840 	(*cmd)->dp_private = (struct dcopy_cmd_priv_s *)
841 	    ((uintptr_t)(*cmd) + sizeof (struct dcopy_cmd_s));
842 	(*cmd)->dp_private->pr_device_cmd_private =
843 	    (struct ioat_cmd_private_s *)((uintptr_t)(*cmd)->dp_private +
844 	    sizeof (struct dcopy_cmd_priv_s));
845 
846 	/*
847 	 * if DCOPY_ALLOC_LINK is set, link the old command to the new one
848 	 * just allocated.
849 	 */
850 	priv = (*cmd)->dp_private->pr_device_cmd_private;
851 	if (flags & DCOPY_ALLOC_LINK) {
852 		priv->ip_next = oldcmd;
853 	} else {
854 		priv->ip_next = NULL;
855 	}
856 
857 	return (DCOPY_SUCCESS);
858 }
859 
860 
861 /*
862  * ioat_cmd_free()
863  */
864 void
865 ioat_cmd_free(void *private, dcopy_cmd_t *cmdp)
866 {
867 	ioat_cmd_private_t *priv;
868 	ioat_channel_t channel;
869 	dcopy_cmd_t next;
870 	dcopy_cmd_t cmd;
871 
872 
873 	channel = (ioat_channel_t)private;
874 	cmd = *(cmdp);
875 
876 	/*
877 	 * free all the commands in the chain (see DCOPY_ALLOC_LINK in
878 	 * ioat_cmd_alloc() for more info).
879 	 */
880 	while (cmd != NULL) {
881 		priv = cmd->dp_private->pr_device_cmd_private;
882 		next = priv->ip_next;
883 		kmem_cache_free(channel->ic_cmd_cache, cmd);
884 		cmd = next;
885 	}
886 	*cmdp = NULL;
887 }
888 
889 
890 /*
891  * ioat_cmd_post()
892  */
893 int
894 ioat_cmd_post(void *private, dcopy_cmd_t cmd)
895 {
896 	ioat_channel_ring_t *ring;
897 	ioat_cmd_private_t *priv;
898 	ioat_channel_t channel;
899 	ioat_state_t *state;
900 	uint64_t dest_paddr;
901 	uint64_t src_paddr;
902 	uint64_t dest_addr;
903 	uint32_t dest_size;
904 	uint64_t src_addr;
905 	uint32_t src_size;
906 	size_t xfer_size;
907 	uint32_t ctrl;
908 	size_t size;
909 	int e;
910 
911 
912 	channel = (ioat_channel_t)private;
913 	priv = cmd->dp_private->pr_device_cmd_private;
914 
915 	state = channel->ic_state;
916 	ring = channel->ic_ring;
917 
918 	mutex_enter(&ring->cr_desc_mutex);
919 
920 	/* if the channel has had a fatal failure, return failure */
921 	if (channel->ic_channel_state == IOAT_CHANNEL_IN_FAILURE) {
922 		mutex_exit(&ring->cr_desc_mutex);
923 		return (DCOPY_FAILURE);
924 	}
925 
926 	/* make sure we have space for the descriptors */
927 	e = ioat_ring_reserve(channel, ring, cmd);
928 	if (e != DCOPY_SUCCESS) {
929 		mutex_exit(&ring->cr_desc_mutex);
930 		return (DCOPY_NORESOURCES);
931 	}
932 
933 	/* if we support DCA, and the DCA flag is set, post a DCA desc */
934 	if ((channel->ic_ver == IOAT_CBv2) &&
935 	    (cmd->dp_flags & DCOPY_CMD_DCA)) {
936 		ioat_cmd_post_dca(ring, cmd->dp_dca_id);
937 	}
938 
939 	/*
940 	 * the dma copy may have to be broken up into multiple descriptors
941 	 * since we can't cross a page boundary.
942 	 */
943 	ASSERT(cmd->dp_version == DCOPY_CMD_V0);
944 	ASSERT(cmd->dp_cmd == DCOPY_CMD_COPY);
945 	src_addr = cmd->dp.copy.cc_source;
946 	dest_addr = cmd->dp.copy.cc_dest;
947 	size = cmd->dp.copy.cc_size;
948 	while (size > 0) {
949 		src_paddr = pa_to_ma(src_addr);
950 		dest_paddr = pa_to_ma(dest_addr);
951 
952 		/* adjust for any offset into the page */
953 		if ((src_addr & PAGEOFFSET) == 0) {
954 			src_size = PAGESIZE;
955 		} else {
956 			src_size = PAGESIZE - (src_addr & PAGEOFFSET);
957 		}
958 		if ((dest_addr & PAGEOFFSET) == 0) {
959 			dest_size = PAGESIZE;
960 		} else {
961 			dest_size = PAGESIZE - (dest_addr & PAGEOFFSET);
962 		}
963 
964 		/* take the smallest of the three */
965 		xfer_size = MIN(src_size, dest_size);
966 		xfer_size = MIN(xfer_size, size);
967 
968 		/*
969 		 * if this is the last descriptor, and we are supposed to
970 		 * generate a completion, generate a completion. same logic
971 		 * for interrupt.
972 		 */
973 		ctrl = 0;
974 		if (xfer_size == size) {
975 			if (!(cmd->dp_flags & DCOPY_CMD_NOSTAT)) {
976 				ctrl |= IOAT_DESC_CTRL_CMPL;
977 			}
978 			if ((cmd->dp_flags & DCOPY_CMD_INTR)) {
979 				ctrl |= IOAT_DESC_CTRL_INTR;
980 			}
981 		}
982 
983 		ioat_cmd_post_copy(ring, src_paddr, dest_paddr, xfer_size,
984 		    ctrl);
985 
986 		/* go to the next page */
987 		src_addr += xfer_size;
988 		dest_addr += xfer_size;
989 		size -= xfer_size;
990 	}
991 
992 	/*
993 	 * if we are going to create a completion, save away the state so we
994 	 * can poll on it.
995 	 */
996 	if (!(cmd->dp_flags & DCOPY_CMD_NOSTAT)) {
997 		priv->ip_generation = ring->cr_desc_gen_prev;
998 		priv->ip_index = ring->cr_desc_prev;
999 	}
1000 
1001 	/* if queue not defined, tell the DMA engine about it */
1002 	if (!(cmd->dp_flags & DCOPY_CMD_QUEUE)) {
1003 		if (channel->ic_ver == IOAT_CBv1) {
1004 			ddi_put8(state->is_reg_handle,
1005 			    (uint8_t *)&channel->ic_regs[IOAT_V1_CHAN_CMD],
1006 			    0x2);
1007 		} else {
1008 			ASSERT(channel->ic_ver == IOAT_CBv2);
1009 			ddi_put16(state->is_reg_handle,
1010 			    (uint16_t *)&channel->ic_regs[IOAT_V2_CHAN_CNT],
1011 			    (uint16_t)(ring->cr_post_cnt & 0xFFFF));
1012 		}
1013 	}
1014 
1015 	mutex_exit(&ring->cr_desc_mutex);
1016 
1017 	return (DCOPY_SUCCESS);
1018 }
1019 
1020 
1021 /*
1022  * ioat_cmd_post_dca()
1023  */
1024 static void
1025 ioat_cmd_post_dca(ioat_channel_ring_t *ring, uint32_t dca_id)
1026 {
1027 	ioat_chan_dca_desc_t *saved_prev;
1028 	ioat_chan_dca_desc_t *desc;
1029 	ioat_chan_dca_desc_t *prev;
1030 	ioat_channel_t channel;
1031 	uint64_t next_desc_phys;
1032 	off_t prev_offset;
1033 	off_t next_offset;
1034 
1035 
1036 	channel = ring->cr_chan;
1037 	desc = (ioat_chan_dca_desc_t *)&ring->cr_desc[ring->cr_desc_next];
1038 	prev = (ioat_chan_dca_desc_t *)&ring->cr_desc[ring->cr_desc_prev];
1039 
1040 	/* keep track of the number of descs posted for cbv2 */
1041 	ring->cr_post_cnt++;
1042 
1043 	/*
1044 	 * post a context change desriptor. If dca has never been used on
1045 	 * this channel, or if the id doesn't match the last id used on this
1046 	 * channel, set CONTEXT_CHANGE bit and dca id, set dca state to active,
1047 	 * and save away the id we're using.
1048 	 */
1049 	desc->dd_ctrl = IOAT_DESC_CTRL_OP_CNTX;
1050 	desc->dd_next_desc = 0x0;
1051 	if (!channel->ic_dca_active || (channel->ic_dca_current != dca_id)) {
1052 		channel->ic_dca_active = B_TRUE;
1053 		channel->ic_dca_current = dca_id;
1054 		desc->dd_ctrl |= IOAT_DESC_CTRL_CNTX_CHNG;
1055 		desc->dd_cntx = dca_id;
1056 	}
1057 
1058 	/*
1059 	 * save next desc and prev offset for when we link the two
1060 	 * descriptors together.
1061 	 */
1062 	saved_prev = prev;
1063 	prev_offset = ring->cr_desc_prev << 6;
1064 	next_offset = ring->cr_desc_next << 6;
1065 	next_desc_phys = ring->cr_phys_desc + next_offset;
1066 
1067 	/* save the current desc_next and desc_last for the completion */
1068 	ring->cr_desc_prev = ring->cr_desc_next;
1069 	ring->cr_desc_gen_prev = ring->cr_desc_gen;
1070 
1071 	/* increment next/gen so it points to the next free desc */
1072 	ring->cr_desc_next++;
1073 	if (ring->cr_desc_next > ring->cr_desc_last) {
1074 		ring->cr_desc_next = 0;
1075 		ring->cr_desc_gen++;
1076 	}
1077 
1078 	/*
1079 	 * if this is CBv2, link the descriptor to an empty descriptor. Since
1080 	 * we always leave on desc empty to detect full, this works out.
1081 	 */
1082 	if (ring->cr_chan->ic_ver == IOAT_CBv2) {
1083 		desc = (ioat_chan_dca_desc_t *)
1084 		    &ring->cr_desc[ring->cr_desc_next];
1085 		prev = (ioat_chan_dca_desc_t *)
1086 		    &ring->cr_desc[ring->cr_desc_prev];
1087 		desc->dd_ctrl = 0;
1088 		desc->dd_next_desc = 0x0;
1089 		(void) ddi_dma_sync(channel->ic_desc_dma_handle,
1090 		    ring->cr_desc_next << 6, 64, DDI_DMA_SYNC_FORDEV);
1091 		prev->dd_next_desc = ring->cr_phys_desc +
1092 		    (ring->cr_desc_next << 6);
1093 	}
1094 
1095 	/* Put the descriptors physical address in the previous descriptor */
1096 	/*LINTED:E_TRUE_LOGICAL_EXPR*/
1097 	ASSERT(sizeof (ioat_chan_dca_desc_t) == 64);
1098 
1099 	/* sync the current desc */
1100 	(void) ddi_dma_sync(channel->ic_desc_dma_handle, next_offset, 64,
1101 	    DDI_DMA_SYNC_FORDEV);
1102 
1103 	/* update the previous desc and sync it too */
1104 	saved_prev->dd_next_desc = next_desc_phys;
1105 	(void) ddi_dma_sync(channel->ic_desc_dma_handle, prev_offset, 64,
1106 	    DDI_DMA_SYNC_FORDEV);
1107 }
1108 
1109 
1110 /*
1111  * ioat_cmd_post_copy()
1112  *
1113  */
1114 static void
1115 ioat_cmd_post_copy(ioat_channel_ring_t *ring, uint64_t src_addr,
1116     uint64_t dest_addr, uint32_t size, uint32_t ctrl)
1117 {
1118 	ioat_chan_dma_desc_t *saved_prev;
1119 	ioat_chan_dma_desc_t *desc;
1120 	ioat_chan_dma_desc_t *prev;
1121 	ioat_channel_t channel;
1122 	uint64_t next_desc_phy;
1123 	off_t prev_offset;
1124 	off_t next_offset;
1125 
1126 
1127 	channel = ring->cr_chan;
1128 	desc = (ioat_chan_dma_desc_t *)&ring->cr_desc[ring->cr_desc_next];
1129 	prev = (ioat_chan_dma_desc_t *)&ring->cr_desc[ring->cr_desc_prev];
1130 
1131 	/* keep track of the number of descs posted for cbv2 */
1132 	ring->cr_post_cnt++;
1133 
1134 	/* write in the DMA desc */
1135 	desc->dd_ctrl = IOAT_DESC_CTRL_OP_DMA | ctrl;
1136 	desc->dd_size = size;
1137 	desc->dd_src_paddr = src_addr;
1138 	desc->dd_dest_paddr = dest_addr;
1139 	desc->dd_next_desc = 0x0;
1140 
1141 	/*
1142 	 * save next desc and prev offset for when we link the two
1143 	 * descriptors together.
1144 	 */
1145 	saved_prev = prev;
1146 	prev_offset = ring->cr_desc_prev << 6;
1147 	next_offset = ring->cr_desc_next << 6;
1148 	next_desc_phy = ring->cr_phys_desc + next_offset;
1149 
1150 	/* increment next/gen so it points to the next free desc */
1151 	ring->cr_desc_prev = ring->cr_desc_next;
1152 	ring->cr_desc_gen_prev = ring->cr_desc_gen;
1153 
1154 	/* increment next/gen so it points to the next free desc */
1155 	ring->cr_desc_next++;
1156 	if (ring->cr_desc_next > ring->cr_desc_last) {
1157 		ring->cr_desc_next = 0;
1158 		ring->cr_desc_gen++;
1159 	}
1160 
1161 	/*
1162 	 * if this is CBv2, link the descriptor to an empty descriptor. Since
1163 	 * we always leave on desc empty to detect full, this works out.
1164 	 */
1165 	if (ring->cr_chan->ic_ver == IOAT_CBv2) {
1166 		desc = (ioat_chan_dma_desc_t *)
1167 		    &ring->cr_desc[ring->cr_desc_next];
1168 		prev = (ioat_chan_dma_desc_t *)
1169 		    &ring->cr_desc[ring->cr_desc_prev];
1170 		desc->dd_size = 0;
1171 		desc->dd_ctrl = 0;
1172 		desc->dd_next_desc = 0x0;
1173 		(void) ddi_dma_sync(channel->ic_desc_dma_handle,
1174 		    ring->cr_desc_next << 6, 64, DDI_DMA_SYNC_FORDEV);
1175 		prev->dd_next_desc = ring->cr_phys_desc +
1176 		    (ring->cr_desc_next << 6);
1177 	}
1178 
1179 	/* Put the descriptors physical address in the previous descriptor */
1180 	/*LINTED:E_TRUE_LOGICAL_EXPR*/
1181 	ASSERT(sizeof (ioat_chan_dma_desc_t) == 64);
1182 
1183 	/* sync the current desc */
1184 	(void) ddi_dma_sync(channel->ic_desc_dma_handle, next_offset, 64,
1185 	    DDI_DMA_SYNC_FORDEV);
1186 
1187 	/* update the previous desc and sync it too */
1188 	saved_prev->dd_next_desc = next_desc_phy;
1189 	(void) ddi_dma_sync(channel->ic_desc_dma_handle, prev_offset, 64,
1190 	    DDI_DMA_SYNC_FORDEV);
1191 }
1192 
1193 
1194 /*
1195  * ioat_cmd_poll()
1196  */
1197 int
1198 ioat_cmd_poll(void *private, dcopy_cmd_t cmd)
1199 {
1200 	ioat_channel_ring_t *ring;
1201 	ioat_cmd_private_t *priv;
1202 	ioat_channel_t channel;
1203 	uint64_t generation;
1204 	uint64_t last_cmpl;
1205 
1206 
1207 	channel = (ioat_channel_t)private;
1208 	priv = cmd->dp_private->pr_device_cmd_private;
1209 
1210 	ring = channel->ic_ring;
1211 	ASSERT(ring != NULL);
1212 
1213 	mutex_enter(&ring->cr_cmpl_mutex);
1214 
1215 	/* if the channel had a fatal failure, fail all polls */
1216 	if ((channel->ic_channel_state == IOAT_CHANNEL_IN_FAILURE) ||
1217 	    IOAT_CMPL_FAILED(channel)) {
1218 		mutex_exit(&ring->cr_cmpl_mutex);
1219 		return (DCOPY_FAILURE);
1220 	}
1221 
1222 	/*
1223 	 * if the current completion is the same as the last time we read one,
1224 	 * post is still pending, nothing further to do. We track completions
1225 	 * as indexes into the ring since post uses VAs and the H/W returns
1226 	 * PAs. We grab a snapshot of generation and last_cmpl in the mutex.
1227 	 */
1228 	(void) ddi_dma_sync(channel->ic_cmpl_dma_handle, 0, 0,
1229 	    DDI_DMA_SYNC_FORCPU);
1230 	last_cmpl = IOAT_CMPL_INDEX(channel);
1231 	if (last_cmpl != ring->cr_cmpl_last) {
1232 		/*
1233 		 * if we wrapped the ring, increment the generation. Store
1234 		 * the last cmpl. This logic assumes a physically contiguous
1235 		 * ring.
1236 		 */
1237 		if (last_cmpl < ring->cr_cmpl_last) {
1238 			ring->cr_cmpl_gen++;
1239 		}
1240 		ring->cr_cmpl_last = last_cmpl;
1241 		generation = ring->cr_cmpl_gen;
1242 
1243 	} else {
1244 		generation = ring->cr_cmpl_gen;
1245 	}
1246 
1247 	mutex_exit(&ring->cr_cmpl_mutex);
1248 
1249 	/*
1250 	 * if cmd isn't passed in, well return.  Useful for updating the
1251 	 * consumer pointer (ring->cr_cmpl_last).
1252 	 */
1253 	if (cmd == NULL) {
1254 		return (DCOPY_PENDING);
1255 	}
1256 
1257 	/*
1258 	 * if the post's generation is old, this post has completed. No reason
1259 	 * to go check the last completion. if the generation is the same
1260 	 * and if the post is before or = to the last completion processed,
1261 	 * the post has completed.
1262 	 */
1263 	if (priv->ip_generation < generation) {
1264 		return (DCOPY_COMPLETED);
1265 	} else if ((priv->ip_generation == generation) &&
1266 	    (priv->ip_index <= last_cmpl)) {
1267 		return (DCOPY_COMPLETED);
1268 	}
1269 
1270 	return (DCOPY_PENDING);
1271 }
1272 
1273 
1274 /*
1275  * ioat_ring_reserve()
1276  */
1277 int
1278 ioat_ring_reserve(ioat_channel_t channel, ioat_channel_ring_t *ring,
1279     dcopy_cmd_t cmd)
1280 {
1281 	uint64_t dest_addr;
1282 	uint32_t dest_size;
1283 	uint64_t src_addr;
1284 	uint32_t src_size;
1285 	size_t xfer_size;
1286 	uint64_t desc;
1287 	int num_desc;
1288 	size_t size;
1289 	int i;
1290 
1291 
1292 	/*
1293 	 * figure out how many descriptors we need. This can include a dca
1294 	 * desc and multiple desc for a dma copy.
1295 	 */
1296 	num_desc = 0;
1297 	if ((channel->ic_ver == IOAT_CBv2) &&
1298 	    (cmd->dp_flags & DCOPY_CMD_DCA)) {
1299 		num_desc++;
1300 	}
1301 	src_addr = cmd->dp.copy.cc_source;
1302 	dest_addr = cmd->dp.copy.cc_dest;
1303 	size = cmd->dp.copy.cc_size;
1304 	while (size > 0) {
1305 		num_desc++;
1306 
1307 		/* adjust for any offset into the page */
1308 		if ((src_addr & PAGEOFFSET) == 0) {
1309 			src_size = PAGESIZE;
1310 		} else {
1311 			src_size = PAGESIZE - (src_addr & PAGEOFFSET);
1312 		}
1313 		if ((dest_addr & PAGEOFFSET) == 0) {
1314 			dest_size = PAGESIZE;
1315 		} else {
1316 			dest_size = PAGESIZE - (dest_addr & PAGEOFFSET);
1317 		}
1318 
1319 		/* take the smallest of the three */
1320 		xfer_size = MIN(src_size, dest_size);
1321 		xfer_size = MIN(xfer_size, size);
1322 
1323 		/* go to the next page */
1324 		src_addr += xfer_size;
1325 		dest_addr += xfer_size;
1326 		size -= xfer_size;
1327 	}
1328 
1329 	/* Make sure we have space for these descriptors */
1330 	desc = ring->cr_desc_next;
1331 	for (i = 0; i < num_desc; i++) {
1332 
1333 		/*
1334 		 * if this is the last descriptor in the ring, see if the
1335 		 * last completed descriptor is #0.
1336 		 */
1337 		if (desc == ring->cr_desc_last) {
1338 			if (ring->cr_cmpl_last == 0) {
1339 				/*
1340 				 * if we think the ring is full, update where
1341 				 * the H/W really is and check for full again.
1342 				 */
1343 				(void) ioat_cmd_poll(channel, NULL);
1344 				if (ring->cr_cmpl_last == 0) {
1345 					return (DCOPY_NORESOURCES);
1346 				}
1347 			}
1348 
1349 			/*
1350 			 * go to the next descriptor which is zero in this
1351 			 * case.
1352 			 */
1353 			desc = 0;
1354 
1355 		/*
1356 		 * if this is not the last descriptor in the ring, see if
1357 		 * the last completion we saw was the next descriptor.
1358 		 */
1359 		} else {
1360 			if ((desc + 1) == ring->cr_cmpl_last) {
1361 				/*
1362 				 * if we think the ring is full, update where
1363 				 * the H/W really is and check for full again.
1364 				 */
1365 				(void) ioat_cmd_poll(channel, NULL);
1366 				if ((desc + 1) == ring->cr_cmpl_last) {
1367 					return (DCOPY_NORESOURCES);
1368 				}
1369 			}
1370 
1371 			/* go to the next descriptor */
1372 			desc++;
1373 		}
1374 	}
1375 
1376 	return (DCOPY_SUCCESS);
1377 }
1378