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
i40e_allocate_virt_mem(struct i40e_hw * hw,struct i40e_virt_mem * mem,u32 size)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
i40e_free_virt_mem(struct i40e_hw * hw,struct i40e_virt_mem * mem)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
i40e_allocate_dma_mem(struct i40e_hw * hw,struct i40e_dma_mem * mem,enum i40e_memory_type type,u64 size,u32 alignment)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
i40e_free_dma_mem(struct i40e_hw * hw,struct i40e_dma_mem * mem)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
i40e_init_spinlock(struct i40e_spinlock * lock)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
i40e_acquire_spinlock(struct i40e_spinlock * lock)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
i40e_release_spinlock(struct i40e_spinlock * lock)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
i40e_destroy_spinlock(struct i40e_spinlock * lock)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
i40e_set_hw_bus_info(struct i40e_hw * hw)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
i40e_debug(void * hw,u32 mask,char * fmt,...)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