1*9d26e4fcSRobert Mustacchi /* 2*9d26e4fcSRobert Mustacchi * This file and its contents are supplied under the terms of the 3*9d26e4fcSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0. 4*9d26e4fcSRobert Mustacchi * You may only use this file in accordance with the terms of version 5*9d26e4fcSRobert Mustacchi * 1.0 of the CDDL. 6*9d26e4fcSRobert Mustacchi * 7*9d26e4fcSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this 8*9d26e4fcSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at 9*9d26e4fcSRobert Mustacchi * http://www.illumos.org/license/CDDL. 10*9d26e4fcSRobert Mustacchi */ 11*9d26e4fcSRobert Mustacchi 12*9d26e4fcSRobert Mustacchi /* 13*9d26e4fcSRobert Mustacchi * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved. 14*9d26e4fcSRobert Mustacchi * Copyright 2016 Joyent, Inc. 15*9d26e4fcSRobert Mustacchi */ 16*9d26e4fcSRobert Mustacchi 17*9d26e4fcSRobert Mustacchi #include "i40e_sw.h" 18*9d26e4fcSRobert Mustacchi #include "i40e_type.h" 19*9d26e4fcSRobert Mustacchi #include "i40e_alloc.h" 20*9d26e4fcSRobert Mustacchi #include "i40e_osdep.h" 21*9d26e4fcSRobert Mustacchi 22*9d26e4fcSRobert Mustacchi #include <sys/dtrace.h> 23*9d26e4fcSRobert Mustacchi 24*9d26e4fcSRobert Mustacchi /* ARGSUSED */ 25*9d26e4fcSRobert Mustacchi i40e_status 26*9d26e4fcSRobert Mustacchi i40e_allocate_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem, u32 size) 27*9d26e4fcSRobert Mustacchi { 28*9d26e4fcSRobert Mustacchi mem->va = kmem_zalloc(size, KM_SLEEP); 29*9d26e4fcSRobert Mustacchi mem->size = size; 30*9d26e4fcSRobert Mustacchi return (I40E_SUCCESS); 31*9d26e4fcSRobert Mustacchi } 32*9d26e4fcSRobert Mustacchi 33*9d26e4fcSRobert Mustacchi /* ARGSUSED */ 34*9d26e4fcSRobert Mustacchi i40e_status 35*9d26e4fcSRobert Mustacchi i40e_free_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem) 36*9d26e4fcSRobert Mustacchi { 37*9d26e4fcSRobert Mustacchi if (mem->va != NULL) 38*9d26e4fcSRobert Mustacchi kmem_free(mem->va, mem->size); 39*9d26e4fcSRobert Mustacchi return (I40E_SUCCESS); 40*9d26e4fcSRobert Mustacchi } 41*9d26e4fcSRobert Mustacchi 42*9d26e4fcSRobert Mustacchi /* ARGSUSED */ 43*9d26e4fcSRobert Mustacchi i40e_status 44*9d26e4fcSRobert Mustacchi i40e_allocate_dma_mem(struct i40e_hw *hw, struct i40e_dma_mem *mem, 45*9d26e4fcSRobert Mustacchi enum i40e_memory_type type, u64 size, u32 alignment) 46*9d26e4fcSRobert Mustacchi { 47*9d26e4fcSRobert Mustacchi int rc; 48*9d26e4fcSRobert Mustacchi i40e_t *i40e = OS_DEP(hw)->ios_i40e; 49*9d26e4fcSRobert Mustacchi dev_info_t *dip = i40e->i40e_dip; 50*9d26e4fcSRobert Mustacchi size_t len; 51*9d26e4fcSRobert Mustacchi ddi_dma_cookie_t cookie; 52*9d26e4fcSRobert Mustacchi uint_t cookie_num; 53*9d26e4fcSRobert Mustacchi ddi_dma_attr_t attr; 54*9d26e4fcSRobert Mustacchi 55*9d26e4fcSRobert Mustacchi /* 56*9d26e4fcSRobert Mustacchi * Because we need to honor the specified alignment, we need to 57*9d26e4fcSRobert Mustacchi * dynamically construct the attributes. We save the alignment for 58*9d26e4fcSRobert Mustacchi * debugging purposes. 59*9d26e4fcSRobert Mustacchi */ 60*9d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_static_dma_attr, &attr, sizeof (ddi_dma_attr_t)); 61*9d26e4fcSRobert Mustacchi attr.dma_attr_align = alignment; 62*9d26e4fcSRobert Mustacchi mem->idm_alignment = alignment; 63*9d26e4fcSRobert Mustacchi rc = ddi_dma_alloc_handle(dip, &i40e->i40e_static_dma_attr, 64*9d26e4fcSRobert Mustacchi DDI_DMA_DONTWAIT, NULL, &mem->idm_dma_handle); 65*9d26e4fcSRobert Mustacchi if (rc != DDI_SUCCESS) { 66*9d26e4fcSRobert Mustacchi mem->idm_dma_handle = NULL; 67*9d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to allocate DMA handle for common " 68*9d26e4fcSRobert Mustacchi "code: %d", rc); 69*9d26e4fcSRobert Mustacchi 70*9d26e4fcSRobert Mustacchi /* 71*9d26e4fcSRobert Mustacchi * Swallow unknown errors and treat them like we do 72*9d26e4fcSRobert Mustacchi * DDI_DMA_NORESOURCES, in other words, a memory error. 73*9d26e4fcSRobert Mustacchi */ 74*9d26e4fcSRobert Mustacchi if (rc == DDI_DMA_BADATTR) 75*9d26e4fcSRobert Mustacchi return (I40E_ERR_PARAM); 76*9d26e4fcSRobert Mustacchi return (I40E_ERR_NO_MEMORY); 77*9d26e4fcSRobert Mustacchi } 78*9d26e4fcSRobert Mustacchi 79*9d26e4fcSRobert Mustacchi rc = ddi_dma_mem_alloc(mem->idm_dma_handle, size, 80*9d26e4fcSRobert Mustacchi &i40e->i40e_buf_acc_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 81*9d26e4fcSRobert Mustacchi NULL, (caddr_t *)&mem->va, &len, &mem->idm_acc_handle); 82*9d26e4fcSRobert Mustacchi if (rc != DDI_SUCCESS) { 83*9d26e4fcSRobert Mustacchi mem->idm_acc_handle = NULL; 84*9d26e4fcSRobert Mustacchi mem->va = NULL; 85*9d26e4fcSRobert Mustacchi ASSERT(mem->idm_dma_handle != NULL); 86*9d26e4fcSRobert Mustacchi ddi_dma_free_handle(&mem->idm_dma_handle); 87*9d26e4fcSRobert Mustacchi mem->idm_dma_handle = NULL; 88*9d26e4fcSRobert Mustacchi 89*9d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to allocate %" PRIu64 " bytes of DMA " 90*9d26e4fcSRobert Mustacchi "memory for common code", size); 91*9d26e4fcSRobert Mustacchi return (I40E_ERR_NO_MEMORY); 92*9d26e4fcSRobert Mustacchi } 93*9d26e4fcSRobert Mustacchi 94*9d26e4fcSRobert Mustacchi bzero(mem->va, len); 95*9d26e4fcSRobert Mustacchi 96*9d26e4fcSRobert Mustacchi rc = ddi_dma_addr_bind_handle(mem->idm_dma_handle, NULL, mem->va, len, 97*9d26e4fcSRobert Mustacchi DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL, 98*9d26e4fcSRobert Mustacchi &cookie, &cookie_num); 99*9d26e4fcSRobert Mustacchi if (rc != DDI_DMA_MAPPED) { 100*9d26e4fcSRobert Mustacchi mem->pa = NULL; 101*9d26e4fcSRobert Mustacchi ASSERT(mem->idm_acc_handle != NULL); 102*9d26e4fcSRobert Mustacchi ddi_dma_mem_free(&mem->idm_acc_handle); 103*9d26e4fcSRobert Mustacchi mem->idm_acc_handle = NULL; 104*9d26e4fcSRobert Mustacchi mem->va = NULL; 105*9d26e4fcSRobert Mustacchi ASSERT(mem->idm_dma_handle != NULL); 106*9d26e4fcSRobert Mustacchi ddi_dma_free_handle(&mem->idm_dma_handle); 107*9d26e4fcSRobert Mustacchi mem->idm_dma_handle = NULL; 108*9d26e4fcSRobert Mustacchi 109*9d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to bind %ld byte sized dma region: %d", 110*9d26e4fcSRobert Mustacchi len, rc); 111*9d26e4fcSRobert Mustacchi switch (rc) { 112*9d26e4fcSRobert Mustacchi case DDI_DMA_INUSE: 113*9d26e4fcSRobert Mustacchi return (I40E_ERR_NOT_READY); 114*9d26e4fcSRobert Mustacchi case DDI_DMA_TOOBIG: 115*9d26e4fcSRobert Mustacchi return (I40E_ERR_INVALID_SIZE); 116*9d26e4fcSRobert Mustacchi case DDI_DMA_NOMAPPING: 117*9d26e4fcSRobert Mustacchi case DDI_DMA_NORESOURCES: 118*9d26e4fcSRobert Mustacchi default: 119*9d26e4fcSRobert Mustacchi return (I40E_ERR_NO_MEMORY); 120*9d26e4fcSRobert Mustacchi } 121*9d26e4fcSRobert Mustacchi } 122*9d26e4fcSRobert Mustacchi 123*9d26e4fcSRobert Mustacchi ASSERT(cookie_num == 1); 124*9d26e4fcSRobert Mustacchi mem->pa = cookie.dmac_laddress; 125*9d26e4fcSRobert Mustacchi /* 126*9d26e4fcSRobert Mustacchi * Lint doesn't like this because the common code gives us a uint64_t as 127*9d26e4fcSRobert Mustacchi * input, but the common code then asks us to assign it to a size_t. So 128*9d26e4fcSRobert Mustacchi * lint's right, but in this case there isn't much we can do. 129*9d26e4fcSRobert Mustacchi */ 130*9d26e4fcSRobert Mustacchi mem->size = (size_t)size; 131*9d26e4fcSRobert Mustacchi 132*9d26e4fcSRobert Mustacchi return (I40E_SUCCESS); 133*9d26e4fcSRobert Mustacchi } 134*9d26e4fcSRobert Mustacchi 135*9d26e4fcSRobert Mustacchi /* ARGSUSED */ 136*9d26e4fcSRobert Mustacchi i40e_status 137*9d26e4fcSRobert Mustacchi i40e_free_dma_mem(struct i40e_hw *hw, struct i40e_dma_mem *mem) 138*9d26e4fcSRobert Mustacchi { 139*9d26e4fcSRobert Mustacchi if (mem->pa != 0) { 140*9d26e4fcSRobert Mustacchi VERIFY(mem->idm_dma_handle != NULL); 141*9d26e4fcSRobert Mustacchi (void) ddi_dma_unbind_handle(mem->idm_dma_handle); 142*9d26e4fcSRobert Mustacchi mem->pa = 0; 143*9d26e4fcSRobert Mustacchi mem->size = 0; 144*9d26e4fcSRobert Mustacchi } 145*9d26e4fcSRobert Mustacchi 146*9d26e4fcSRobert Mustacchi if (mem->idm_acc_handle != NULL) { 147*9d26e4fcSRobert Mustacchi ddi_dma_mem_free(&mem->idm_acc_handle); 148*9d26e4fcSRobert Mustacchi mem->idm_acc_handle = NULL; 149*9d26e4fcSRobert Mustacchi mem->va = NULL; 150*9d26e4fcSRobert Mustacchi } 151*9d26e4fcSRobert Mustacchi 152*9d26e4fcSRobert Mustacchi if (mem->idm_dma_handle != NULL) { 153*9d26e4fcSRobert Mustacchi ddi_dma_free_handle(&mem->idm_dma_handle); 154*9d26e4fcSRobert Mustacchi mem->idm_dma_handle = NULL; 155*9d26e4fcSRobert Mustacchi } 156*9d26e4fcSRobert Mustacchi 157*9d26e4fcSRobert Mustacchi /* 158*9d26e4fcSRobert Mustacchi * Watch out for sloppiness. 159*9d26e4fcSRobert Mustacchi */ 160*9d26e4fcSRobert Mustacchi ASSERT(mem->pa == 0); 161*9d26e4fcSRobert Mustacchi ASSERT(mem->va == NULL); 162*9d26e4fcSRobert Mustacchi ASSERT(mem->size == 0); 163*9d26e4fcSRobert Mustacchi mem->idm_alignment = UINT32_MAX; 164*9d26e4fcSRobert Mustacchi 165*9d26e4fcSRobert Mustacchi return (I40E_SUCCESS); 166*9d26e4fcSRobert Mustacchi } 167*9d26e4fcSRobert Mustacchi 168*9d26e4fcSRobert Mustacchi /* 169*9d26e4fcSRobert Mustacchi * The common code wants to initialize its 'spinlocks' here, aka adaptive 170*9d26e4fcSRobert Mustacchi * mutexes. At this time these are only used to maintain the adminq's data and 171*9d26e4fcSRobert Mustacchi * as such it will only be used outside of interrupt context and even then, 172*9d26e4fcSRobert Mustacchi * we're not going to actually end up ever doing anything above lock level and 173*9d26e4fcSRobert Mustacchi * up in doing stuff with high level interrupts. 174*9d26e4fcSRobert Mustacchi */ 175*9d26e4fcSRobert Mustacchi void 176*9d26e4fcSRobert Mustacchi i40e_init_spinlock(struct i40e_spinlock *lock) 177*9d26e4fcSRobert Mustacchi { 178*9d26e4fcSRobert Mustacchi mutex_init(&lock->ispl_mutex, NULL, MUTEX_DRIVER, NULL); 179*9d26e4fcSRobert Mustacchi } 180*9d26e4fcSRobert Mustacchi 181*9d26e4fcSRobert Mustacchi void 182*9d26e4fcSRobert Mustacchi i40e_acquire_spinlock(struct i40e_spinlock *lock) 183*9d26e4fcSRobert Mustacchi { 184*9d26e4fcSRobert Mustacchi mutex_enter(&lock->ispl_mutex); 185*9d26e4fcSRobert Mustacchi } 186*9d26e4fcSRobert Mustacchi 187*9d26e4fcSRobert Mustacchi void 188*9d26e4fcSRobert Mustacchi i40e_release_spinlock(struct i40e_spinlock *lock) 189*9d26e4fcSRobert Mustacchi { 190*9d26e4fcSRobert Mustacchi mutex_exit(&lock->ispl_mutex); 191*9d26e4fcSRobert Mustacchi } 192*9d26e4fcSRobert Mustacchi 193*9d26e4fcSRobert Mustacchi void 194*9d26e4fcSRobert Mustacchi i40e_destroy_spinlock(struct i40e_spinlock *lock) 195*9d26e4fcSRobert Mustacchi { 196*9d26e4fcSRobert Mustacchi mutex_destroy(&lock->ispl_mutex); 197*9d26e4fcSRobert Mustacchi } 198*9d26e4fcSRobert Mustacchi 199*9d26e4fcSRobert Mustacchi boolean_t 200*9d26e4fcSRobert Mustacchi i40e_set_hw_bus_info(struct i40e_hw *hw) 201*9d26e4fcSRobert Mustacchi { 202*9d26e4fcSRobert Mustacchi uint8_t pcie_id = PCI_CAP_ID_PCI_E; 203*9d26e4fcSRobert Mustacchi uint16_t pcie_cap, value; 204*9d26e4fcSRobert Mustacchi int status; 205*9d26e4fcSRobert Mustacchi 206*9d26e4fcSRobert Mustacchi /* locate the pci-e capability block */ 207*9d26e4fcSRobert Mustacchi status = pci_lcap_locate((OS_DEP(hw))->ios_cfg_handle, pcie_id, 208*9d26e4fcSRobert Mustacchi &pcie_cap); 209*9d26e4fcSRobert Mustacchi if (status != DDI_SUCCESS) { 210*9d26e4fcSRobert Mustacchi i40e_error(OS_DEP(hw)->ios_i40e, "failed to locate PCIe " 211*9d26e4fcSRobert Mustacchi "capability block: %d", 212*9d26e4fcSRobert Mustacchi status); 213*9d26e4fcSRobert Mustacchi return (B_FALSE); 214*9d26e4fcSRobert Mustacchi } 215*9d26e4fcSRobert Mustacchi 216*9d26e4fcSRobert Mustacchi value = pci_config_get16(OS_DEP(hw)->ios_cfg_handle, 217*9d26e4fcSRobert Mustacchi pcie_cap + PCIE_LINKSTS); 218*9d26e4fcSRobert Mustacchi 219*9d26e4fcSRobert Mustacchi i40e_set_pci_config_data(hw, value); 220*9d26e4fcSRobert Mustacchi 221*9d26e4fcSRobert Mustacchi return (B_TRUE); 222*9d26e4fcSRobert Mustacchi } 223*9d26e4fcSRobert Mustacchi 224*9d26e4fcSRobert Mustacchi /* ARGSUSED */ 225*9d26e4fcSRobert Mustacchi void 226*9d26e4fcSRobert Mustacchi i40e_debug(void *hw, u32 mask, char *fmt, ...) 227*9d26e4fcSRobert Mustacchi { 228*9d26e4fcSRobert Mustacchi char buf[1024]; 229*9d26e4fcSRobert Mustacchi va_list args; 230*9d26e4fcSRobert Mustacchi 231*9d26e4fcSRobert Mustacchi va_start(args, fmt); 232*9d26e4fcSRobert Mustacchi (void) vsnprintf(buf, sizeof (buf), fmt, args); 233*9d26e4fcSRobert Mustacchi va_end(args); 234*9d26e4fcSRobert Mustacchi 235*9d26e4fcSRobert Mustacchi DTRACE_PROBE2(i40e__debug, uint32_t, mask, char *, buf); 236*9d26e4fcSRobert Mustacchi } 237