xref: /titanic_50/usr/src/uts/common/io/i40e/i40e_osdep.c (revision 6845d4e7f857afe78e21cd55b143355db45f1c41)
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