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-2013 Solarflare Communications Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/ddi.h> 28 29 #include "sfxge.h" 30 #include "efx.h" 31 32 static int 33 sfxge_dma_buffer_unbind_handle(efsys_mem_t *esmp) 34 { 35 int rc; 36 37 esmp->esm_addr = 0; 38 rc = ddi_dma_unbind_handle(esmp->esm_dma_handle); 39 if (rc != DDI_SUCCESS) 40 goto fail1; 41 42 return (0); 43 44 fail1: 45 DTRACE_PROBE1(fail1, int, rc); 46 47 return (rc); 48 } 49 50 static void 51 sfxge_dma_buffer_mem_free(efsys_mem_t *esmp) 52 { 53 esmp->esm_base = NULL; 54 ddi_dma_mem_free(&(esmp->esm_acc_handle)); 55 esmp->esm_acc_handle = NULL; 56 } 57 58 static void 59 sfxge_dma_buffer_handle_free(ddi_dma_handle_t *dhandlep) 60 { 61 ddi_dma_free_handle(dhandlep); 62 *dhandlep = NULL; 63 } 64 65 int 66 sfxge_dma_buffer_create(efsys_mem_t *esmp, const sfxge_dma_buffer_attr_t *sdbap) 67 { 68 int err; 69 int rc; 70 size_t unit; 71 ddi_dma_cookie_t dmac; 72 unsigned int ncookies; 73 74 /* Allocate a DMA handle */ 75 err = ddi_dma_alloc_handle(sdbap->sdba_dip, sdbap->sdba_dattrp, 76 sdbap->sdba_callback, NULL, &(esmp->esm_dma_handle)); 77 switch (err) { 78 case DDI_SUCCESS: 79 break; 80 81 case DDI_DMA_BADATTR: 82 rc = EINVAL; 83 goto fail1; 84 85 case DDI_DMA_NORESOURCES: 86 rc = ENOMEM; 87 goto fail1; 88 89 default: 90 rc = EFAULT; 91 goto fail1; 92 } 93 94 /* Allocate some DMA memory */ 95 err = ddi_dma_mem_alloc(esmp->esm_dma_handle, sdbap->sdba_length, 96 sdbap->sdba_devaccp, sdbap->sdba_memflags, 97 sdbap->sdba_callback, NULL, 98 &(esmp->esm_base), &unit, &(esmp->esm_acc_handle)); 99 switch (err) { 100 case DDI_SUCCESS: 101 break; 102 103 case DDI_FAILURE: 104 /*FALLTHRU*/ 105 default: 106 rc = EFAULT; 107 goto fail2; 108 } 109 110 if (sdbap->sdba_zeroinit) 111 bzero(esmp->esm_base, sdbap->sdba_length); 112 113 /* Bind the DMA memory to the DMA handle */ 114 /* We aren't handling partial mappings */ 115 ASSERT3U(sdbap->sdba_bindflags & DDI_DMA_PARTIAL, !=, DDI_DMA_PARTIAL); 116 err = ddi_dma_addr_bind_handle(esmp->esm_dma_handle, NULL, 117 esmp->esm_base, sdbap->sdba_length, sdbap->sdba_bindflags, 118 sdbap->sdba_callback, NULL, &dmac, &ncookies); 119 switch (err) { 120 case DDI_DMA_MAPPED: 121 break; 122 123 case DDI_DMA_INUSE: 124 rc = EEXIST; 125 goto fail3; 126 127 case DDI_DMA_NORESOURCES: 128 rc = ENOMEM; 129 goto fail3; 130 131 case DDI_DMA_NOMAPPING: 132 rc = ENOTSUP; 133 goto fail3; 134 135 case DDI_DMA_TOOBIG: 136 rc = EFBIG; 137 goto fail3; 138 139 default: 140 rc = EFAULT; 141 goto fail3; 142 } 143 ASSERT3U(ncookies, >=, 1); 144 ASSERT3U(ncookies, <=, sdbap->sdba_maxcookies); 145 146 esmp->esm_addr = dmac.dmac_laddress; 147 DTRACE_PROBE1(addr, efsys_dma_addr_t, esmp->esm_addr); 148 149 return (0); 150 151 fail3: 152 DTRACE_PROBE(fail3); 153 154 sfxge_dma_buffer_mem_free(esmp); 155 156 fail2: 157 DTRACE_PROBE(fail2); 158 159 sfxge_dma_buffer_handle_free(&(esmp->esm_dma_handle)); 160 esmp->esm_dma_handle = NULL; 161 162 fail1: 163 DTRACE_PROBE1(fail1, int, rc); 164 165 return (-1); 166 } 167 168 void 169 sfxge_dma_buffer_destroy(efsys_mem_t *esmp) 170 { 171 int rc; 172 173 rc = sfxge_dma_buffer_unbind_handle(esmp); 174 if (rc != 0) { 175 cmn_err(CE_WARN, SFXGE_CMN_ERR "ERROR: DMA Unbind failed rc=%d", 176 rc); 177 } 178 sfxge_dma_buffer_mem_free(esmp); 179 sfxge_dma_buffer_handle_free(&(esmp->esm_dma_handle)); 180 }