]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright(c) 2014-2015 Broadcom Corporation. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Broadcom Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include <inttypes.h> | |
35 | ||
36 | #include <rte_memzone.h> | |
37 | #include <rte_malloc.h> | |
38 | ||
39 | #include "bnxt.h" | |
40 | #include "bnxt_vnic.h" | |
41 | #include "hsi_struct_def_dpdk.h" | |
42 | ||
43 | /* | |
44 | * VNIC Functions | |
45 | */ | |
46 | ||
47 | static void prandom_bytes(void *dest_ptr, size_t len) | |
48 | { | |
49 | char *dest = (char *)dest_ptr; | |
50 | uint64_t rb; | |
51 | ||
52 | while (len) { | |
53 | rb = rte_rand(); | |
54 | if (len >= 8) { | |
55 | memcpy(dest, &rb, 8); | |
56 | len -= 8; | |
57 | dest += 8; | |
58 | } else { | |
59 | memcpy(dest, &rb, len); | |
60 | dest += len; | |
61 | len = 0; | |
62 | } | |
63 | } | |
64 | } | |
65 | ||
66 | void bnxt_init_vnics(struct bnxt *bp) | |
67 | { | |
68 | struct bnxt_vnic_info *vnic; | |
69 | uint16_t max_vnics; | |
70 | int i, j; | |
71 | ||
72 | if (BNXT_PF(bp)) { | |
73 | struct bnxt_pf_info *pf = &bp->pf; | |
74 | ||
75 | max_vnics = pf->max_vnics; | |
76 | } else { | |
77 | struct bnxt_vf_info *vf = &bp->vf; | |
78 | ||
79 | max_vnics = vf->max_vnics; | |
80 | } | |
81 | STAILQ_INIT(&bp->free_vnic_list); | |
82 | for (i = 0; i < max_vnics; i++) { | |
83 | vnic = &bp->vnic_info[i]; | |
84 | vnic->fw_vnic_id = (uint16_t)HWRM_NA_SIGNATURE; | |
85 | vnic->fw_rss_cos_lb_ctx = (uint16_t)HWRM_NA_SIGNATURE; | |
86 | vnic->ctx_is_rss_cos_lb = HW_CONTEXT_NONE; | |
87 | ||
88 | for (j = 0; j < MAX_QUEUES_PER_VNIC; j++) | |
89 | vnic->fw_grp_ids[j] = (uint16_t)HWRM_NA_SIGNATURE; | |
90 | ||
91 | prandom_bytes(vnic->rss_hash_key, HW_HASH_KEY_SIZE); | |
92 | STAILQ_INIT(&vnic->filter); | |
93 | STAILQ_INSERT_TAIL(&bp->free_vnic_list, vnic, next); | |
94 | } | |
95 | for (i = 0; i < MAX_FF_POOLS; i++) | |
96 | STAILQ_INIT(&bp->ff_pool[i]); | |
97 | } | |
98 | ||
99 | int bnxt_free_vnic(struct bnxt *bp, struct bnxt_vnic_info *vnic, | |
100 | int pool) | |
101 | { | |
102 | struct bnxt_vnic_info *temp; | |
103 | ||
104 | temp = STAILQ_FIRST(&bp->ff_pool[pool]); | |
105 | while (temp) { | |
106 | if (temp == vnic) { | |
107 | STAILQ_REMOVE(&bp->ff_pool[pool], vnic, | |
108 | bnxt_vnic_info, next); | |
109 | vnic->fw_vnic_id = (uint16_t)HWRM_NA_SIGNATURE; | |
110 | STAILQ_INSERT_TAIL(&bp->free_vnic_list, vnic, | |
111 | next); | |
112 | return 0; | |
113 | } | |
114 | temp = STAILQ_NEXT(temp, next); | |
115 | } | |
116 | RTE_LOG(ERR, PMD, "VNIC %p is not found in pool[%d]\n", vnic, pool); | |
117 | return -EINVAL; | |
118 | } | |
119 | ||
120 | struct bnxt_vnic_info *bnxt_alloc_vnic(struct bnxt *bp) | |
121 | { | |
122 | struct bnxt_vnic_info *vnic; | |
123 | ||
124 | /* Find the 1st unused vnic from the free_vnic_list pool*/ | |
125 | vnic = STAILQ_FIRST(&bp->free_vnic_list); | |
126 | if (!vnic) { | |
127 | RTE_LOG(ERR, PMD, "No more free VNIC resources\n"); | |
128 | return NULL; | |
129 | } | |
130 | STAILQ_REMOVE_HEAD(&bp->free_vnic_list, next); | |
131 | return vnic; | |
132 | } | |
133 | ||
134 | void bnxt_free_all_vnics(struct bnxt *bp) | |
135 | { | |
136 | struct bnxt_vnic_info *temp, *next; | |
137 | int i; | |
138 | ||
139 | for (i = 0; i < MAX_FF_POOLS; i++) { | |
140 | temp = STAILQ_FIRST(&bp->ff_pool[i]); | |
141 | while (temp) { | |
142 | next = STAILQ_NEXT(temp, next); | |
143 | STAILQ_REMOVE(&bp->ff_pool[i], temp, bnxt_vnic_info, | |
144 | next); | |
145 | STAILQ_INSERT_TAIL(&bp->free_vnic_list, temp, next); | |
146 | temp = next; | |
147 | } | |
148 | } | |
149 | } | |
150 | ||
151 | void bnxt_free_vnic_attributes(struct bnxt *bp) | |
152 | { | |
153 | struct bnxt_vnic_info *vnic; | |
154 | ||
155 | STAILQ_FOREACH(vnic, &bp->free_vnic_list, next) { | |
156 | if (vnic->rss_table) { | |
157 | /* 'Unreserve' the rss_table */ | |
158 | /* N/A */ | |
159 | ||
160 | vnic->rss_table = NULL; | |
161 | } | |
162 | ||
163 | if (vnic->rss_hash_key) { | |
164 | /* 'Unreserve' the rss_hash_key */ | |
165 | /* N/A */ | |
166 | ||
167 | vnic->rss_hash_key = NULL; | |
168 | } | |
169 | } | |
170 | } | |
171 | ||
172 | int bnxt_alloc_vnic_attributes(struct bnxt *bp) | |
173 | { | |
174 | struct bnxt_vnic_info *vnic; | |
175 | struct rte_pci_device *pdev = bp->pdev; | |
176 | const struct rte_memzone *mz; | |
177 | char mz_name[RTE_MEMZONE_NAMESIZE]; | |
178 | uint32_t entry_length = RTE_CACHE_LINE_ROUNDUP( | |
179 | HW_HASH_INDEX_SIZE * sizeof(*vnic->rss_table) + | |
180 | HW_HASH_KEY_SIZE); | |
181 | uint16_t max_vnics; | |
182 | int i; | |
183 | ||
184 | if (BNXT_PF(bp)) { | |
185 | struct bnxt_pf_info *pf = &bp->pf; | |
186 | ||
187 | max_vnics = pf->max_vnics; | |
188 | } else { | |
189 | struct bnxt_vf_info *vf = &bp->vf; | |
190 | ||
191 | max_vnics = vf->max_vnics; | |
192 | } | |
193 | snprintf(mz_name, RTE_MEMZONE_NAMESIZE, | |
194 | "bnxt_%04x:%02x:%02x:%02x_vnicattr", pdev->addr.domain, | |
195 | pdev->addr.bus, pdev->addr.devid, pdev->addr.function); | |
196 | mz_name[RTE_MEMZONE_NAMESIZE - 1] = 0; | |
197 | mz = rte_memzone_lookup(mz_name); | |
198 | if (!mz) { | |
199 | mz = rte_memzone_reserve(mz_name, | |
200 | entry_length * max_vnics, | |
201 | SOCKET_ID_ANY, | |
202 | RTE_MEMZONE_2MB | | |
203 | RTE_MEMZONE_SIZE_HINT_ONLY); | |
204 | if (!mz) | |
205 | return -ENOMEM; | |
206 | } | |
207 | ||
208 | for (i = 0; i < max_vnics; i++) { | |
209 | vnic = &bp->vnic_info[i]; | |
210 | ||
211 | /* Allocate rss table and hash key */ | |
212 | vnic->rss_table = | |
213 | (void *)((char *)mz->addr + (entry_length * i)); | |
214 | memset(vnic->rss_table, -1, entry_length); | |
215 | ||
216 | vnic->rss_table_dma_addr = mz->phys_addr + (entry_length * i); | |
217 | vnic->rss_hash_key = (void *)((char *)vnic->rss_table + | |
218 | HW_HASH_INDEX_SIZE * sizeof(*vnic->rss_table)); | |
219 | ||
220 | vnic->rss_hash_key_dma_addr = vnic->rss_table_dma_addr + | |
221 | HW_HASH_INDEX_SIZE * sizeof(*vnic->rss_table); | |
222 | } | |
223 | ||
224 | return 0; | |
225 | } | |
226 | ||
227 | void bnxt_free_vnic_mem(struct bnxt *bp) | |
228 | { | |
229 | struct bnxt_vnic_info *vnic; | |
230 | uint16_t max_vnics, i; | |
231 | ||
232 | if (bp->vnic_info == NULL) | |
233 | return; | |
234 | ||
235 | if (BNXT_PF(bp)) { | |
236 | struct bnxt_pf_info *pf = &bp->pf; | |
237 | ||
238 | max_vnics = pf->max_vnics; | |
239 | } else { | |
240 | struct bnxt_vf_info *vf = &bp->vf; | |
241 | ||
242 | max_vnics = vf->max_vnics; | |
243 | } | |
244 | for (i = 0; i < max_vnics; i++) { | |
245 | vnic = &bp->vnic_info[i]; | |
246 | if (vnic->fw_vnic_id != (uint16_t)HWRM_NA_SIGNATURE) { | |
247 | RTE_LOG(ERR, PMD, "VNIC is not freed yet!\n"); | |
248 | /* TODO Call HWRM to free VNIC */ | |
249 | } | |
250 | } | |
251 | ||
252 | rte_free(bp->vnic_info); | |
253 | bp->vnic_info = NULL; | |
254 | } | |
255 | ||
256 | int bnxt_alloc_vnic_mem(struct bnxt *bp) | |
257 | { | |
258 | struct bnxt_vnic_info *vnic_mem; | |
259 | uint16_t max_vnics; | |
260 | ||
261 | if (BNXT_PF(bp)) { | |
262 | struct bnxt_pf_info *pf = &bp->pf; | |
263 | ||
264 | max_vnics = pf->max_vnics; | |
265 | } else { | |
266 | struct bnxt_vf_info *vf = &bp->vf; | |
267 | ||
268 | max_vnics = vf->max_vnics; | |
269 | } | |
270 | /* Allocate memory for VNIC pool and filter pool */ | |
271 | vnic_mem = rte_zmalloc("bnxt_vnic_info", | |
272 | max_vnics * sizeof(struct bnxt_vnic_info), 0); | |
273 | if (vnic_mem == NULL) { | |
274 | RTE_LOG(ERR, PMD, "Failed to alloc memory for %d VNICs", | |
275 | max_vnics); | |
276 | return -ENOMEM; | |
277 | } | |
278 | bp->vnic_info = vnic_mem; | |
279 | return 0; | |
280 | } |