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 #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_cmpl_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_cmpl_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 *desc; 1028 ioat_chan_dca_desc_t *prev; 1029 ioat_channel_t channel; 1030 1031 1032 channel = ring->cr_chan; 1033 desc = (ioat_chan_dca_desc_t *)&ring->cr_desc[ring->cr_desc_next]; 1034 prev = (ioat_chan_dca_desc_t *)&ring->cr_desc[ring->cr_desc_prev]; 1035 1036 /* keep track of the number of descs posted for cbv2 */ 1037 ring->cr_post_cnt++; 1038 1039 /* 1040 * post a context change desriptor. If dca has never been used on 1041 * this channel, or if the id doesn't match the last id used on this 1042 * channel, set CONTEXT_CHANGE bit and dca id, set dca state to active, 1043 * and save away the id we're using. 1044 */ 1045 desc->dd_ctrl = IOAT_DESC_CTRL_OP_CNTX; 1046 desc->dd_next_desc = 0x0; 1047 if (!channel->ic_dca_active || (channel->ic_dca_current != dca_id)) { 1048 channel->ic_dca_active = B_TRUE; 1049 channel->ic_dca_current = dca_id; 1050 desc->dd_ctrl |= IOAT_DESC_CTRL_CNTX_CHNG; 1051 desc->dd_cntx = dca_id; 1052 } 1053 1054 /* Put the descriptors physical address in the previous descriptor */ 1055 /*LINTED:E_TRUE_LOGICAL_EXPR*/ 1056 ASSERT(sizeof (ioat_chan_dca_desc_t) == 64); 1057 1058 /* sync the current desc */ 1059 (void) ddi_dma_sync(channel->ic_desc_dma_handle, 1060 ring->cr_desc_next << 6, 64, DDI_DMA_SYNC_FORDEV); 1061 1062 /* update the previous desc and sync it too */ 1063 prev->dd_next_desc = ring->cr_phys_desc + 1064 (ring->cr_desc_next << 6); 1065 (void) ddi_dma_sync(channel->ic_desc_dma_handle, 1066 ring->cr_desc_prev << 6, 64, DDI_DMA_SYNC_FORDEV); 1067 1068 /* save the current desc_next and desc_last for the completion */ 1069 ring->cr_desc_prev = ring->cr_desc_next; 1070 ring->cr_desc_gen_prev = ring->cr_desc_gen; 1071 1072 /* increment next/gen so it points to the next free desc */ 1073 ring->cr_desc_next++; 1074 if (ring->cr_desc_next > ring->cr_desc_last) { 1075 ring->cr_desc_next = 0; 1076 ring->cr_desc_gen++; 1077 } 1078 1079 /* 1080 * if this is CBv2, link the descriptor to an empty descriptor. Since 1081 * we always leave on desc empty to detect full, this works out. 1082 */ 1083 if (ring->cr_chan->ic_ver == IOAT_CBv2) { 1084 desc = (ioat_chan_dca_desc_t *) 1085 &ring->cr_desc[ring->cr_desc_next]; 1086 prev = (ioat_chan_dca_desc_t *) 1087 &ring->cr_desc[ring->cr_desc_prev]; 1088 desc->dd_ctrl = 0; 1089 desc->dd_next_desc = 0x0; 1090 1091 prev->dd_next_desc = ring->cr_phys_desc + 1092 (ring->cr_desc_next << 6); 1093 } 1094 } 1095 1096 1097 /* 1098 * ioat_cmd_post_copy() 1099 * 1100 */ 1101 static void 1102 ioat_cmd_post_copy(ioat_channel_ring_t *ring, uint64_t src_addr, 1103 uint64_t dest_addr, uint32_t size, uint32_t ctrl) 1104 { 1105 ioat_chan_dma_desc_t *desc; 1106 ioat_chan_dma_desc_t *prev; 1107 ioat_channel_t channel; 1108 1109 1110 channel = ring->cr_chan; 1111 desc = (ioat_chan_dma_desc_t *)&ring->cr_desc[ring->cr_desc_next]; 1112 prev = (ioat_chan_dma_desc_t *)&ring->cr_desc[ring->cr_desc_prev]; 1113 1114 /* keep track of the number of descs posted for cbv2 */ 1115 ring->cr_post_cnt++; 1116 1117 /* write in the DMA desc */ 1118 desc->dd_ctrl = IOAT_DESC_CTRL_OP_DMA | ctrl; 1119 desc->dd_size = size; 1120 desc->dd_src_paddr = src_addr; 1121 desc->dd_dest_paddr = dest_addr; 1122 desc->dd_next_desc = 0x0; 1123 1124 /* Put the descriptors physical address in the previous descriptor */ 1125 /*LINTED:E_TRUE_LOGICAL_EXPR*/ 1126 ASSERT(sizeof (ioat_chan_dma_desc_t) == 64); 1127 1128 /* sync the current desc */ 1129 (void) ddi_dma_sync(channel->ic_desc_dma_handle, 1130 ring->cr_desc_next << 6, 64, DDI_DMA_SYNC_FORDEV); 1131 1132 /* update the previous desc and sync it too */ 1133 prev->dd_next_desc = ring->cr_phys_desc + 1134 (ring->cr_desc_next << 6); 1135 (void) ddi_dma_sync(channel->ic_desc_dma_handle, 1136 ring->cr_desc_prev << 6, 64, DDI_DMA_SYNC_FORDEV); 1137 1138 /* increment next/gen so it points to the next free desc */ 1139 ring->cr_desc_prev = ring->cr_desc_next; 1140 ring->cr_desc_gen_prev = ring->cr_desc_gen; 1141 1142 /* increment next/gen so it points to the next free desc */ 1143 ring->cr_desc_next++; 1144 if (ring->cr_desc_next > ring->cr_desc_last) { 1145 ring->cr_desc_next = 0; 1146 ring->cr_desc_gen++; 1147 } 1148 1149 /* 1150 * if this is CBv2, link the descriptor to an empty descriptor. Since 1151 * we always leave on desc empty to detect full, this works out. 1152 */ 1153 if (ring->cr_chan->ic_ver == IOAT_CBv2) { 1154 desc = (ioat_chan_dma_desc_t *) 1155 &ring->cr_desc[ring->cr_desc_next]; 1156 prev = (ioat_chan_dma_desc_t *) 1157 &ring->cr_desc[ring->cr_desc_prev]; 1158 desc->dd_size = 0; 1159 desc->dd_ctrl = 0; 1160 desc->dd_next_desc = 0x0; 1161 1162 prev->dd_next_desc = ring->cr_phys_desc + 1163 (ring->cr_desc_next << 6); 1164 } 1165 } 1166 1167 1168 /* 1169 * ioat_cmd_poll() 1170 */ 1171 int 1172 ioat_cmd_poll(void *private, dcopy_cmd_t cmd) 1173 { 1174 ioat_channel_ring_t *ring; 1175 ioat_cmd_private_t *priv; 1176 ioat_channel_t channel; 1177 uint64_t generation; 1178 uint64_t last_cmpl; 1179 1180 1181 channel = (ioat_channel_t)private; 1182 priv = cmd->dp_private->pr_device_cmd_private; 1183 1184 ring = channel->ic_ring; 1185 ASSERT(ring != NULL); 1186 1187 mutex_enter(&ring->cr_cmpl_mutex); 1188 1189 /* if the channel had a fatal failure, fail all polls */ 1190 if ((channel->ic_channel_state == IOAT_CHANNEL_IN_FAILURE) || 1191 IOAT_CMPL_FAILED(channel)) { 1192 mutex_exit(&ring->cr_cmpl_mutex); 1193 return (DCOPY_FAILURE); 1194 } 1195 1196 /* 1197 * if the current completion is the same as the last time we read one, 1198 * post is still pending, nothing further to do. We track completions 1199 * as indexes into the ring since post uses VAs and the H/W returns 1200 * PAs. We grab a snapshot of generation and last_cmpl in the mutex. 1201 */ 1202 (void) ddi_dma_sync(channel->ic_cmpl_dma_handle, 0, 0, 1203 DDI_DMA_SYNC_FORCPU); 1204 last_cmpl = IOAT_CMPL_INDEX(channel); 1205 if (last_cmpl != ring->cr_cmpl_last) { 1206 /* 1207 * if we wrapped the ring, increment the generation. Store 1208 * the last cmpl. This logic assumes a physically contiguous 1209 * ring. 1210 */ 1211 if (last_cmpl < ring->cr_cmpl_last) { 1212 ring->cr_cmpl_gen++; 1213 } 1214 ring->cr_cmpl_last = last_cmpl; 1215 generation = ring->cr_cmpl_gen; 1216 1217 } else { 1218 generation = ring->cr_cmpl_gen; 1219 } 1220 1221 mutex_exit(&ring->cr_cmpl_mutex); 1222 1223 /* 1224 * if cmd isn't passed in, well return. Useful for updating the 1225 * consumer pointer (ring->cr_cmpl_last). 1226 */ 1227 if (cmd == NULL) { 1228 return (DCOPY_PENDING); 1229 } 1230 1231 /* 1232 * if the post's generation is old, this post has completed. No reason 1233 * to go check the last completion. if the generation is the same 1234 * and if the post is before or = to the last completion processed, 1235 * the post has completed. 1236 */ 1237 if (priv->ip_generation < generation) { 1238 return (DCOPY_COMPLETED); 1239 } else if ((priv->ip_generation == generation) && 1240 (priv->ip_index <= last_cmpl)) { 1241 return (DCOPY_COMPLETED); 1242 } 1243 1244 return (DCOPY_PENDING); 1245 } 1246 1247 1248 /* 1249 * ioat_ring_reserve() 1250 */ 1251 int 1252 ioat_ring_reserve(ioat_channel_t channel, ioat_channel_ring_t *ring, 1253 dcopy_cmd_t cmd) 1254 { 1255 uint64_t dest_addr; 1256 uint32_t dest_size; 1257 uint64_t src_addr; 1258 uint32_t src_size; 1259 size_t xfer_size; 1260 uint64_t desc; 1261 int num_desc; 1262 size_t size; 1263 int i; 1264 1265 1266 /* 1267 * figure out how many descriptors we need. This can include a dca 1268 * desc and multiple desc for a dma copy. 1269 */ 1270 num_desc = 0; 1271 if ((channel->ic_ver == IOAT_CBv2) && 1272 (cmd->dp_flags & DCOPY_CMD_DCA)) { 1273 num_desc++; 1274 } 1275 src_addr = cmd->dp.copy.cc_source; 1276 dest_addr = cmd->dp.copy.cc_dest; 1277 size = cmd->dp.copy.cc_size; 1278 while (size > 0) { 1279 num_desc++; 1280 1281 /* adjust for any offset into the page */ 1282 if ((src_addr & PAGEOFFSET) == 0) { 1283 src_size = PAGESIZE; 1284 } else { 1285 src_size = PAGESIZE - (src_addr & PAGEOFFSET); 1286 } 1287 if ((dest_addr & PAGEOFFSET) == 0) { 1288 dest_size = PAGESIZE; 1289 } else { 1290 dest_size = PAGESIZE - (dest_addr & PAGEOFFSET); 1291 } 1292 1293 /* take the smallest of the three */ 1294 xfer_size = MIN(src_size, dest_size); 1295 xfer_size = MIN(xfer_size, size); 1296 1297 /* go to the next page */ 1298 src_addr += xfer_size; 1299 dest_addr += xfer_size; 1300 size -= xfer_size; 1301 } 1302 1303 /* Make sure we have space for these descriptors */ 1304 desc = ring->cr_desc_next; 1305 for (i = 0; i < num_desc; i++) { 1306 1307 /* 1308 * if this is the last descriptor in the ring, see if the 1309 * last completed descriptor is #0. 1310 */ 1311 if (desc == ring->cr_desc_last) { 1312 if (ring->cr_cmpl_last == 0) { 1313 /* 1314 * if we think the ring is full, update where 1315 * the H/W really is and check for full again. 1316 */ 1317 (void) ioat_cmd_poll(channel, NULL); 1318 if (ring->cr_cmpl_last == 0) { 1319 return (DCOPY_NORESOURCES); 1320 } 1321 } 1322 1323 /* 1324 * go to the next descriptor which is zero in this 1325 * case. 1326 */ 1327 desc = 0; 1328 1329 /* 1330 * if this is not the last descriptor in the ring, see if 1331 * the last completion we saw was the next descriptor. 1332 */ 1333 } else { 1334 if ((desc + 1) == ring->cr_cmpl_last) { 1335 /* 1336 * if we think the ring is full, update where 1337 * the H/W really is and check for full again. 1338 */ 1339 (void) ioat_cmd_poll(channel, NULL); 1340 if ((desc + 1) == ring->cr_cmpl_last) { 1341 return (DCOPY_NORESOURCES); 1342 } 1343 } 1344 1345 /* go to the next descriptor */ 1346 desc++; 1347 } 1348 } 1349 1350 return (DCOPY_SUCCESS); 1351 } 1352