1/******************************************************************************
2
3  Copyright (c) 2013-2018, Intel Corporation
4  All rights reserved.
5
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions are met:
8
9   1. Redistributions of source code must retain the above copyright notice,
10      this list of conditions and the following disclaimer.
11
12   2. Redistributions in binary form must reproduce the above copyright
13      notice, this list of conditions and the following disclaimer in the
14      documentation and/or other materials provided with the distribution.
15
16   3. Neither the name of the Intel Corporation nor the names of its
17      contributors may be used to endorse or promote products derived from
18      this software without specific prior written permission.
19
20  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  POSSIBILITY OF SUCH DAMAGE.
31
32******************************************************************************/
33/*$FreeBSD$*/
34
35#include <sys/limits.h>
36#include <sys/time.h>
37
38#include "ixl.h"
39
40/********************************************************************
41 * Manage DMA'able memory.
42 *******************************************************************/
43static void
44i40e_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error)
45{
46        if (error)
47                return;
48        *(bus_addr_t *) arg = segs->ds_addr;
49}
50
51i40e_status
52i40e_allocate_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem, u32 size)
53{
54	mem->va = malloc(size, M_IXL, M_NOWAIT | M_ZERO);
55	return (mem->va == NULL);
56}
57
58i40e_status
59i40e_free_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem)
60{
61	free(mem->va, M_IXL);
62	mem->va = NULL;
63
64	return (I40E_SUCCESS);
65}
66
67i40e_status
68i40e_allocate_dma_mem(struct i40e_hw *hw, struct i40e_dma_mem *mem,
69	enum i40e_memory_type type __unused, u64 size, u32 alignment)
70{
71	device_t	dev = ((struct i40e_osdep *)hw->back)->dev;
72	int		err;
73
74
75	err = bus_dma_tag_create(bus_get_dma_tag(dev),	/* parent */
76			       alignment, 0,	/* alignment, bounds */
77			       BUS_SPACE_MAXADDR,	/* lowaddr */
78			       BUS_SPACE_MAXADDR,	/* highaddr */
79			       NULL, NULL,	/* filter, filterarg */
80			       size,	/* maxsize */
81			       1,	/* nsegments */
82			       size,	/* maxsegsize */
83			       BUS_DMA_ALLOCNOW, /* flags */
84			       NULL,	/* lockfunc */
85			       NULL,	/* lockfuncarg */
86			       &mem->tag);
87	if (err != 0) {
88		device_printf(dev,
89		    "i40e_allocate_dma: bus_dma_tag_create failed, "
90		    "error %u\n", err);
91		goto fail_0;
92	}
93	err = bus_dmamem_alloc(mem->tag, (void **)&mem->va,
94			     BUS_DMA_NOWAIT | BUS_DMA_ZERO, &mem->map);
95	if (err != 0) {
96		device_printf(dev,
97		    "i40e_allocate_dma: bus_dmamem_alloc failed, "
98		    "error %u\n", err);
99		goto fail_1;
100	}
101	err = bus_dmamap_load(mem->tag, mem->map, mem->va,
102			    size,
103			    i40e_dmamap_cb,
104			    &mem->pa,
105			    BUS_DMA_NOWAIT);
106	if (err != 0) {
107		device_printf(dev,
108		    "i40e_allocate_dma: bus_dmamap_load failed, "
109		    "error %u\n", err);
110		goto fail_2;
111	}
112	mem->nseg = 1;
113	mem->size = size;
114	bus_dmamap_sync(mem->tag, mem->map,
115	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
116	return (I40E_SUCCESS);
117fail_2:
118	bus_dmamem_free(mem->tag, mem->va, mem->map);
119fail_1:
120	bus_dma_tag_destroy(mem->tag);
121fail_0:
122	mem->map = NULL;
123	mem->tag = NULL;
124	return (err);
125}
126
127i40e_status
128i40e_free_dma_mem(struct i40e_hw *hw, struct i40e_dma_mem *mem)
129{
130	bus_dmamap_sync(mem->tag, mem->map,
131	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
132	bus_dmamap_unload(mem->tag, mem->map);
133	bus_dmamem_free(mem->tag, mem->va, mem->map);
134	bus_dma_tag_destroy(mem->tag);
135	return (I40E_SUCCESS);
136}
137
138void
139i40e_init_spinlock(struct i40e_spinlock *lock)
140{
141	mtx_init(&lock->mutex, "mutex",
142	    "ixl spinlock", MTX_DEF | MTX_DUPOK);
143}
144
145void
146i40e_acquire_spinlock(struct i40e_spinlock *lock)
147{
148	mtx_lock(&lock->mutex);
149}
150
151void
152i40e_release_spinlock(struct i40e_spinlock *lock)
153{
154	mtx_unlock(&lock->mutex);
155}
156
157void
158i40e_destroy_spinlock(struct i40e_spinlock *lock)
159{
160	if (mtx_initialized(&lock->mutex))
161		mtx_destroy(&lock->mutex);
162}
163
164#ifndef MSEC_2_TICKS
165#define MSEC_2_TICKS(m) max(1, (uint32_t)((hz == 1000) ? \
166	  (m) : ((uint64_t)(m) * (uint64_t)hz)/(uint64_t)1000))
167#endif
168
169void
170i40e_msec_pause(int msecs)
171{
172	pause("i40e_msec_pause", MSEC_2_TICKS(msecs));
173}
174
175/*
176 * Helper function for debug statement printing
177 */
178void
179i40e_debug_shared(struct i40e_hw *hw, enum i40e_debug_mask mask, char *fmt, ...)
180{
181	va_list args;
182	device_t dev;
183
184	if (!(mask & ((struct i40e_hw *)hw)->debug_mask))
185		return;
186
187	dev = ((struct i40e_osdep *)hw->back)->dev;
188
189	/* Re-implement device_printf() */
190	device_print_prettyname(dev);
191	va_start(args, fmt);
192	vprintf(fmt, args);
193	va_end(args);
194}
195
196const char *
197ixl_vc_opcode_str(uint16_t op)
198{
199	switch (op) {
200	case VIRTCHNL_OP_VERSION:
201		return ("VERSION");
202	case VIRTCHNL_OP_RESET_VF:
203		return ("RESET_VF");
204	case VIRTCHNL_OP_GET_VF_RESOURCES:
205		return ("GET_VF_RESOURCES");
206	case VIRTCHNL_OP_CONFIG_TX_QUEUE:
207		return ("CONFIG_TX_QUEUE");
208	case VIRTCHNL_OP_CONFIG_RX_QUEUE:
209		return ("CONFIG_RX_QUEUE");
210	case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
211		return ("CONFIG_VSI_QUEUES");
212	case VIRTCHNL_OP_CONFIG_IRQ_MAP:
213		return ("CONFIG_IRQ_MAP");
214	case VIRTCHNL_OP_ENABLE_QUEUES:
215		return ("ENABLE_QUEUES");
216	case VIRTCHNL_OP_DISABLE_QUEUES:
217		return ("DISABLE_QUEUES");
218	case VIRTCHNL_OP_ADD_ETH_ADDR:
219		return ("ADD_ETH_ADDR");
220	case VIRTCHNL_OP_DEL_ETH_ADDR:
221		return ("DEL_ETH_ADDR");
222	case VIRTCHNL_OP_ADD_VLAN:
223		return ("ADD_VLAN");
224	case VIRTCHNL_OP_DEL_VLAN:
225		return ("DEL_VLAN");
226	case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
227		return ("CONFIG_PROMISCUOUS_MODE");
228	case VIRTCHNL_OP_GET_STATS:
229		return ("GET_STATS");
230	case VIRTCHNL_OP_RSVD:
231		return ("RSVD");
232	case VIRTCHNL_OP_EVENT:
233		return ("EVENT");
234	case VIRTCHNL_OP_CONFIG_RSS_KEY:
235		return ("CONFIG_RSS_KEY");
236	case VIRTCHNL_OP_CONFIG_RSS_LUT:
237		return ("CONFIG_RSS_LUT");
238	case VIRTCHNL_OP_GET_RSS_HENA_CAPS:
239		return ("GET_RSS_HENA_CAPS");
240	case VIRTCHNL_OP_SET_RSS_HENA:
241		return ("SET_RSS_HENA");
242	default:
243		return ("UNKNOWN");
244	}
245}
246
247u16
248i40e_read_pci_cfg(struct i40e_hw *hw, u32 reg)
249{
250        u16 value;
251
252        value = pci_read_config(((struct i40e_osdep *)hw->back)->dev,
253            reg, 2);
254
255        return (value);
256}
257
258void
259i40e_write_pci_cfg(struct i40e_hw *hw, u32 reg, u16 value)
260{
261        pci_write_config(((struct i40e_osdep *)hw->back)->dev,
262            reg, value, 2);
263}
264
265