1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2021 Oxide Computer Company 14 */ 15 16 #include "ena.h" 17 18 /* 19 * Create DMA attributes based on the conf parameter. 20 */ 21 void 22 ena_dma_attr(const ena_t *ena, ddi_dma_attr_t *attrp, 23 const ena_dma_conf_t *conf) 24 { 25 bzero(attrp, sizeof (*attrp)); 26 27 /* 28 * Round up maximums to next page. This is what the Linux and 29 * FreeBSD driver do, so we follow suit. 30 */ 31 const size_t size_up = 32 P2ROUNDUP_TYPED(conf->edc_size, ena->ena_page_sz, size_t); 33 34 attrp->dma_attr_version = DMA_ATTR_V0; 35 36 /* 37 * The device tells us the window it supports in terms of 38 * number of bits, we convert that to the appropriate mask. 39 */ 40 ASSERT3U(ena->ena_dma_width, >=, 32); 41 ASSERT3U(ena->ena_dma_width, <=, 48); 42 attrp->dma_attr_addr_lo = 0x0; 43 attrp->dma_attr_addr_hi = ENA_DMA_BIT_MASK(ena->ena_dma_width); 44 45 /* 46 * This indicates the amount of data that can fit in one 47 * cookie/segment. We allow the entire object to live in one 48 * segment, when possible. 49 * 50 * NOTE: This value must be _one less_ than the desired max 51 * (i.e. a value of 4095 indicates a max of 4096). 52 */ 53 attrp->dma_attr_count_max = size_up - 1; 54 55 /* 56 * The alignment of the starting address. 57 */ 58 attrp->dma_attr_align = conf->edc_align; 59 60 /* 61 * The segment boundary dictates the address which a segment 62 * cannot cross. In this case there is no boundary. 63 */ 64 attrp->dma_attr_seg = UINT64_MAX; 65 66 /* 67 * Allow a burst size of the entire object. 68 */ 69 attrp->dma_attr_burstsizes = size_up; 70 71 /* 72 * Minimum and maximum amount of data we can send. This isn't 73 * strictly limited by PCI in hardware, as it'll just make the 74 * appropriate number of requests. Simiarly, PCIe allows for 75 * an arbitrary granularity. We set this to one, as it's 76 * really a matter of what hardware is requesting from us. 77 */ 78 attrp->dma_attr_minxfer = 0x1; 79 attrp->dma_attr_maxxfer = size_up; 80 attrp->dma_attr_granular = 0x1; 81 82 /* 83 * The maximum length of the Scatter Gather List, aka the 84 * maximum number of segments a device can address in a 85 * transfer. 86 */ 87 attrp->dma_attr_sgllen = conf->edc_sgl; 88 } 89 90 void 91 ena_dma_free(ena_dma_buf_t *edb) 92 { 93 if (edb->edb_cookie != NULL) { 94 (void) ddi_dma_unbind_handle(edb->edb_dma_hdl); 95 edb->edb_cookie = NULL; 96 edb->edb_real_len = 0; 97 } 98 99 if (edb->edb_acc_hdl != NULL) { 100 ddi_dma_mem_free(&edb->edb_acc_hdl); 101 edb->edb_acc_hdl = NULL; 102 edb->edb_va = NULL; 103 } 104 105 if (edb->edb_dma_hdl != NULL) { 106 ddi_dma_free_handle(&edb->edb_dma_hdl); 107 edb->edb_dma_hdl = NULL; 108 } 109 110 edb->edb_len = 0; 111 } 112 113 boolean_t 114 ena_dma_alloc(ena_t *ena, ena_dma_buf_t *edb, ena_dma_conf_t *conf, size_t size) 115 { 116 int ret; 117 size_t size_allocated; 118 ddi_dma_attr_t attr; 119 ddi_device_acc_attr_t acc; 120 uint_t flags = 121 conf->edc_stream ? DDI_DMA_STREAMING : DDI_DMA_CONSISTENT; 122 123 ena_dma_attr(ena, &attr, conf); 124 125 acc.devacc_attr_version = DDI_DEVICE_ATTR_V1; 126 acc.devacc_attr_endian_flags = conf->edc_endian; 127 acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 128 129 ret = ddi_dma_alloc_handle(ena->ena_dip, &attr, DDI_DMA_DONTWAIT, NULL, 130 &edb->edb_dma_hdl); 131 if (ret != DDI_SUCCESS) { 132 ena_err(ena, "!failed to allocate DMA handle: %d", ret); 133 return (B_FALSE); 134 } 135 136 ret = ddi_dma_mem_alloc(edb->edb_dma_hdl, size, &acc, flags, 137 DDI_DMA_DONTWAIT, NULL, &edb->edb_va, &size_allocated, 138 &edb->edb_acc_hdl); 139 if (ret != DDI_SUCCESS) { 140 ena_err(ena, "!failed to allocate %lu bytes of DMA " 141 "memory: %d", size, ret); 142 ena_dma_free(edb); 143 return (B_FALSE); 144 } 145 146 bzero(edb->edb_va, size_allocated); 147 148 ret = ddi_dma_addr_bind_handle(edb->edb_dma_hdl, NULL, edb->edb_va, 149 size_allocated, DDI_DMA_RDWR | flags, DDI_DMA_DONTWAIT, NULL, NULL, 150 NULL); 151 if (ret != DDI_SUCCESS) { 152 ena_err(ena, "!failed to bind %lu bytes of DMA " 153 "memory: %d", size_allocated, ret); 154 ena_dma_free(edb); 155 return (B_FALSE); 156 } 157 158 edb->edb_len = size; 159 edb->edb_real_len = size_allocated; 160 edb->edb_cookie = ddi_dma_cookie_one(edb->edb_dma_hdl); 161 return (B_TRUE); 162 } 163 164 /* 165 * Write the physical DMA address to the ENA hardware address pointer. 166 * While the DMA engine should guarantee that the allocation is within 167 * the specified range, we double check here to catch programmer error 168 * and avoid hard-to-debug situations. 169 */ 170 void 171 ena_set_dma_addr(const ena_t *ena, const uint64_t phys_addr, 172 enahw_addr_t *hwaddrp) 173 { 174 ENA_DMA_VERIFY_ADDR(ena, phys_addr); 175 hwaddrp->ea_low = (uint32_t)phys_addr; 176 hwaddrp->ea_high = (uint16_t)(phys_addr >> 32); 177 } 178 179 /* 180 * The same as the above function, but writes the phsyical address to 181 * the supplied value pointers instead. Mostly used as a sanity check 182 * that the address fits in the reported DMA width. 183 */ 184 void 185 ena_set_dma_addr_values(const ena_t *ena, const uint64_t phys_addr, 186 uint32_t *dst_low, uint16_t *dst_high) 187 { 188 ENA_DMA_VERIFY_ADDR(ena, phys_addr); 189 *dst_low = (uint32_t)phys_addr; 190 *dst_high = (uint16_t)(phys_addr >> 32); 191 } 192