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