]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bnxt/bnxt_sysctl.c
MFV: r319352
[FreeBSD/FreeBSD.git] / sys / dev / bnxt / bnxt_sysctl.c
1 /*-
2  * Broadcom NetXtreme-C/E network driver.
3  *
4  * Copyright (c) 2016 Broadcom, All Rights Reserved.
5  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
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  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
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  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/types.h>
33 #include <sys/sysctl.h>
34
35 #include "bnxt.h"
36 #include "bnxt_hwrm.h"
37 #include "bnxt_sysctl.h"
38
39 static int bnxt_vlan_only_sysctl(SYSCTL_HANDLER_ARGS);
40 /*
41  * We want to create:
42  * dev.bnxt.0.hwstats.txq0
43  * dev.bnxt.0.hwstats.txq0.txmbufs
44  * dev.bnxt.0.hwstats.rxq0
45  * dev.bnxt.0.hwstats.txq0.rxmbufs
46  * so the hwstats ctx list needs to be created in attach_post and populated
47  * during init.
48  *
49  * Then, it needs to be cleaned up in stop.
50  */
51
52 int
53 bnxt_init_sysctl_ctx(struct bnxt_softc *softc)
54 {
55         struct sysctl_ctx_list *ctx;
56
57         sysctl_ctx_init(&softc->hw_stats);
58         ctx = device_get_sysctl_ctx(softc->dev);
59         softc->hw_stats_oid = SYSCTL_ADD_NODE(ctx,
60             SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
61             "hwstats", CTLFLAG_RD, 0, "hardware statistics");
62         if (!softc->hw_stats_oid) {
63                 sysctl_ctx_free(&softc->hw_stats);
64                 return ENOMEM;
65         }
66
67         sysctl_ctx_init(&softc->ver_info->ver_ctx);
68         ctx = device_get_sysctl_ctx(softc->dev);
69         softc->ver_info->ver_oid = SYSCTL_ADD_NODE(ctx,
70             SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
71             "ver", CTLFLAG_RD, 0, "hardware/firmware version information");
72         if (!softc->ver_info->ver_oid) {
73                 sysctl_ctx_free(&softc->ver_info->ver_ctx);
74                 return ENOMEM;
75         }
76
77         sysctl_ctx_init(&softc->nvm_info->nvm_ctx);
78         ctx = device_get_sysctl_ctx(softc->dev);
79         softc->nvm_info->nvm_oid = SYSCTL_ADD_NODE(ctx,
80             SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
81             "nvram", CTLFLAG_RD, 0, "nvram information");
82         if (!softc->nvm_info->nvm_oid) {
83                 sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
84                 return ENOMEM;
85         }
86
87         return 0;
88 }
89
90 int
91 bnxt_free_sysctl_ctx(struct bnxt_softc *softc)
92 {
93         int orc;
94         int rc = 0;
95
96         if (softc->hw_stats_oid != NULL) {
97                 orc = sysctl_ctx_free(&softc->hw_stats);
98                 if (orc)
99                         rc = orc;
100                 else
101                         softc->hw_stats_oid = NULL;
102         }
103         if (softc->ver_info->ver_oid != NULL) {
104                 orc = sysctl_ctx_free(&softc->ver_info->ver_ctx);
105                 if (orc)
106                         rc = orc;
107                 else
108                         softc->ver_info->ver_oid = NULL;
109         }
110         if (softc->nvm_info->nvm_oid != NULL) {
111                 orc = sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
112                 if (orc)
113                         rc = orc;
114                 else
115                         softc->nvm_info->nvm_oid = NULL;
116         }
117
118         return rc;
119 }
120
121 int
122 bnxt_create_tx_sysctls(struct bnxt_softc *softc, int txr)
123 {
124         struct sysctl_oid *oid;
125         struct ctx_hw_stats *tx_stats = (void *)softc->tx_stats.idi_vaddr;
126         char    name[32];
127         char    desc[64];
128
129         sprintf(name, "txq%d", txr);
130         sprintf(desc, "transmit queue %d", txr);
131         oid = SYSCTL_ADD_NODE(&softc->hw_stats,
132             SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name, CTLFLAG_RD, 0,
133             desc);
134         if (!oid)
135                 return ENOMEM;
136
137
138         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
139             "ucast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_ucast_pkts,
140             "unicast packets sent");
141         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
142             "mcast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_mcast_pkts,
143             "multicast packets sent");
144         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
145             "bcast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_bcast_pkts,
146             "broadcast packets sent");
147         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
148             "discard_pkts", CTLFLAG_RD,
149             &tx_stats[txr].tx_discard_pkts, "discarded transmit packets");
150         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
151             "drop_pkts", CTLFLAG_RD, &tx_stats[txr].tx_drop_pkts,
152             "dropped transmit packets");
153         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
154             "ucast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_ucast_bytes,
155             "unicast bytes sent");
156         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
157             "mcast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_mcast_bytes,
158             "multicast bytes sent");
159         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
160             "bcast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_bcast_bytes,
161             "broadcast bytes sent");
162
163         return 0;
164 }
165
166 int
167 bnxt_create_rx_sysctls(struct bnxt_softc *softc, int rxr)
168 {
169         struct sysctl_oid *oid;
170         struct ctx_hw_stats *rx_stats = (void *)softc->rx_stats.idi_vaddr;
171         char    name[32];
172         char    desc[64];
173
174         sprintf(name, "rxq%d", rxr);
175         sprintf(desc, "receive queue %d", rxr);
176         oid = SYSCTL_ADD_NODE(&softc->hw_stats,
177             SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name, CTLFLAG_RD, 0,
178             desc);
179         if (!oid)
180                 return ENOMEM;
181
182         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
183             "ucast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_ucast_pkts,
184             "unicast packets received");
185         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
186             "mcast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_mcast_pkts,
187             "multicast packets received");
188         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
189             "bcast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_bcast_pkts,
190             "broadcast packets received");
191         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
192             "discard_pkts", CTLFLAG_RD,
193             &rx_stats[rxr].rx_discard_pkts, "discarded receive packets");
194         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
195             "drop_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_drop_pkts,
196             "dropped receive packets");
197         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
198             "ucast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_ucast_bytes,
199             "unicast bytes received");
200         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
201             "mcast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_mcast_bytes,
202             "multicast bytes received");
203         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
204             "bcast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_bcast_bytes,
205             "broadcast bytes received");
206
207         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
208             "tpa_pkts", CTLFLAG_RD, &rx_stats[rxr].tpa_pkts,
209             "TPA packets");
210         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
211             "tpa_bytes", CTLFLAG_RD, &rx_stats[rxr].tpa_bytes,
212             "TPA bytes");
213         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
214             "tpa_events", CTLFLAG_RD, &rx_stats[rxr].tpa_events,
215             "TPA events");
216         SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
217             "tpa_aborts", CTLFLAG_RD, &rx_stats[rxr].tpa_aborts,
218             "TPA aborts");
219
220         return 0;
221 }
222
223 static char *bnxt_chip_type[] = {
224         "ASIC",
225         "FPGA",
226         "Palladium",
227         "Unknown"
228 };
229 #define MAX_CHIP_TYPE 3
230
231 static int
232 bnxt_package_ver_sysctl(SYSCTL_HANDLER_ARGS)
233 {
234         struct bnxt_softc *softc = arg1;
235         struct iflib_dma_info dma_data;
236         char *pkglog = NULL;
237         char *p;
238         char *next;
239         char unk[] = "<unknown>";
240         char *buf = unk;
241         int rc;
242         int field;
243         uint16_t ordinal = BNX_DIR_ORDINAL_FIRST;
244         uint16_t index;
245         uint32_t data_len;
246
247         rc = bnxt_hwrm_nvm_find_dir_entry(softc, BNX_DIR_TYPE_PKG_LOG,
248             &ordinal, BNX_DIR_EXT_NONE, &index, false,
249             HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_EQ,
250             &data_len, NULL, NULL);
251         dma_data.idi_vaddr = NULL;
252         if (rc == 0 && data_len) {
253                 rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data,
254                     BUS_DMA_NOWAIT);
255                 if (rc == 0) {
256                         rc = bnxt_hwrm_nvm_read(softc, index, 0, data_len,
257                             &dma_data);
258                         if (rc == 0) {
259                                 pkglog = dma_data.idi_vaddr;
260                                 /* NULL terminate (removes last \n) */
261                                 pkglog[data_len-1] = 0;
262
263                                 /* Set p = start of last line */
264                                 p = strrchr(pkglog, '\n');
265                                 if (p == NULL)
266                                         p = pkglog;
267
268                                 /* Now find the correct tab delimited field */
269                                 for (field = 0, next = p,
270                                     p = strsep(&next, "\t");
271                                     field <
272                                     BNX_PKG_LOG_FIELD_IDX_PKG_VERSION && p;
273                                     p = strsep(&next, "\t")) {
274                                         field++;
275                                 }
276                                 if (field == BNX_PKG_LOG_FIELD_IDX_PKG_VERSION)
277                                         buf = p;
278                         }
279                 }
280                 else
281                         dma_data.idi_vaddr = NULL;
282         }
283
284         rc = sysctl_handle_string(oidp, buf, 0, req);
285         if (dma_data.idi_vaddr)
286                 iflib_dma_free(&dma_data);
287         return rc;
288 }
289
290 static int
291 bnxt_hwrm_min_ver_sysctl(SYSCTL_HANDLER_ARGS)
292 {
293         struct bnxt_softc *softc = arg1;
294         char buf[16];
295         uint8_t newver[3];
296         int rc;
297
298         sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major,
299             softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update);
300
301         rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
302         if (rc || req->newptr == NULL)
303                 return rc;
304         if (sscanf(buf, "%hhu.%hhu.%hhu%*c", &newver[0], &newver[1],
305             &newver[2]) != 3)
306                 return EINVAL;
307         softc->ver_info->hwrm_min_major = newver[0];
308         softc->ver_info->hwrm_min_minor = newver[1];
309         softc->ver_info->hwrm_min_update = newver[2];
310         bnxt_check_hwrm_version(softc);
311
312         return rc;
313 }
314
315 int
316 bnxt_create_ver_sysctls(struct bnxt_softc *softc)
317 {
318         struct bnxt_ver_info *vi = softc->ver_info;
319         struct sysctl_oid *oid = vi->ver_oid;
320
321         if (!oid)
322                 return ENOMEM;
323
324         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
325             "hwrm_if", CTLFLAG_RD, vi->hwrm_if_ver, 0,
326             "HWRM interface version");
327         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
328             "driver_hwrm_if", CTLFLAG_RD, vi->driver_hwrm_if_ver, 0,
329             "HWRM firmware version");
330         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
331             "hwrm_fw", CTLFLAG_RD, vi->hwrm_fw_ver, 0,
332             "HWRM firmware version");
333         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
334             "mgmt_fw", CTLFLAG_RD, vi->mgmt_fw_ver, 0,
335             "management firmware version");
336         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
337             "netctrl_fw", CTLFLAG_RD, vi->netctrl_fw_ver, 0,
338             "network control firmware version");
339         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
340             "roce_fw", CTLFLAG_RD, vi->roce_fw_ver, 0,
341             "RoCE firmware version");
342         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
343             "phy", CTLFLAG_RD, vi->phy_ver, 0,
344             "PHY version");
345         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
346             "hwrm_fw_name", CTLFLAG_RD, vi->hwrm_fw_name, 0,
347             "HWRM firmware name");
348         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
349             "mgmt_fw_name", CTLFLAG_RD, vi->mgmt_fw_name, 0,
350             "management firmware name");
351         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
352             "netctrl_fw_name", CTLFLAG_RD, vi->netctrl_fw_name, 0,
353             "network control firmware name");
354         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
355             "roce_fw_name", CTLFLAG_RD, vi->roce_fw_name, 0,
356             "RoCE firmware name");
357         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
358             "phy_vendor", CTLFLAG_RD, vi->phy_vendor, 0,
359             "PHY vendor name");
360         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
361             "phy_partnumber", CTLFLAG_RD, vi->phy_partnumber, 0,
362             "PHY vendor part number");
363         SYSCTL_ADD_U16(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
364             "chip_num", CTLFLAG_RD, &vi->chip_num, 0, "chip number");
365         SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
366             "chip_rev", CTLFLAG_RD, &vi->chip_rev, 0, "chip revision");
367         SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
368             "chip_metal", CTLFLAG_RD, &vi->chip_metal, 0, "chip metal number");
369         SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
370             "chip_bond_id", CTLFLAG_RD, &vi->chip_bond_id, 0,
371             "chip bond id");
372         SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
373             "chip_type", CTLFLAG_RD, vi->chip_type > MAX_CHIP_TYPE ?
374             bnxt_chip_type[MAX_CHIP_TYPE] : bnxt_chip_type[vi->chip_type], 0,
375             "RoCE firmware name");
376         SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
377             "package_ver", CTLTYPE_STRING|CTLFLAG_RD, softc, 0,
378             bnxt_package_ver_sysctl, "A",
379             "currently installed package version");
380         SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
381             "hwrm_min_ver", CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0,
382             bnxt_hwrm_min_ver_sysctl, "A",
383             "minimum hwrm API vesion to support");
384
385         return 0;
386 }
387
388 int
389 bnxt_create_nvram_sysctls(struct bnxt_nvram_info *ni)
390 {
391         struct sysctl_oid *oid = ni->nvm_oid;
392
393         if (!oid)
394                 return ENOMEM;
395
396         SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
397             "mfg_id", CTLFLAG_RD, &ni->mfg_id, 0, "manufacturer id");
398         SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
399             "device_id", CTLFLAG_RD, &ni->device_id, 0, "device id");
400         SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
401             "sector_size", CTLFLAG_RD, &ni->sector_size, 0, "sector size");
402         SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
403             "size", CTLFLAG_RD, &ni->size, 0, "nvram total size");
404         SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
405             "reserved_size", CTLFLAG_RD, &ni->reserved_size, 0,
406             "total reserved space");
407         SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
408             "available_size", CTLFLAG_RD, &ni->available_size, 0,
409             "total available space");
410
411         return 0;
412 }
413
414 static int
415 bnxt_rss_key_sysctl(SYSCTL_HANDLER_ARGS)
416 {
417         struct bnxt_softc *softc = arg1;
418         char buf[HW_HASH_KEY_SIZE*2+1] = {0};
419         char *p;
420         int i;
421         int rc;
422
423         for (p = buf, i=0; i<HW_HASH_KEY_SIZE; i++)
424                 p += sprintf(p, "%02x", softc->vnic_info.rss_hash_key[i]);
425
426         rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
427         if (rc || req->newptr == NULL)
428                 return rc;
429
430         if (strspn(buf, "0123456789abcdefABCDEF") != (HW_HASH_KEY_SIZE * 2))
431                 return EINVAL;
432
433         for (p = buf, i=0; i<HW_HASH_KEY_SIZE; i++) {
434                 if (sscanf(p, "%02hhx", &softc->vnic_info.rss_hash_key[i]) != 1)
435                         return EINVAL;
436                 p += 2;
437         }
438
439         if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
440                 bnxt_hwrm_rss_cfg(softc, &softc->vnic_info,
441                     softc->vnic_info.rss_hash_type);
442
443         return rc;
444 }
445
446 static const char *bnxt_hash_types[] = {"ipv4", "tcp_ipv4", "udp_ipv4", "ipv6",
447     "tcp_ipv6", "udp_ipv6", NULL};
448
449 static int bnxt_get_rss_type_str_bit(char *str)
450 {
451         int i;
452
453         for (i=0; bnxt_hash_types[i]; i++)
454                 if (strcmp(bnxt_hash_types[i], str) == 0)
455                         return i;
456
457         return -1;
458 }
459
460 static int
461 bnxt_rss_type_sysctl(SYSCTL_HANDLER_ARGS)
462 {
463         struct bnxt_softc *softc = arg1;
464         char buf[256] = {0};
465         char *p;
466         char *next;
467         int rc;
468         int type;
469         int bit;
470
471         for (type = softc->vnic_info.rss_hash_type; type;
472             type &= ~(1<<bit)) {
473                 bit = ffs(type) - 1;
474                 if (bit >= sizeof(bnxt_hash_types) / sizeof(const char *))
475                         continue;
476                 if (type != softc->vnic_info.rss_hash_type)
477                         strcat(buf, ",");
478                 strcat(buf, bnxt_hash_types[bit]);
479         }
480
481         rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
482         if (rc || req->newptr == NULL)
483                 return rc;
484
485         for (type = 0, next = buf, p = strsep(&next, " ,"); p;
486             p = strsep(&next, " ,")) {
487                 bit = bnxt_get_rss_type_str_bit(p);
488                 if (bit == -1)
489                         return EINVAL;
490                 type |= 1<<bit;
491         }
492         if (type != softc->vnic_info.rss_hash_type) {
493                 softc->vnic_info.rss_hash_type = type;
494                 if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
495                         bnxt_hwrm_rss_cfg(softc, &softc->vnic_info,
496                             softc->vnic_info.rss_hash_type);
497         }
498
499         return rc;
500 }
501
502 static int
503 bnxt_rx_stall_sysctl(SYSCTL_HANDLER_ARGS) {
504         struct bnxt_softc *softc = arg1;
505         int rc;
506         int val;
507
508         if (softc == NULL)
509                 return EBUSY;
510
511         val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_BD_STALL);
512         rc = sysctl_handle_int(oidp, &val, 0, req);
513         if (rc || !req->newptr)
514                 return rc;
515
516         if (val)
517                 softc->vnic_info.flags |= BNXT_VNIC_FLAG_BD_STALL;
518         else
519                 softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_BD_STALL;
520
521         if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
522                 rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info);
523
524         return rc;
525 }
526
527 static int
528 bnxt_vlan_strip_sysctl(SYSCTL_HANDLER_ARGS) {
529         struct bnxt_softc *softc = arg1;
530         int rc;
531         int val;
532
533         if (softc == NULL)
534                 return EBUSY;
535
536         val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_VLAN_STRIP);
537         rc = sysctl_handle_int(oidp, &val, 0, req);
538         if (rc || !req->newptr)
539                 return rc;
540
541         if (val)
542                 softc->vnic_info.flags |= BNXT_VNIC_FLAG_VLAN_STRIP;
543         else
544                 softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_VLAN_STRIP;
545
546         if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
547                 rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info);
548
549         return rc;
550 }
551
552 int
553 bnxt_create_config_sysctls_pre(struct bnxt_softc *softc)
554 {
555         struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev);
556         struct sysctl_oid_list *children;
557
558         children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));;
559
560         SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_key",
561             CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, bnxt_rss_key_sysctl, "A",
562             "RSS key");
563         SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_type",
564             CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, bnxt_rss_type_sysctl, "A",
565             "RSS type bits");
566         SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_stall",
567             CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_rx_stall_sysctl, "I",
568             "buffer rx packets in hardware until the host posts new buffers");
569         SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_strip",
570             CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_vlan_strip_sysctl, "I",
571             "strip VLAN tag in the RX path");
572         SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "if_name", CTLFLAG_RD,
573                 iflib_get_ifp(softc->ctx)->if_xname, 0, "interface name");
574
575         return 0;
576 }
577
578 static int
579 bnxt_vlan_only_sysctl(SYSCTL_HANDLER_ARGS) {
580         struct bnxt_softc *softc = arg1;
581         int rc;
582         int val;
583
584         if (softc == NULL)
585                 return EBUSY;
586
587         val = softc->vnic_info.vlan_only;
588         rc = sysctl_handle_int(oidp, &val, 0, req);
589         if (rc || !req->newptr)
590                 return rc;
591
592         if (val)
593                 val = 1;
594
595         if (val != softc->vnic_info.vlan_only) {
596                 softc->vnic_info.vlan_only = val;
597                 if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
598                         rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc,
599                             &softc->vnic_info);
600         }
601
602         return rc;
603 }
604
605 int
606 bnxt_create_config_sysctls_post(struct bnxt_softc *softc)
607 {
608         struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev);
609         struct sysctl_oid_list *children;
610
611         children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));;
612
613         SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_only",
614             CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_vlan_only_sysctl, "I",
615             "require vlan tag on received packets when vlan is enabled");
616
617         return 0;
618 }