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