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