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