Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c
106845 views
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
#include <sys/endian.h>
31
#include <linux/pci.h>
32
33
#include "bnxt.h"
34
#include "bnxt_hwrm.h"
35
#include "hsi_struct_def.h"
36
37
static int bnxt_hwrm_err_map(uint16_t err);
38
static inline int _is_valid_ether_addr(uint8_t *);
39
static inline void get_random_ether_addr(uint8_t *);
40
static void bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
41
struct hwrm_port_phy_cfg_input *req);
42
static void bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
43
struct hwrm_port_phy_cfg_input *req);
44
static void bnxt_hwrm_set_eee(struct bnxt_softc *softc,
45
struct hwrm_port_phy_cfg_input *req);
46
47
/* NVRam stuff has a five minute timeout */
48
#define BNXT_NVM_TIMEO (5 * 60 * 1000)
49
50
#define BNXT_RX_STATS_PRI_ENTRY(counter, n) \
51
BNXT_RX_STATS_EXT_OFFSET(counter##_cos0)
52
53
#define BNXT_TX_STATS_PRI_ENTRY(counter, n) \
54
BNXT_TX_STATS_EXT_OFFSET(counter##_cos0)
55
56
#define BNXT_RX_STATS_PRI_ENTRIES(counter) \
57
BNXT_RX_STATS_PRI_ENTRY(counter, 0), \
58
BNXT_RX_STATS_PRI_ENTRY(counter, 1), \
59
BNXT_RX_STATS_PRI_ENTRY(counter, 2), \
60
BNXT_RX_STATS_PRI_ENTRY(counter, 3), \
61
BNXT_RX_STATS_PRI_ENTRY(counter, 4), \
62
BNXT_RX_STATS_PRI_ENTRY(counter, 5), \
63
BNXT_RX_STATS_PRI_ENTRY(counter, 6), \
64
BNXT_RX_STATS_PRI_ENTRY(counter, 7)
65
66
#define BNXT_TX_STATS_PRI_ENTRIES(counter) \
67
BNXT_TX_STATS_PRI_ENTRY(counter, 0), \
68
BNXT_TX_STATS_PRI_ENTRY(counter, 1), \
69
BNXT_TX_STATS_PRI_ENTRY(counter, 2), \
70
BNXT_TX_STATS_PRI_ENTRY(counter, 3), \
71
BNXT_TX_STATS_PRI_ENTRY(counter, 4), \
72
BNXT_TX_STATS_PRI_ENTRY(counter, 5), \
73
BNXT_TX_STATS_PRI_ENTRY(counter, 6), \
74
BNXT_TX_STATS_PRI_ENTRY(counter, 7)
75
76
77
long bnxt_rx_bytes_pri_arr_base_off[] = {BNXT_RX_STATS_PRI_ENTRIES(rx_bytes)};
78
long bnxt_rx_pkts_pri_arr_base_off[] = {BNXT_RX_STATS_PRI_ENTRIES(rx_packets)};
79
long bnxt_tx_bytes_pri_arr_base_off[] = {BNXT_TX_STATS_PRI_ENTRIES(tx_bytes)};
80
long bnxt_tx_pkts_pri_arr_base_off[] = {BNXT_TX_STATS_PRI_ENTRIES(tx_packets)};
81
82
static int
83
bnxt_hwrm_err_map(uint16_t err)
84
{
85
int rc;
86
87
switch (err) {
88
case HWRM_ERR_CODE_SUCCESS:
89
return 0;
90
case HWRM_ERR_CODE_INVALID_PARAMS:
91
case HWRM_ERR_CODE_INVALID_FLAGS:
92
case HWRM_ERR_CODE_INVALID_ENABLES:
93
return EINVAL;
94
case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
95
return EACCES;
96
case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
97
return ENOMEM;
98
case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
99
return ENOSYS;
100
case HWRM_ERR_CODE_FAIL:
101
return EIO;
102
case HWRM_ERR_CODE_HWRM_ERROR:
103
case HWRM_ERR_CODE_UNKNOWN_ERR:
104
default:
105
return EDOOFUS;
106
}
107
108
return rc;
109
}
110
111
int
112
bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
113
{
114
int rc;
115
116
rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
117
BUS_DMA_NOWAIT);
118
return rc;
119
}
120
121
void
122
bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
123
{
124
if (softc->hwrm_cmd_resp.idi_vaddr)
125
iflib_dma_free(&softc->hwrm_cmd_resp);
126
softc->hwrm_cmd_resp.idi_vaddr = NULL;
127
return;
128
}
129
130
void
131
bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
132
uint16_t req_type)
133
{
134
struct input *req = request;
135
136
req->req_type = htole16(req_type);
137
req->cmpl_ring = 0xffff;
138
req->target_id = 0xffff;
139
req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
140
}
141
142
int
143
_hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
144
{
145
struct input *req = msg;
146
struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
147
uint32_t *data = msg;
148
int i;
149
uint8_t *valid;
150
uint16_t err;
151
uint16_t max_req_len = BNXT_HWRM_MAX_REQ_LEN;
152
struct hwrm_short_input short_input = {0};
153
154
/* TODO: DMASYNC in here. */
155
req->seq_id = htole16(softc->hwrm_cmd_seq++);
156
memset(resp, 0, PAGE_SIZE);
157
158
if (BNXT_NO_FW_ACCESS(softc) &&
159
(req->req_type != HWRM_FUNC_RESET && req->req_type != HWRM_VER_GET))
160
return -EINVAL;
161
162
if ((softc->flags & BNXT_FLAG_SHORT_CMD) ||
163
msg_len > BNXT_HWRM_MAX_REQ_LEN) {
164
void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
165
uint16_t max_msg_len;
166
167
/* Set boundary for maximum extended request length for short
168
* cmd format. If passed up from device use the max supported
169
* internal req length.
170
*/
171
172
max_msg_len = softc->hwrm_max_ext_req_len;
173
174
175
memcpy(short_cmd_req, req, msg_len);
176
if (msg_len < max_msg_len)
177
memset((uint8_t *) short_cmd_req + msg_len, 0,
178
max_msg_len - msg_len);
179
180
short_input.req_type = req->req_type;
181
short_input.signature =
182
htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
183
short_input.size = htole16(msg_len);
184
short_input.req_addr =
185
htole64(softc->hwrm_short_cmd_req_addr.idi_paddr);
186
187
data = (uint32_t *)&short_input;
188
msg_len = sizeof(short_input);
189
190
/* Sync memory write before updating doorbell */
191
wmb();
192
193
max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
194
}
195
196
/* Write request msg to hwrm channel */
197
for (i = 0; i < msg_len; i += 4) {
198
bus_space_write_4(softc->hwrm_bar.tag,
199
softc->hwrm_bar.handle,
200
i, *data);
201
data++;
202
}
203
204
/* Clear to the end of the request buffer */
205
for (i = msg_len; i < max_req_len; i += 4)
206
bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
207
i, 0);
208
209
/* Ring channel doorbell */
210
bus_space_write_4(softc->hwrm_bar.tag,
211
softc->hwrm_bar.handle,
212
0x100, htole32(1));
213
214
/* Check if response len is updated */
215
for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
216
if (resp->resp_len && resp->resp_len <= 4096)
217
break;
218
DELAY(1000);
219
}
220
if (i >= softc->hwrm_cmd_timeo) {
221
device_printf(softc->dev,
222
"Timeout sending %s: (timeout: %u) seq: %d\n",
223
GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
224
le16toh(req->seq_id));
225
return ETIMEDOUT;
226
}
227
/* Last byte of resp contains the valid key */
228
valid = (uint8_t *)resp + resp->resp_len - 1;
229
for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
230
if (*valid == HWRM_RESP_VALID_KEY)
231
break;
232
DELAY(1000);
233
}
234
if (i >= softc->hwrm_cmd_timeo) {
235
device_printf(softc->dev, "Timeout sending %s: "
236
"(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
237
GET_HWRM_REQ_TYPE(req->req_type),
238
softc->hwrm_cmd_timeo, le16toh(req->req_type),
239
le16toh(req->seq_id), msg_len,
240
*valid);
241
return ETIMEDOUT;
242
}
243
244
err = le16toh(resp->error_code);
245
if (err) {
246
/* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
247
if (err != HWRM_ERR_CODE_FAIL) {
248
device_printf(softc->dev,
249
"%s command returned %s error.\n",
250
GET_HWRM_REQ_TYPE(req->req_type),
251
GET_HWRM_ERROR_CODE(err));
252
}
253
return bnxt_hwrm_err_map(err);
254
}
255
256
return 0;
257
}
258
259
int
260
hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
261
{
262
int rc;
263
264
BNXT_HWRM_LOCK(softc);
265
rc = _hwrm_send_message(softc, msg, msg_len);
266
BNXT_HWRM_UNLOCK(softc);
267
return rc;
268
}
269
270
int
271
bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc, uint32_t path_dir)
272
{
273
int rc = 0;
274
struct hwrm_queue_qportcfg_input req = {0};
275
struct hwrm_queue_qportcfg_output *resp =
276
(void *)softc->hwrm_cmd_resp.idi_vaddr;
277
uint8_t max_tc, max_lltc, *max_q;
278
uint8_t queue_profile, queue_id;
279
struct bnxt_queue_info *q_info;
280
uint8_t i, j, *qptr, *q_ids;
281
bool no_rdma;
282
283
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
284
285
BNXT_HWRM_LOCK(softc);
286
rc = _hwrm_send_message(softc, &req, sizeof(req));
287
if (rc)
288
goto qportcfg_exit;
289
290
if (!resp->max_configurable_queues) {
291
rc = -EINVAL;
292
goto qportcfg_exit;
293
}
294
295
if (resp->queue_cfg_info & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_CFG_INFO_ASYM_CFG) {
296
softc->is_asym_q = true;
297
/* bnxt_init_cosq_names(softc, path_dir); */
298
} else {
299
softc->is_asym_q = false;
300
/* bnxt_free_stats_cosqnames_mem(softc); */
301
}
302
303
max_tc = min_t(uint8_t, resp->max_configurable_queues, BNXT_MAX_QUEUE);
304
max_lltc = resp->max_configurable_lossless_queues;
305
306
/*
307
* No RDMA support yet.
308
* no_rdma = !(softc->flags & BNXT_FLAG_ROCE_CAP);
309
*/
310
no_rdma = true;
311
qptr = &resp->queue_id0;
312
313
if (path_dir == HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX) {
314
q_info = softc->tx_q_info;
315
q_ids = softc->tx_q_ids;
316
max_q = &softc->tx_max_q;
317
} else {
318
q_info = softc->rx_q_info;
319
q_ids = softc->rx_q_ids;
320
max_q = &softc->rx_max_q;
321
}
322
323
for (i = 0, j = 0; i < max_tc; i++) {
324
queue_id = *qptr;
325
qptr++;
326
327
queue_profile = *qptr;
328
qptr++;
329
330
q_info[j].queue_id = queue_id;
331
q_info[j].queue_profile = queue_profile;
332
q_ids[i] = queue_id;
333
334
softc->tc_to_qidx[j] = j;
335
336
if (!BNXT_CNPQ(q_info[j].queue_profile) ||
337
(no_rdma && BNXT_PF(softc)))
338
j++;
339
}
340
*max_q = max_tc;
341
max_tc = max_t(uint8_t, j, 1);
342
softc->max_tc = softc->max_tc ? min(softc->max_tc, max_tc) : max_tc;
343
softc->max_lltc = softc->max_lltc ? min(softc->max_lltc, max_lltc) : max_lltc;
344
345
if (softc->max_lltc > softc->max_tc)
346
softc->max_lltc = softc->max_tc;
347
348
qportcfg_exit:
349
BNXT_HWRM_UNLOCK(softc);
350
return rc;
351
}
352
353
static int bnxt_alloc_all_ctx_pg_info(struct bnxt_softc *softc, int ctx_max)
354
{
355
struct bnxt_ctx_mem_info *ctx = softc->ctx_mem;
356
u16 type;
357
358
for (type = 0; type < ctx_max; type++) {
359
struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
360
int n = 1;
361
362
if (!ctxm->max_entries || ctxm->pg_info)
363
continue;
364
365
if (ctxm->instance_bmap)
366
n = hweight32(ctxm->instance_bmap);
367
ctxm->pg_info = kcalloc(n, sizeof(*ctxm->pg_info), GFP_ATOMIC);
368
if (!ctxm->pg_info)
369
return -ENOMEM;
370
}
371
return 0;
372
}
373
374
static void bnxt_init_ctx_initializer(struct bnxt_ctx_mem_type *ctxm,
375
u8 init_val, u8 init_offset,
376
bool init_mask_set)
377
{
378
ctxm->init_value = init_val;
379
ctxm->init_offset = BNXT_CTX_INIT_INVALID_OFFSET;
380
if (init_mask_set)
381
ctxm->init_offset = init_offset * 4;
382
else
383
ctxm->init_value = 0;
384
}
385
386
#define BNXT_CTX_INIT_VALID(flags) \
387
(!!((flags) & \
388
HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_ENABLE_CTX_KIND_INIT))
389
390
static int
391
bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt_softc *softc)
392
{
393
struct hwrm_func_backing_store_qcaps_v2_input req = {0};
394
struct hwrm_func_backing_store_qcaps_v2_output *resp =
395
(void *)softc->hwrm_cmd_resp.idi_vaddr;
396
struct bnxt_ctx_mem_info *ctx = NULL;
397
u16 type;
398
int rc;
399
400
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_QCAPS_V2);
401
402
ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
403
if (!ctx)
404
return -ENOMEM;
405
406
softc->ctx_mem = ctx;
407
408
BNXT_HWRM_LOCK(softc);
409
for (type = 0; type < BNXT_CTX_V2_MAX; ) {
410
struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
411
u8 init_val, init_off, i;
412
__le32 *p;
413
u32 flags;
414
415
req.type = cpu_to_le16(type);
416
rc = _hwrm_send_message(softc, &req, sizeof(req));
417
if (rc)
418
goto ctx_done;
419
flags = le32_to_cpu(resp->flags);
420
type = le16_to_cpu(resp->next_valid_type);
421
if (!(flags & HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_TYPE_VALID))
422
continue;
423
424
ctxm->type = le16_to_cpu(resp->type);
425
ctxm->flags = flags;
426
427
ctxm->entry_size = le16_to_cpu(resp->entry_size);
428
ctxm->instance_bmap = le32_to_cpu(resp->instance_bit_map);
429
ctxm->entry_multiple = resp->entry_multiple;
430
ctxm->max_entries = le32_to_cpu(resp->max_num_entries);
431
ctxm->min_entries = le32_to_cpu(resp->min_num_entries);
432
init_val = resp->ctx_init_value;
433
init_off = resp->ctx_init_offset;
434
bnxt_init_ctx_initializer(ctxm, init_val, init_off,
435
BNXT_CTX_INIT_VALID(flags));
436
ctxm->split_entry_cnt = min_t(u8, resp->subtype_valid_cnt,
437
BNXT_MAX_SPLIT_ENTRY);
438
for (i = 0, p = &resp->split_entry_0; i < ctxm->split_entry_cnt;
439
i++, p++)
440
ctxm->split[i] = le32_to_cpu(*p);
441
}
442
rc = bnxt_alloc_all_ctx_pg_info(softc, BNXT_CTX_V2_MAX);
443
444
ctx_done:
445
BNXT_HWRM_UNLOCK(softc);
446
return rc;
447
}
448
449
int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc)
450
{
451
struct hwrm_func_backing_store_qcaps_input req = {0};
452
struct hwrm_func_backing_store_qcaps_output *resp =
453
(void *)softc->hwrm_cmd_resp.idi_vaddr;
454
int rc;
455
456
if (softc->hwrm_spec_code < 0x10902 || softc->ctx_mem)
457
return 0;
458
459
if (BNXT_CHIP_P7(softc)) {
460
if (softc->fw_cap & BNXT_FW_CAP_BACKING_STORE_V2)
461
return bnxt_hwrm_func_backing_store_qcaps_v2(softc);
462
}
463
464
if (BNXT_VF(softc))
465
return 0;
466
467
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_QCAPS);
468
BNXT_HWRM_LOCK(softc);
469
rc = _hwrm_send_message(softc, &req, sizeof(req));
470
if (!rc) {
471
struct bnxt_ctx_mem_type *ctxm;
472
struct bnxt_ctx_mem_info *ctx;
473
u8 init_val, init_idx = 0;
474
u16 init_mask;
475
476
ctx = softc->ctx_mem;
477
if (!ctx) {
478
ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
479
if (!ctx) {
480
rc = -ENOMEM;
481
goto ctx_err;
482
}
483
softc->ctx_mem = ctx;
484
}
485
init_val = resp->ctx_kind_initializer;
486
init_mask = le16_to_cpu(resp->ctx_init_mask);
487
488
ctxm = &ctx->ctx_arr[BNXT_CTX_QP];
489
ctxm->max_entries = le32_to_cpu(resp->qp_max_entries);
490
ctxm->qp_qp1_entries = le16_to_cpu(resp->qp_min_qp1_entries);
491
ctxm->qp_l2_entries = le16_to_cpu(resp->qp_max_l2_entries);
492
ctxm->entry_size = le16_to_cpu(resp->qp_entry_size);
493
bnxt_init_ctx_initializer(ctxm, init_val, resp->qp_init_offset,
494
(init_mask & (1 << init_idx++)) != 0);
495
496
ctxm = &ctx->ctx_arr[BNXT_CTX_SRQ];
497
ctxm->srq_l2_entries = le16_to_cpu(resp->srq_max_l2_entries);
498
ctxm->max_entries = le32_to_cpu(resp->srq_max_entries);
499
ctxm->entry_size = le16_to_cpu(resp->srq_entry_size);
500
bnxt_init_ctx_initializer(ctxm, init_val, resp->srq_init_offset,
501
(init_mask & (1 << init_idx++)) != 0);
502
503
ctxm = &ctx->ctx_arr[BNXT_CTX_CQ];
504
ctxm->cq_l2_entries = le16_to_cpu(resp->cq_max_l2_entries);
505
ctxm->max_entries = le32_to_cpu(resp->cq_max_entries);
506
ctxm->entry_size = le16_to_cpu(resp->cq_entry_size);
507
bnxt_init_ctx_initializer(ctxm, init_val, resp->cq_init_offset,
508
(init_mask & (1 << init_idx++)) != 0);
509
510
ctxm = &ctx->ctx_arr[BNXT_CTX_VNIC];
511
ctxm->vnic_entries = le32_to_cpu(resp->vnic_max_vnic_entries);
512
ctxm->max_entries = ctxm->vnic_entries +
513
le16_to_cpu(resp->vnic_max_ring_table_entries);
514
ctxm->entry_size = le16_to_cpu(resp->vnic_entry_size);
515
bnxt_init_ctx_initializer(ctxm, init_val,
516
resp->vnic_init_offset,
517
(init_mask & (1 << init_idx++)) != 0);
518
519
ctxm = &ctx->ctx_arr[BNXT_CTX_STAT];
520
ctxm->max_entries = le32_to_cpu(resp->stat_max_entries);
521
ctxm->entry_size = le16_to_cpu(resp->stat_entry_size);
522
bnxt_init_ctx_initializer(ctxm, init_val,
523
resp->stat_init_offset,
524
(init_mask & (1 << init_idx++)) != 0);
525
526
ctxm = &ctx->ctx_arr[BNXT_CTX_STQM];
527
ctxm->entry_size = le16_to_cpu(resp->tqm_entry_size);
528
ctxm->min_entries = le32_to_cpu(resp->tqm_min_entries_per_ring);
529
ctxm->max_entries = le32_to_cpu(resp->tqm_max_entries_per_ring);
530
ctxm->entry_multiple = resp->tqm_entries_multiple;
531
if (!ctxm->entry_multiple)
532
ctxm->entry_multiple = 1;
533
534
memcpy(&ctx->ctx_arr[BNXT_CTX_FTQM], ctxm, sizeof(*ctxm));
535
536
ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV];
537
ctxm->max_entries = le32_to_cpu(resp->mrav_max_entries);
538
ctxm->entry_size = le16_to_cpu(resp->mrav_entry_size);
539
ctxm->mrav_num_entries_units =
540
le16_to_cpu(resp->mrav_num_entries_units);
541
bnxt_init_ctx_initializer(ctxm, init_val,
542
resp->mrav_init_offset,
543
(init_mask & (1 << init_idx++)) != 0);
544
545
ctxm = &ctx->ctx_arr[BNXT_CTX_TIM];
546
ctxm->entry_size = le16_to_cpu(resp->tim_entry_size);
547
ctxm->max_entries = le32_to_cpu(resp->tim_max_entries);
548
549
ctx->tqm_fp_rings_count = resp->tqm_fp_rings_count;
550
if (!ctx->tqm_fp_rings_count)
551
ctx->tqm_fp_rings_count = softc->tx_max_q;
552
else if (ctx->tqm_fp_rings_count > BNXT_MAX_TQM_FP_LEGACY_RINGS)
553
ctx->tqm_fp_rings_count = BNXT_MAX_TQM_FP_LEGACY_RINGS;
554
if (ctx->tqm_fp_rings_count == BNXT_MAX_TQM_FP_LEGACY_RINGS &&
555
softc->hwrm_max_ext_req_len >= BNXT_BACKING_STORE_CFG_LEN) {
556
ctx->tqm_fp_rings_count += resp->tqm_fp_rings_count_ext;
557
if (ctx->tqm_fp_rings_count > BNXT_MAX_TQM_FP_RINGS)
558
ctx->tqm_fp_rings_count = BNXT_MAX_TQM_FP_RINGS;
559
}
560
ctxm = &ctx->ctx_arr[BNXT_CTX_FTQM];
561
memcpy(ctxm, &ctx->ctx_arr[BNXT_CTX_STQM], sizeof(*ctxm));
562
ctxm->instance_bmap = (1 << ctx->tqm_fp_rings_count) - 1;
563
564
rc = bnxt_alloc_all_ctx_pg_info(softc, BNXT_CTX_MAX);
565
} else {
566
rc = 0;
567
}
568
ctx_err:
569
BNXT_HWRM_UNLOCK(softc);
570
return rc;
571
}
572
573
#define HWRM_FUNC_BACKING_STORE_CFG_INPUT_DFLT_ENABLES \
574
(HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP | \
575
HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ | \
576
HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ | \
577
HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC | \
578
HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT)
579
580
static void bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info *rmem, uint8_t *pg_attr,
581
uint64_t *pg_dir)
582
{
583
if (!rmem->nr_pages)
584
return;
585
586
BNXT_SET_CTX_PAGE_ATTR(*pg_attr);
587
588
if (rmem->depth >= 1) {
589
if (rmem->depth == 2)
590
*pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2;
591
else
592
*pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_1;
593
*pg_dir = htole64(rmem->pg_tbl.idi_paddr);
594
} else {
595
*pg_dir = htole64(rmem->pg_arr[0].idi_paddr);
596
}
597
}
598
599
int bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc *softc, uint32_t enables)
600
{
601
struct hwrm_func_backing_store_cfg_input req = {0};
602
struct bnxt_ctx_mem_info *ctx = softc->ctx_mem;
603
struct bnxt_ctx_pg_info *ctx_pg;
604
struct bnxt_ctx_mem_type *ctxm;
605
u32 req_len = sizeof(req);
606
__le32 *num_entries;
607
u32 ena, flags = 0;
608
__le64 *pg_dir;
609
u8 *pg_attr;
610
int i;
611
612
if (!ctx)
613
return 0;
614
615
if (req_len > softc->hwrm_max_ext_req_len)
616
req_len = BNXT_BACKING_STORE_CFG_LEGACY_LEN;
617
618
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG);
619
req.enables = htole32(enables);
620
621
if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP) {
622
ctxm = &ctx->ctx_arr[BNXT_CTX_QP];
623
ctx_pg = ctxm->pg_info;
624
req.qp_num_entries = cpu_to_le32(ctx_pg->entries);
625
req.qp_num_qp1_entries = cpu_to_le16(ctxm->qp_qp1_entries);
626
req.qp_num_l2_entries = cpu_to_le16(ctxm->qp_l2_entries);
627
req.qp_entry_size = cpu_to_le16(ctxm->entry_size);
628
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
629
&req.qpc_pg_size_qpc_lvl,
630
&req.qpc_page_dir);
631
}
632
if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ) {
633
ctxm = &ctx->ctx_arr[BNXT_CTX_SRQ];
634
ctx_pg = ctxm->pg_info;
635
req.srq_num_entries = cpu_to_le32(ctx_pg->entries);
636
req.srq_num_l2_entries = cpu_to_le16(ctxm->srq_l2_entries);
637
req.srq_entry_size = cpu_to_le16(ctxm->entry_size);
638
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
639
&req.srq_pg_size_srq_lvl,
640
&req.srq_page_dir);
641
}
642
if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ) {
643
ctxm = &ctx->ctx_arr[BNXT_CTX_CQ];
644
ctx_pg = ctxm->pg_info;
645
req.cq_num_entries = cpu_to_le32(ctx_pg->entries);
646
req.cq_num_l2_entries = cpu_to_le16(ctxm->cq_l2_entries);
647
req.cq_entry_size = cpu_to_le16(ctxm->entry_size);
648
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
649
&req.cq_pg_size_cq_lvl,
650
&req.cq_page_dir);
651
}
652
if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV) {
653
ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV];
654
ctx_pg = ctxm->pg_info;
655
req.mrav_num_entries = cpu_to_le32(ctx_pg->entries);
656
if (ctxm->mrav_num_entries_units)
657
flags |=
658
HWRM_FUNC_BACKING_STORE_CFG_INPUT_FLAGS_MRAV_RESERVATION_SPLIT;
659
req.mrav_entry_size = cpu_to_le16(ctxm->entry_size);
660
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
661
&req.mrav_pg_size_mrav_lvl,
662
&req.mrav_page_dir);
663
}
664
if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TIM) {
665
ctxm = &ctx->ctx_arr[BNXT_CTX_TIM];
666
ctx_pg = ctxm->pg_info;
667
req.tim_num_entries = cpu_to_le32(ctx_pg->entries);
668
req.tim_entry_size = cpu_to_le16(ctxm->entry_size);
669
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
670
&req.tim_pg_size_tim_lvl,
671
&req.tim_page_dir);
672
}
673
if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC) {
674
ctxm = &ctx->ctx_arr[BNXT_CTX_VNIC];
675
ctx_pg = ctxm->pg_info;
676
req.vnic_num_vnic_entries = cpu_to_le16(ctxm->vnic_entries);
677
req.vnic_num_ring_table_entries =
678
cpu_to_le16(ctxm->max_entries - ctxm->vnic_entries);
679
req.vnic_entry_size = cpu_to_le16(ctxm->entry_size);
680
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
681
&req.vnic_pg_size_vnic_lvl,
682
&req.vnic_page_dir);
683
}
684
if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT) {
685
ctxm = &ctx->ctx_arr[BNXT_CTX_STAT];
686
ctx_pg = ctxm->pg_info;
687
req.stat_num_entries = cpu_to_le32(ctxm->max_entries);
688
req.stat_entry_size = cpu_to_le16(ctxm->entry_size);
689
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
690
&req.stat_pg_size_stat_lvl,
691
&req.stat_page_dir);
692
}
693
ctxm = &ctx->ctx_arr[BNXT_CTX_STQM];
694
for (i = 0, num_entries = &req.tqm_sp_num_entries,
695
pg_attr = &req.tqm_sp_pg_size_tqm_sp_lvl,
696
pg_dir = &req.tqm_sp_page_dir,
697
ena = HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP,
698
ctx_pg = ctxm->pg_info;
699
i < BNXT_MAX_TQM_LEGACY_RINGS;
700
ctx_pg = &ctx->ctx_arr[BNXT_CTX_FTQM].pg_info[i],
701
i++, num_entries++, pg_attr++, pg_dir++, ena <<= 1) {
702
if (!(enables & ena))
703
continue;
704
705
req.tqm_entry_size = cpu_to_le16(ctxm->entry_size);
706
*num_entries = cpu_to_le32(ctx_pg->entries);
707
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir);
708
}
709
if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_RING8) {
710
pg_attr = &req.tqm_ring8_pg_size_tqm_ring_lvl;
711
pg_dir = &req.tqm_ring8_page_dir;
712
ctx_pg = &ctx->ctx_arr[BNXT_CTX_FTQM].pg_info[8];
713
req.tqm_ring8_num_entries = cpu_to_le32(ctx_pg->entries);
714
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir);
715
}
716
req.flags = cpu_to_le32(flags);
717
return hwrm_send_message(softc, &req, req_len);
718
}
719
720
int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all)
721
{
722
struct hwrm_func_resource_qcaps_output *resp =
723
(void *)softc->hwrm_cmd_resp.idi_vaddr;
724
struct hwrm_func_resource_qcaps_input req = {0};
725
struct bnxt_hw_resc *hw_resc = &softc->hw_resc;
726
int rc;
727
728
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESOURCE_QCAPS);
729
req.fid = htole16(0xffff);
730
731
BNXT_HWRM_LOCK(softc);
732
rc = _hwrm_send_message(softc, &req, sizeof(req));
733
if (rc) {
734
rc = -EIO;
735
goto hwrm_func_resc_qcaps_exit;
736
}
737
738
hw_resc->max_tx_sch_inputs = le16toh(resp->max_tx_scheduler_inputs);
739
if (!all)
740
goto hwrm_func_resc_qcaps_exit;
741
742
hw_resc->min_rsscos_ctxs = le16toh(resp->min_rsscos_ctx);
743
hw_resc->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
744
hw_resc->min_cp_rings = le16toh(resp->min_cmpl_rings);
745
hw_resc->max_cp_rings = le16toh(resp->max_cmpl_rings);
746
hw_resc->min_tx_rings = le16toh(resp->min_tx_rings);
747
hw_resc->max_tx_rings = le16toh(resp->max_tx_rings);
748
hw_resc->min_rx_rings = le16toh(resp->min_rx_rings);
749
hw_resc->max_rx_rings = le16toh(resp->max_rx_rings);
750
hw_resc->min_hw_ring_grps = le16toh(resp->min_hw_ring_grps);
751
hw_resc->max_hw_ring_grps = le16toh(resp->max_hw_ring_grps);
752
hw_resc->min_l2_ctxs = le16toh(resp->min_l2_ctxs);
753
hw_resc->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
754
hw_resc->min_vnics = le16toh(resp->min_vnics);
755
hw_resc->max_vnics = le16toh(resp->max_vnics);
756
hw_resc->min_stat_ctxs = le16toh(resp->min_stat_ctx);
757
hw_resc->max_stat_ctxs = le16toh(resp->max_stat_ctx);
758
759
if (BNXT_CHIP_P5_PLUS(softc)) {
760
hw_resc->max_nqs = le16toh(resp->max_msix);
761
hw_resc->max_hw_ring_grps = hw_resc->max_rx_rings;
762
}
763
764
hwrm_func_resc_qcaps_exit:
765
BNXT_HWRM_UNLOCK(softc);
766
return rc;
767
}
768
769
int bnxt_hwrm_func_backing_store_cfg_v2(struct bnxt_softc *softc,
770
struct bnxt_ctx_mem_type *ctxm,
771
bool last)
772
{
773
struct hwrm_func_backing_store_cfg_v2_input req = {0};
774
u32 instance_bmap = ctxm->instance_bmap;
775
int i, j, rc = 0, n = 1;
776
__le32 *p;
777
778
if (!(ctxm->flags & BNXT_CTX_MEM_TYPE_VALID) || !ctxm->pg_info)
779
return 0;
780
781
if (instance_bmap)
782
n = hweight32(ctxm->instance_bmap);
783
else
784
instance_bmap = 1;
785
786
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG_V2);
787
788
BNXT_HWRM_LOCK(softc);
789
req.type = cpu_to_le16(ctxm->type);
790
req.entry_size = cpu_to_le16(ctxm->entry_size);
791
req.subtype_valid_cnt = ctxm->split_entry_cnt;
792
for (i = 0, p = &req.split_entry_0; i < ctxm->split_entry_cnt; i++)
793
p[i] = cpu_to_le32(ctxm->split[i]);
794
for (i = 0, j = 0; j < n && !rc; i++) {
795
struct bnxt_ctx_pg_info *ctx_pg;
796
797
if (!(instance_bmap & (1 << i)))
798
continue;
799
req.instance = cpu_to_le16(i);
800
ctx_pg = &ctxm->pg_info[j++];
801
if (!ctx_pg->entries)
802
continue;
803
req.num_entries = cpu_to_le32(ctx_pg->entries);
804
bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
805
&req.page_size_pbl_level,
806
&req.page_dir);
807
if (last && j == n)
808
req.flags =
809
cpu_to_le32(HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_FLAGS_BS_CFG_ALL_DONE);
810
rc = _hwrm_send_message(softc, &req, sizeof(req));
811
}
812
BNXT_HWRM_UNLOCK(softc);
813
return rc;
814
}
815
816
int
817
bnxt_hwrm_passthrough(struct bnxt_softc *softc, void *req, uint32_t req_len,
818
void *resp, uint32_t resp_len, uint32_t app_timeout)
819
{
820
int rc = 0;
821
void *output = (void *)softc->hwrm_cmd_resp.idi_vaddr;
822
struct input *input = req;
823
uint32_t old_timeo;
824
825
input->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
826
BNXT_HWRM_LOCK(softc);
827
old_timeo = softc->hwrm_cmd_timeo;
828
if (input->req_type == HWRM_NVM_INSTALL_UPDATE)
829
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
830
else
831
softc->hwrm_cmd_timeo = max(app_timeout, softc->hwrm_cmd_timeo);
832
rc = _hwrm_send_message(softc, req, req_len);
833
softc->hwrm_cmd_timeo = old_timeo;
834
if (rc) {
835
device_printf(softc->dev, "%s: %s command failed with rc: 0x%x\n",
836
__FUNCTION__, GET_HWRM_REQ_TYPE(input->req_type), rc);
837
goto fail;
838
}
839
840
memcpy(resp, output, resp_len);
841
fail:
842
BNXT_HWRM_UNLOCK(softc);
843
return rc;
844
}
845
846
847
int
848
bnxt_hwrm_ver_get(struct bnxt_softc *softc)
849
{
850
struct hwrm_ver_get_input req = {0};
851
struct hwrm_ver_get_output *resp =
852
(void *)softc->hwrm_cmd_resp.idi_vaddr;
853
int rc;
854
const char nastr[] = "<not installed>";
855
const char naver[] = "<N/A>";
856
uint32_t dev_caps_cfg;
857
uint16_t fw_maj, fw_min, fw_bld, fw_rsv, len;
858
859
softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
860
softc->hwrm_cmd_timeo = 1000;
861
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
862
863
req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
864
req.hwrm_intf_min = HWRM_VERSION_MINOR;
865
req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
866
867
BNXT_HWRM_LOCK(softc);
868
rc = _hwrm_send_message(softc, &req, sizeof(req));
869
if (rc)
870
goto fail;
871
872
snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
873
resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
874
softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj_8b;
875
softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min_8b;
876
softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd_8b;
877
strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
878
BNXT_VERSTR_SIZE);
879
strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
880
BNXT_NAME_SIZE);
881
882
softc->hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
883
resp->hwrm_intf_min_8b << 8 |
884
resp->hwrm_intf_upd_8b;
885
if (resp->hwrm_intf_maj_8b < 1) {
886
device_printf(softc->dev, "HWRM interface %d.%d.%d is older "
887
"than 1.0.0.\n", resp->hwrm_intf_maj_8b,
888
resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
889
device_printf(softc->dev, "Please update firmware with HWRM "
890
"interface 1.0.0 or newer.\n");
891
}
892
if (resp->mgmt_fw_major == 0 && resp->mgmt_fw_minor == 0 &&
893
resp->mgmt_fw_build == 0) {
894
strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
895
strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
896
}
897
else {
898
snprintf(softc->ver_info->mgmt_fw_ver, FW_VER_STR_LEN,
899
"%d.%d.%d.%d", resp->mgmt_fw_major, resp->mgmt_fw_minor,
900
resp->mgmt_fw_build, resp->mgmt_fw_patch);
901
strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
902
BNXT_NAME_SIZE);
903
}
904
if (resp->netctrl_fw_major == 0 && resp->netctrl_fw_minor == 0 &&
905
resp->netctrl_fw_build == 0) {
906
strlcpy(softc->ver_info->netctrl_fw_ver, naver,
907
BNXT_VERSTR_SIZE);
908
strlcpy(softc->ver_info->netctrl_fw_name, nastr,
909
BNXT_NAME_SIZE);
910
}
911
else {
912
snprintf(softc->ver_info->netctrl_fw_ver, FW_VER_STR_LEN,
913
"%d.%d.%d.%d", resp->netctrl_fw_major, resp->netctrl_fw_minor,
914
resp->netctrl_fw_build, resp->netctrl_fw_patch);
915
strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
916
BNXT_NAME_SIZE);
917
}
918
if (resp->roce_fw_major == 0 && resp->roce_fw_minor == 0 &&
919
resp->roce_fw_build == 0) {
920
strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
921
strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
922
}
923
else {
924
snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
925
"%d.%d.%d.%d", resp->roce_fw_major, resp->roce_fw_minor,
926
resp->roce_fw_build, resp->roce_fw_patch);
927
strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
928
BNXT_NAME_SIZE);
929
}
930
931
fw_maj = le32toh(resp->hwrm_fw_major);
932
if (softc->hwrm_spec_code > 0x10803 && fw_maj) {
933
fw_min = le16toh(resp->hwrm_fw_minor);
934
fw_bld = le16toh(resp->hwrm_fw_build);
935
fw_rsv = le16toh(resp->hwrm_fw_patch);
936
len = FW_VER_STR_LEN;
937
} else {
938
fw_maj = resp->hwrm_fw_maj_8b;
939
fw_min = resp->hwrm_fw_min_8b;
940
fw_bld = resp->hwrm_fw_bld_8b;
941
fw_rsv = resp->hwrm_fw_rsvd_8b;
942
len = BC_HWRM_STR_LEN;
943
}
944
945
softc->ver_info->fw_ver_code = BNXT_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv);
946
snprintf (softc->ver_info->fw_ver_str, len, "%d.%d.%d.%d",
947
fw_maj, fw_min, fw_bld, fw_rsv);
948
949
if (strlen(resp->active_pkg_name)) {
950
int fw_ver_len = strlen (softc->ver_info->fw_ver_str);
951
952
snprintf(softc->ver_info->fw_ver_str + fw_ver_len,
953
FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
954
resp->active_pkg_name);
955
softc->fw_cap |= BNXT_FW_CAP_PKG_VER;
956
}
957
958
softc->ver_info->chip_num = le16toh(resp->chip_num);
959
softc->ver_info->chip_rev = resp->chip_rev;
960
softc->ver_info->chip_metal = resp->chip_metal;
961
softc->ver_info->chip_bond_id = resp->chip_bond_id;
962
softc->ver_info->chip_type = resp->chip_platform_type;
963
964
if (resp->hwrm_intf_maj_8b >= 1) {
965
softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
966
softc->hwrm_max_ext_req_len = le16toh(resp->max_ext_req_len);
967
}
968
softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
969
if (!softc->hwrm_cmd_timeo)
970
softc->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT;
971
972
dev_caps_cfg = le32toh(resp->dev_caps_cfg);
973
if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
974
(dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
975
softc->flags |= BNXT_FLAG_SHORT_CMD;
976
977
if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
978
(dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
979
softc->fw_cap |= BNXT_FW_CAP_SHORT_CMD;
980
981
if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
982
softc->fw_cap |= BNXT_FW_CAP_KONG_MB_CHNL;
983
984
if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_FLOW_HANDLE_64BIT_SUPPORTED)
985
softc->fw_cap |= BNXT_FW_CAP_OVS_64BIT_HANDLE;
986
987
if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_TRUSTED_VF_SUPPORTED)
988
softc->fw_cap |= BNXT_FW_CAP_TRUSTED_VF;
989
990
if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED)
991
softc->fw_cap |= BNXT_FW_CAP_CFA_ADV_FLOW;
992
993
if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_EEM_SUPPORTED)
994
softc->fw_cap |= BNXT_FW_CAP_CFA_EEM;
995
996
if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_TRUFLOW_SUPPORTED)
997
softc->fw_cap |= BNXT_FW_CAP_TRUFLOW_EN;
998
999
fail:
1000
BNXT_HWRM_UNLOCK(softc);
1001
return rc;
1002
}
1003
1004
static const u16 bnxt_async_events_arr[] = {
1005
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
1006
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE,
1007
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
1008
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
1009
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
1010
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
1011
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE,
1012
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY,
1013
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY,
1014
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RING_MONITOR_MSG,
1015
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEFAULT_VNIC_CHANGE,
1016
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION,
1017
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEFERRED_RESPONSE,
1018
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST,
1019
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP,
1020
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT,
1021
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PHC_UPDATE,
1022
};
1023
1024
int bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *bp, unsigned long *bmap, int bmap_size,
1025
bool async_only)
1026
{
1027
DECLARE_BITMAP(async_events_bmap, 256);
1028
u32 *events = (u32 *)async_events_bmap;
1029
struct hwrm_func_drv_rgtr_output *resp =
1030
(void *)bp->hwrm_cmd_resp.idi_vaddr;
1031
struct hwrm_func_drv_rgtr_input req = {0};
1032
u32 flags = 0;
1033
int rc;
1034
int i;
1035
1036
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_DRV_RGTR);
1037
req.ver_maj = HWRM_VERSION_MAJOR;
1038
req.ver_min = HWRM_VERSION_MINOR;
1039
req.ver_upd = HWRM_VERSION_UPDATE;
1040
1041
req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE |
1042
HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
1043
HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
1044
1045
if (bp->fw_cap & BNXT_FW_CAP_HOT_RESET)
1046
flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_HOT_RESET_SUPPORT;
1047
if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)
1048
flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ERROR_RECOVERY_SUPPORT |
1049
HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_MASTER_SUPPORT;
1050
if (bp->fw_cap & BNXT_FW_CAP_NPAR_1_2)
1051
flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_NPAR_1_2_SUPPORT;
1052
flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ASYM_QUEUE_CFG_SUPPORT;
1053
req.flags = htole32(flags);
1054
req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
1055
1056
if (BNXT_PF(bp)) {
1057
req.enables |=
1058
htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VF_REQ_FWD);
1059
}
1060
1061
if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
1062
req.flags |= cpu_to_le32(HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FLOW_HANDLE_64BIT_MODE);
1063
1064
memset(async_events_bmap, 0, sizeof(async_events_bmap));
1065
for (i = 0; i < ARRAY_SIZE(bnxt_async_events_arr); i++) {
1066
u16 event_id = bnxt_async_events_arr[i];
1067
1068
if (event_id == HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY &&
1069
!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) {
1070
continue;
1071
}
1072
__set_bit(bnxt_async_events_arr[i], async_events_bmap);
1073
}
1074
if (bmap && bmap_size) {
1075
for (i = 0; i < bmap_size; i++) {
1076
if (test_bit(i, bmap))
1077
__set_bit(i, async_events_bmap);
1078
}
1079
}
1080
for (i = 0; i < 8; i++)
1081
req.async_event_fwd[i] |= htole32(events[i]);
1082
1083
if (async_only)
1084
req.enables =
1085
htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
1086
1087
rc = hwrm_send_message(bp, &req, sizeof(req));
1088
1089
if (!rc) {
1090
if (resp->flags &
1091
le32toh(HWRM_FUNC_DRV_RGTR_OUTPUT_FLAGS_IF_CHANGE_SUPPORTED))
1092
bp->fw_cap |= BNXT_FW_CAP_IF_CHANGE;
1093
}
1094
1095
1096
return rc;
1097
}
1098
1099
int
1100
bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
1101
{
1102
struct hwrm_func_drv_unrgtr_input req = {0};
1103
1104
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
1105
if (shutdown == true)
1106
req.flags |=
1107
HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
1108
return hwrm_send_message(softc, &req, sizeof(req));
1109
}
1110
1111
static inline int
1112
_is_valid_ether_addr(uint8_t *addr)
1113
{
1114
char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1115
1116
if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1117
return (FALSE);
1118
1119
return (TRUE);
1120
}
1121
1122
static inline void
1123
get_random_ether_addr(uint8_t *addr)
1124
{
1125
uint8_t temp[ETHER_ADDR_LEN];
1126
1127
arc4rand(&temp, sizeof(temp), 0);
1128
temp[0] &= 0xFE;
1129
temp[0] |= 0x02;
1130
bcopy(temp, addr, sizeof(temp));
1131
}
1132
1133
int
1134
bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
1135
{
1136
int rc = 0;
1137
struct hwrm_func_qcaps_input req = {0};
1138
struct hwrm_func_qcaps_output *resp =
1139
(void *)softc->hwrm_cmd_resp.idi_vaddr;
1140
struct bnxt_func_info *func = &softc->func;
1141
uint32_t flags, flags_ext, flags_ext2;
1142
1143
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
1144
req.fid = htole16(0xffff);
1145
1146
BNXT_HWRM_LOCK(softc);
1147
rc = _hwrm_send_message(softc, &req, sizeof(req));
1148
if (rc)
1149
goto fail;
1150
1151
flags = htole32(resp->flags);
1152
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED)
1153
softc->flags |= BNXT_FLAG_WOL_CAP;
1154
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED)
1155
softc->flags |= BNXT_FLAG_FW_CAP_EXT_STATS;
1156
1157
/* Enable RoCE only on Thor devices */
1158
if (BNXT_CHIP_P5_PLUS(softc)) {
1159
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V1_SUPPORTED)
1160
softc->flags |= BNXT_FLAG_ROCEV1_CAP;
1161
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V2_SUPPORTED)
1162
softc->flags |= BNXT_FLAG_ROCEV2_CAP;
1163
}
1164
1165
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_LINK_ADMIN_STATUS_SUPPORTED)
1166
softc->fw_cap |= BNXT_FW_CAP_LINK_ADMIN;
1167
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ADMIN_PF_SUPPORTED)
1168
softc->fw_cap |= BNXT_FW_CAP_ADMIN_PF;
1169
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_HOT_RESET_CAPABLE)
1170
softc->fw_cap |= BNXT_FW_CAP_HOT_RESET;
1171
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERROR_RECOVERY_CAPABLE)
1172
softc->fw_cap |= BNXT_FW_CAP_ERROR_RECOVERY;
1173
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_PCIE_STATS_SUPPORTED)
1174
softc->fw_cap |= BNXT_FW_CAP_PCIE_STATS_SUPPORTED;
1175
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED)
1176
softc->fw_cap |= BNXT_FW_CAP_EXT_STATS_SUPPORTED;
1177
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERR_RECOVER_RELOAD)
1178
softc->fw_cap |= BNXT_FW_CAP_ERR_RECOVER_RELOAD;
1179
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_NOTIFY_VF_DEF_VNIC_CHNG_SUPPORTED)
1180
softc->fw_cap |= BNXT_FW_CAP_VF_VNIC_NOTIFY;
1181
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_CRASHDUMP_CMD_SUPPORTED)
1182
softc->fw_cap |= BNXT_FW_CAP_CRASHDUMP;
1183
if (!(flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_VLAN_ACCELERATION_TX_DISABLED))
1184
softc->fw_cap |= BNXT_FW_CAP_VLAN_TX_INSERT;
1185
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_DBG_QCAPS_CMD_SUPPORTED)
1186
softc->fw_cap |= BNXT_FW_CAP_DBG_QCAPS;
1187
1188
flags_ext = htole32(resp->flags_ext);
1189
if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_EXT_HW_STATS_SUPPORTED)
1190
softc->fw_cap |= BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED;
1191
if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_ECN_STATS_SUPPORTED))
1192
softc->fw_cap |= BNXT_FW_CAP_ECN_STATS;
1193
1194
if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_PPS_SUPPORTED)
1195
softc->fw_cap |= BNXT_FW_CAP_PTP_PPS;
1196
if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_PTM_SUPPORTED)
1197
softc->fw_cap |= BNXT_FW_CAP_PTP_PTM;
1198
if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_64BIT_RTC_SUPPORTED)
1199
softc->fw_cap |= BNXT_FW_CAP_PTP_RTC;
1200
if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_HOT_RESET_IF_SUPPORT))
1201
softc->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF;
1202
if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED))
1203
softc->fw_cap |= BNXT_FW_CAP_LIVEPATCH;
1204
if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_NPAR_1_2_SUPPORTED)
1205
softc->fw_cap |= BNXT_FW_CAP_NPAR_1_2;
1206
if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_BS_V2_SUPPORTED)
1207
softc->fw_cap |= BNXT_FW_CAP_BACKING_STORE_V2;
1208
if (BNXT_PF(softc) &&
1209
(flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_VF_CFG_ASYNC_FOR_PF_SUPPORTED))
1210
softc->fw_cap |= BNXT_FW_CAP_VF_CFG_FOR_PF;
1211
1212
flags_ext2 = htole32(resp->flags_ext2);
1213
if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_RX_ALL_PKTS_TIMESTAMPS_SUPPORTED)
1214
softc->fw_cap |= BNXT_FW_CAP_RX_ALL_PKT_TS;
1215
if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SW_DBR_DROP_RECOVERY_SUPPORTED)
1216
softc->fw_cap |= BNXT_FW_CAP_DBR_SUPPORTED;
1217
if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_DBR_PACING_EXT_SUPPORTED ||
1218
flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_DBR_PACING_SUPPORTED)
1219
softc->fw_cap |= BNXT_FW_CAP_DBR_PACING_SUPPORTED;
1220
1221
if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SW_MAX_RESOURCE_LIMITS_SUPPORTED)
1222
softc->fw_cap |= BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS;
1223
1224
if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_GENERIC_STATS_SUPPORTED)
1225
softc->fw_cap |= BNXT_FW_CAP_GENERIC_STATS;
1226
func->fw_fid = le16toh(resp->fid);
1227
memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
1228
func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
1229
func->max_cp_rings = le16toh(resp->max_cmpl_rings);
1230
func->max_tx_rings = le16toh(resp->max_tx_rings);
1231
func->max_rx_rings = le16toh(resp->max_rx_rings);
1232
func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
1233
if (!func->max_hw_ring_grps)
1234
func->max_hw_ring_grps = func->max_tx_rings;
1235
func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
1236
func->max_vnics = le16toh(resp->max_vnics);
1237
func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
1238
if (BNXT_PF(softc)) {
1239
struct bnxt_pf_info *pf = &softc->pf;
1240
1241
pf->port_id = le16toh(resp->port_id);
1242
pf->first_vf_id = le16toh(resp->first_vf_id);
1243
pf->max_vfs = le16toh(resp->max_vfs);
1244
pf->max_encap_records = le32toh(resp->max_encap_records);
1245
pf->max_decap_records = le32toh(resp->max_decap_records);
1246
pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
1247
pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
1248
pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
1249
pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
1250
}
1251
if (!_is_valid_ether_addr(func->mac_addr)) {
1252
device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
1253
get_random_ether_addr(func->mac_addr);
1254
}
1255
1256
fail:
1257
BNXT_HWRM_UNLOCK(softc);
1258
return rc;
1259
}
1260
1261
int
1262
bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
1263
{
1264
struct hwrm_func_qcfg_input req = {0};
1265
struct hwrm_func_qcfg_output *resp =
1266
(void *)softc->hwrm_cmd_resp.idi_vaddr;
1267
struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
1268
uint32_t min_db_offset = 0;
1269
uint16_t flags;
1270
int rc;
1271
1272
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
1273
req.fid = htole16(0xffff);
1274
BNXT_HWRM_LOCK(softc);
1275
rc = _hwrm_send_message(softc, &req, sizeof(req));
1276
if (rc)
1277
goto end;
1278
1279
fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
1280
fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
1281
fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
1282
fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
1283
1284
switch (resp->port_partition_type) {
1285
case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_0:
1286
case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_2:
1287
case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_5:
1288
case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR2_0:
1289
softc->port_partition_type = resp->port_partition_type;
1290
break;
1291
}
1292
1293
flags = le16toh(resp->flags);
1294
if (flags & (HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED |
1295
HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_LLDP_AGENT_ENABLED)) {
1296
softc->fw_cap |= BNXT_FW_CAP_LLDP_AGENT;
1297
if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED)
1298
softc->fw_cap |= BNXT_FW_CAP_DCBX_AGENT;
1299
}
1300
if (BNXT_PF(softc) && (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_MULTI_HOST))
1301
softc->flags |= BNXT_FLAG_MULTI_HOST;
1302
if (BNXT_PF(softc) && (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_MULTI_ROOT))
1303
softc->flags |= BNXT_FLAG_MULTI_ROOT;
1304
if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_SECURE_MODE_ENABLED)
1305
softc->fw_cap |= BNXT_FW_CAP_SECURE_MODE;
1306
if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_RING_MONITOR_ENABLED)
1307
softc->fw_cap |= BNXT_FW_CAP_RING_MONITOR;
1308
if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_ENABLE_RDMA_SRIOV)
1309
softc->fw_cap |= BNXT_FW_CAP_ENABLE_RDMA_SRIOV;
1310
1311
if (softc->db_size)
1312
goto end;
1313
1314
softc->legacy_db_size = le16_to_cpu(resp->legacy_l2_db_size_kb) * 1024;
1315
softc->db_offset = le16toh(resp->legacy_l2_db_size_kb) * 1024;
1316
1317
if (BNXT_CHIP_P5(softc)) {
1318
if (BNXT_PF(softc))
1319
min_db_offset = DB_PF_OFFSET_P5;
1320
else
1321
min_db_offset = DB_VF_OFFSET_P5;
1322
softc->legacy_db_size = min_db_offset;
1323
softc->db_offset = min_db_offset;
1324
}
1325
1326
softc->db_size = roundup2(le16_to_cpu(resp->l2_doorbell_bar_size_kb) *
1327
1024, PAGE_SIZE);
1328
if (!softc->db_size || softc->db_size > pci_resource_len(softc->pdev, 2) ||
1329
softc->db_size <= min_db_offset)
1330
softc->db_size = pci_resource_len(softc->pdev, 2);
1331
1332
end:
1333
BNXT_HWRM_UNLOCK(softc);
1334
return rc;
1335
}
1336
1337
int
1338
bnxt_hwrm_func_reset(struct bnxt_softc *softc)
1339
{
1340
struct hwrm_func_reset_input req = {0};
1341
1342
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
1343
req.enables = 0;
1344
1345
return hwrm_send_message(softc, &req, sizeof(req));
1346
}
1347
1348
static void
1349
bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
1350
struct hwrm_port_phy_cfg_input *req)
1351
{
1352
struct bnxt_link_info *link_info = &softc->link_info;
1353
uint8_t autoneg = softc->link_info.autoneg;
1354
uint16_t fw_link_speed = softc->link_info.req_link_speed;
1355
1356
if (autoneg & BNXT_AUTONEG_SPEED) {
1357
uint8_t phy_type = get_phy_type(softc);
1358
1359
if (phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET ||
1360
phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET ||
1361
phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE) {
1362
1363
req->auto_mode |= htole32(HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK);
1364
if (link_info->advertising) {
1365
req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK);
1366
req->auto_link_speed_mask = htole16(link_info->advertising);
1367
}
1368
} else {
1369
req->auto_mode |= HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
1370
}
1371
1372
req->enables |=
1373
htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
1374
req->flags |=
1375
htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
1376
} else {
1377
1378
if (link_info->force_speed2_nrz ||
1379
link_info->force_pam4_56_speed2 ||
1380
link_info->force_pam4_112_speed2) {
1381
req->force_link_speeds2 = htole16(fw_link_speed);
1382
req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_LINK_SPEEDS2);
1383
link_info->force_speed2_nrz = false;
1384
link_info->force_pam4_56_speed2 = false;
1385
link_info->force_pam4_112_speed2 = false;
1386
} else if (link_info->force_pam4_speed) {
1387
req->force_pam4_link_speed = htole16(fw_link_speed);
1388
req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAM4_LINK_SPEED);
1389
link_info->force_pam4_speed = false;
1390
} else {
1391
req->force_link_speed = htole16(fw_link_speed);
1392
}
1393
1394
req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
1395
}
1396
1397
/* tell chimp that the setting takes effect immediately */
1398
req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
1399
}
1400
1401
static void
1402
bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
1403
struct hwrm_port_phy_cfg_input *req)
1404
{
1405
struct bnxt_link_info *link_info = &softc->link_info;
1406
1407
if (link_info->flow_ctrl.autoneg) {
1408
req->auto_pause =
1409
HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
1410
if (link_info->flow_ctrl.rx)
1411
req->auto_pause |=
1412
HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
1413
if (link_info->flow_ctrl.tx)
1414
req->auto_pause |=
1415
HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
1416
req->enables |=
1417
htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
1418
} else {
1419
if (link_info->flow_ctrl.rx)
1420
req->force_pause |=
1421
HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
1422
if (link_info->flow_ctrl.tx)
1423
req->force_pause |=
1424
HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
1425
req->enables |=
1426
htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
1427
req->auto_pause = req->force_pause;
1428
req->enables |=
1429
htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
1430
}
1431
}
1432
1433
/* JFV this needs interface connection */
1434
static void
1435
bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
1436
{
1437
/* struct ethtool_eee *eee = &softc->eee; */
1438
bool eee_enabled = false;
1439
1440
if (eee_enabled) {
1441
#if 0
1442
uint16_t eee_speeds;
1443
uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
1444
1445
if (eee->tx_lpi_enabled)
1446
flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
1447
1448
req->flags |= htole32(flags);
1449
eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
1450
req->eee_link_speed_mask = htole16(eee_speeds);
1451
req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
1452
#endif
1453
} else {
1454
req->flags |=
1455
htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
1456
}
1457
}
1458
1459
int
1460
bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
1461
bool set_eee, bool set_link)
1462
{
1463
struct hwrm_port_phy_cfg_input req = {0};
1464
int rc;
1465
1466
if (softc->flags & BNXT_FLAG_NPAR)
1467
return ENOTSUP;
1468
1469
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
1470
1471
if (set_pause) {
1472
bnxt_hwrm_set_pause_common(softc, &req);
1473
1474
if (softc->link_info.flow_ctrl.autoneg)
1475
set_link = true;
1476
}
1477
1478
if (set_link)
1479
bnxt_hwrm_set_link_common(softc, &req);
1480
1481
if (set_eee)
1482
bnxt_hwrm_set_eee(softc, &req);
1483
1484
BNXT_HWRM_LOCK(softc);
1485
rc = _hwrm_send_message(softc, &req, sizeof(req));
1486
1487
if (!rc) {
1488
if (set_pause) {
1489
/* since changing of 'force pause' setting doesn't
1490
* trigger any link change event, the driver needs to
1491
* update the current pause result upon successfully i
1492
* return of the phy_cfg command */
1493
if (!softc->link_info.flow_ctrl.autoneg)
1494
bnxt_report_link(softc);
1495
}
1496
}
1497
BNXT_HWRM_UNLOCK(softc);
1498
return rc;
1499
}
1500
1501
int
1502
bnxt_hwrm_vnic_set_hds(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1503
{
1504
struct hwrm_vnic_plcmodes_cfg_input req = {0};
1505
1506
if (!BNXT_CHIP_P5_PLUS(softc))
1507
return 0;
1508
1509
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_PLCMODES_CFG);
1510
1511
req.flags = htole32(HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT);
1512
req.vnic_id = htole16(vnic->id);
1513
1514
return hwrm_send_message(softc, &req, sizeof(req));
1515
}
1516
1517
int
1518
bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1519
{
1520
struct hwrm_vnic_cfg_input req = {0};
1521
1522
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
1523
1524
if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1525
req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
1526
if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
1527
req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
1528
if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
1529
req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
1530
if (BNXT_CHIP_P5_PLUS (softc)) {
1531
req.default_rx_ring_id =
1532
htole16(softc->rx_rings[0].phys_id);
1533
req.default_cmpl_ring_id =
1534
htole16(softc->rx_cp_rings[0].ring.phys_id);
1535
req.enables |=
1536
htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_RX_RING_ID |
1537
HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_CMPL_RING_ID);
1538
req.vnic_id = htole16(vnic->id);
1539
} else {
1540
req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
1541
HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE);
1542
req.vnic_id = htole16(vnic->id);
1543
req.dflt_ring_grp = htole16(vnic->def_ring_grp);
1544
}
1545
req.rss_rule = htole16(vnic->rss_id);
1546
req.cos_rule = htole16(vnic->cos_rule);
1547
req.lb_rule = htole16(vnic->lb_rule);
1548
req.enables |= htole32(HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
1549
req.mru = htole16(vnic->mru);
1550
1551
return hwrm_send_message(softc, &req, sizeof(req));
1552
}
1553
1554
int
1555
bnxt_hwrm_vnic_free(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1556
{
1557
struct hwrm_vnic_free_input req = {0};
1558
int rc = 0;
1559
1560
if (vnic->id == (uint16_t)HWRM_NA_SIGNATURE)
1561
return rc;
1562
1563
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_FREE);
1564
1565
req.vnic_id = htole32(vnic->id);
1566
1567
BNXT_HWRM_LOCK(softc);
1568
rc = _hwrm_send_message(softc, &req, sizeof(req));
1569
if (rc)
1570
goto fail;
1571
1572
fail:
1573
BNXT_HWRM_UNLOCK(softc);
1574
return (rc);
1575
}
1576
1577
int
1578
bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1579
{
1580
struct hwrm_vnic_alloc_input req = {0};
1581
struct hwrm_vnic_alloc_output *resp =
1582
(void *)softc->hwrm_cmd_resp.idi_vaddr;
1583
int rc;
1584
1585
if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
1586
device_printf(softc->dev,
1587
"Attempt to re-allocate vnic %04x\n", vnic->id);
1588
return EDOOFUS;
1589
}
1590
1591
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
1592
1593
if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1594
req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
1595
1596
BNXT_HWRM_LOCK(softc);
1597
rc = _hwrm_send_message(softc, &req, sizeof(req));
1598
if (rc)
1599
goto fail;
1600
1601
vnic->id = le32toh(resp->vnic_id);
1602
1603
fail:
1604
BNXT_HWRM_UNLOCK(softc);
1605
return (rc);
1606
}
1607
1608
int
1609
bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *softc, uint16_t ctx_id)
1610
{
1611
struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0};
1612
int rc = 0;
1613
1614
if (ctx_id == (uint16_t)HWRM_NA_SIGNATURE)
1615
return rc;
1616
1617
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE);
1618
req.rss_cos_lb_ctx_id = htole16(ctx_id);
1619
BNXT_HWRM_LOCK(softc);
1620
rc = _hwrm_send_message(softc, &req, sizeof(req));
1621
if (rc)
1622
goto fail;
1623
1624
fail:
1625
BNXT_HWRM_UNLOCK(softc);
1626
return rc;
1627
}
1628
1629
int
1630
bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
1631
{
1632
struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
1633
struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
1634
(void *)softc->hwrm_cmd_resp.idi_vaddr;
1635
int rc;
1636
1637
if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
1638
device_printf(softc->dev,
1639
"Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
1640
return EDOOFUS;
1641
}
1642
1643
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
1644
1645
BNXT_HWRM_LOCK(softc);
1646
rc = _hwrm_send_message(softc, &req, sizeof(req));
1647
if (rc)
1648
goto fail;
1649
1650
*ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
1651
1652
fail:
1653
BNXT_HWRM_UNLOCK(softc);
1654
return (rc);
1655
}
1656
1657
int
1658
bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1659
{
1660
struct hwrm_ring_grp_alloc_input req = {0};
1661
struct hwrm_ring_grp_alloc_output *resp;
1662
int rc = 0;
1663
1664
if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
1665
device_printf(softc->dev,
1666
"Attempt to re-allocate ring group %04x\n", grp->grp_id);
1667
return EDOOFUS;
1668
}
1669
1670
if (BNXT_CHIP_P5_PLUS (softc))
1671
return 0;
1672
1673
resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1674
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
1675
req.cr = htole16(grp->cp_ring_id);
1676
req.rr = htole16(grp->rx_ring_id);
1677
req.ar = htole16(grp->ag_ring_id);
1678
req.sc = htole16(grp->stats_ctx);
1679
1680
BNXT_HWRM_LOCK(softc);
1681
rc = _hwrm_send_message(softc, &req, sizeof(req));
1682
if (rc)
1683
goto fail;
1684
1685
grp->grp_id = le32toh(resp->ring_group_id);
1686
1687
fail:
1688
BNXT_HWRM_UNLOCK(softc);
1689
return rc;
1690
}
1691
1692
int
1693
bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1694
{
1695
struct hwrm_ring_grp_free_input req = {0};
1696
int rc = 0;
1697
1698
if (grp->grp_id == (uint16_t)HWRM_NA_SIGNATURE)
1699
return 0;
1700
1701
if (BNXT_CHIP_P5_PLUS (softc))
1702
return 0;
1703
1704
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_FREE);
1705
1706
req.ring_group_id = htole32(grp->grp_id);
1707
1708
BNXT_HWRM_LOCK(softc);
1709
rc = _hwrm_send_message(softc, &req, sizeof(req));
1710
if (rc)
1711
goto fail;
1712
1713
fail:
1714
BNXT_HWRM_UNLOCK(softc);
1715
return rc;
1716
}
1717
1718
int bnxt_hwrm_ring_free(struct bnxt_softc *softc, uint32_t ring_type,
1719
struct bnxt_ring *ring, int cmpl_ring_id)
1720
{
1721
struct hwrm_ring_free_input req = {0};
1722
struct hwrm_ring_free_output *resp;
1723
int rc = 0;
1724
uint16_t error_code;
1725
1726
if (ring->phys_id == (uint16_t)HWRM_NA_SIGNATURE)
1727
return 0;
1728
1729
resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1730
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_FREE);
1731
req.cmpl_ring = htole16(cmpl_ring_id);
1732
req.ring_type = ring_type;
1733
req.ring_id = htole16(ring->phys_id);
1734
1735
BNXT_HWRM_LOCK(softc);
1736
rc = _hwrm_send_message(softc, &req, sizeof(req));
1737
error_code = le16toh(resp->error_code);
1738
1739
if (rc || error_code) {
1740
device_printf(softc->dev, "hwrm_ring_free type %d failed. "
1741
"rc:%x err:%x\n", ring_type, rc, error_code);
1742
if (!rc)
1743
rc = -EIO;
1744
}
1745
1746
BNXT_HWRM_UNLOCK(softc);
1747
return rc;
1748
}
1749
1750
/*
1751
* Ring allocation message to the firmware
1752
*/
1753
int
1754
bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
1755
struct bnxt_ring *ring)
1756
{
1757
struct hwrm_ring_alloc_input req = {0};
1758
struct hwrm_ring_alloc_output *resp;
1759
uint16_t idx = ring->idx;
1760
struct bnxt_cp_ring *cp_ring;
1761
int rc;
1762
1763
if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
1764
device_printf(softc->dev,
1765
"Attempt to re-allocate ring %04x\n", ring->phys_id);
1766
return EDOOFUS;
1767
}
1768
1769
resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1770
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
1771
req.enables = htole32(0);
1772
req.fbo = htole32(0);
1773
req.ring_type = type;
1774
req.page_tbl_addr = htole64(ring->paddr);
1775
req.logical_id = htole16(ring->id);
1776
req.length = htole32(ring->ring_size);
1777
1778
switch (type) {
1779
case HWRM_RING_ALLOC_INPUT_RING_TYPE_TX:
1780
cp_ring = &softc->tx_cp_rings[idx];
1781
1782
req.cmpl_ring_id = htole16(cp_ring->ring.phys_id);
1783
/* queue_id - what CoS queue the TX ring is associated with */
1784
req.queue_id = htole16(softc->tx_q_info[0].queue_id);
1785
1786
req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1787
req.enables |= htole32(
1788
HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1789
break;
1790
case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX:
1791
if (!BNXT_CHIP_P5_PLUS(softc))
1792
break;
1793
1794
cp_ring = &softc->rx_cp_rings[idx];
1795
1796
req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1797
req.rx_buf_size = htole16(softc->rx_buf_size);
1798
req.enables |= htole32(
1799
HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1800
HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1801
break;
1802
case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG:
1803
if (!BNXT_CHIP_P5_PLUS(softc)) {
1804
req.ring_type = HWRM_RING_ALLOC_INPUT_RING_TYPE_RX;
1805
break;
1806
}
1807
1808
cp_ring = &softc->rx_cp_rings[idx];
1809
1810
req.rx_ring_id = htole16(softc->rx_rings[idx].phys_id);
1811
req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1812
req.rx_buf_size = htole16(softc->rx_buf_size);
1813
req.enables |= htole32(
1814
HWRM_RING_ALLOC_INPUT_ENABLES_RX_RING_ID_VALID |
1815
HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1816
HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1817
break;
1818
case HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL:
1819
if (!BNXT_CHIP_P5_PLUS(softc)) {
1820
req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1821
break;
1822
}
1823
1824
req.cq_handle = htole64(ring->id);
1825
req.nq_ring_id = htole16(softc->nq_rings[idx].ring.phys_id);
1826
req.enables |= htole32(
1827
HWRM_RING_ALLOC_INPUT_ENABLES_NQ_RING_ID_VALID);
1828
break;
1829
case HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ:
1830
req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1831
break;
1832
default:
1833
device_printf(softc->dev,
1834
"hwrm alloc invalid ring type %d\n", type);
1835
return -1;
1836
}
1837
1838
BNXT_HWRM_LOCK(softc);
1839
rc = _hwrm_send_message(softc, &req, sizeof(req));
1840
if (rc)
1841
goto fail;
1842
1843
ring->phys_id = le16toh(resp->ring_id);
1844
1845
fail:
1846
BNXT_HWRM_UNLOCK(softc);
1847
return rc;
1848
}
1849
1850
int
1851
bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr)
1852
{
1853
struct hwrm_stat_ctx_free_input req = {0};
1854
int rc = 0;
1855
1856
if (cpr->stats_ctx_id == HWRM_NA_SIGNATURE)
1857
return rc;
1858
1859
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_FREE);
1860
1861
req.stat_ctx_id = htole16(cpr->stats_ctx_id);
1862
BNXT_HWRM_LOCK(softc);
1863
rc = _hwrm_send_message(softc, &req, sizeof(req));
1864
if (rc)
1865
goto fail;
1866
1867
fail:
1868
BNXT_HWRM_UNLOCK(softc);
1869
1870
return rc;
1871
}
1872
1873
int
1874
bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
1875
uint64_t paddr)
1876
{
1877
struct hwrm_stat_ctx_alloc_input req = {0};
1878
struct hwrm_stat_ctx_alloc_output *resp;
1879
int rc = 0;
1880
1881
if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
1882
device_printf(softc->dev,
1883
"Attempt to re-allocate stats ctx %08x\n",
1884
cpr->stats_ctx_id);
1885
return EDOOFUS;
1886
}
1887
1888
resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1889
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
1890
1891
req.update_period_ms = htole32(1000);
1892
req.stats_dma_addr = htole64(paddr);
1893
1894
if (BNXT_CHIP_P7(softc))
1895
req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats_ext));
1896
else if (BNXT_CHIP_P5(softc))
1897
req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats_ext) - 8);
1898
else
1899
req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats));
1900
1901
BNXT_HWRM_LOCK(softc);
1902
rc = _hwrm_send_message(softc, &req, sizeof(req));
1903
if (rc)
1904
goto fail;
1905
1906
cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
1907
1908
fail:
1909
BNXT_HWRM_UNLOCK(softc);
1910
1911
return rc;
1912
}
1913
1914
int
1915
bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
1916
{
1917
struct hwrm_port_qstats_input req = {0};
1918
int rc = 0;
1919
1920
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
1921
1922
req.port_id = htole16(softc->pf.port_id);
1923
req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
1924
req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
1925
1926
BNXT_HWRM_LOCK(softc);
1927
rc = _hwrm_send_message(softc, &req, sizeof(req));
1928
BNXT_HWRM_UNLOCK(softc);
1929
1930
return rc;
1931
}
1932
static int bnxt_hwrm_pri2cos_idx(struct bnxt_softc *softc, uint32_t path_dir)
1933
{
1934
struct hwrm_queue_pri2cos_qcfg_input req = {0};
1935
struct hwrm_queue_pri2cos_qcfg_output *resp;
1936
uint8_t *pri2cos_idx, *q_ids, max_q;
1937
int rc, i, j;
1938
uint8_t *pri2cos;
1939
1940
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_QCFG);
1941
resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1942
1943
req.flags = htole32(HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN |
1944
path_dir);
1945
rc = hwrm_send_message(softc, &req, sizeof(req));
1946
1947
if (rc)
1948
return rc;
1949
1950
if (path_dir == HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX) {
1951
pri2cos_idx = softc->tx_pri2cos_idx;
1952
q_ids = softc->tx_q_ids;
1953
max_q = softc->tx_max_q;
1954
} else {
1955
pri2cos_idx = softc->rx_pri2cos_idx;
1956
q_ids = softc->rx_q_ids;
1957
max_q = softc->rx_max_q;
1958
}
1959
1960
pri2cos = &resp->pri0_cos_queue_id;
1961
1962
for (i = 0; i < BNXT_MAX_QUEUE; i++) {
1963
uint8_t queue_id = pri2cos[i];
1964
uint8_t queue_idx;
1965
1966
/* Per port queue IDs start from 0, 10, 20, etc */
1967
queue_idx = queue_id % 10;
1968
if (queue_idx > BNXT_MAX_QUEUE) {
1969
softc->pri2cos_valid = false;
1970
rc = -EINVAL;
1971
return rc;
1972
}
1973
1974
for (j = 0; j < max_q; j++) {
1975
if (q_ids[j] == queue_id)
1976
pri2cos_idx[i] = queue_idx;
1977
}
1978
}
1979
1980
softc->pri2cos_valid = true;
1981
1982
return rc;
1983
}
1984
1985
int
1986
bnxt_hwrm_port_qstats_ext(struct bnxt_softc *softc)
1987
{
1988
struct hwrm_port_qstats_ext_input req = {0};
1989
struct hwrm_port_qstats_ext_output *resp;
1990
int rc = 0, i;
1991
uint32_t tx_stat_size;
1992
1993
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS_EXT);
1994
resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1995
1996
tx_stat_size = sizeof(struct tx_port_stats_ext);
1997
req.port_id = htole16(softc->pf.port_id);
1998
req.tx_stat_size = htole16(tx_stat_size);
1999
req.rx_stat_size = htole16(sizeof(struct rx_port_stats_ext));
2000
req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats_ext.idi_paddr);
2001
req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats_ext.idi_paddr);
2002
2003
rc = hwrm_send_message(softc, &req, sizeof(req));
2004
2005
if (!rc) {
2006
softc->fw_rx_stats_ext_size =
2007
le16toh(resp->rx_stat_size) / 8;
2008
if (BNXT_FW_MAJ(softc) < 220 && !BNXT_CHIP_P7(softc) &&
2009
softc->fw_rx_stats_ext_size > BNXT_RX_STATS_EXT_NUM_LEGACY)
2010
softc->fw_rx_stats_ext_size = BNXT_RX_STATS_EXT_NUM_LEGACY;
2011
2012
softc->fw_tx_stats_ext_size = tx_stat_size ?
2013
le16toh(resp->tx_stat_size) / 8 : 0;
2014
} else {
2015
softc->fw_rx_stats_ext_size = 0;
2016
softc->fw_tx_stats_ext_size = 0;
2017
}
2018
2019
if (softc->fw_tx_stats_ext_size <=
2020
offsetof(struct tx_port_stats_ext, pfc_pri0_tx_duration_us) / 8) {
2021
softc->pri2cos_valid = false;
2022
return rc;
2023
}
2024
2025
rc = bnxt_hwrm_pri2cos_idx(softc, HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX);
2026
if (rc)
2027
return rc;
2028
2029
if (softc->is_asym_q) {
2030
rc = bnxt_hwrm_pri2cos_idx(softc, HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX);
2031
if (rc)
2032
return rc;
2033
} else {
2034
memcpy(softc->rx_pri2cos_idx, softc->tx_pri2cos_idx, sizeof(softc->rx_pri2cos_idx));
2035
}
2036
2037
u64 *rx_port_stats_ext = (u64 *)softc->hw_rx_port_stats_ext.idi_vaddr;
2038
u64 *tx_port_stats_ext = (u64 *)softc->hw_tx_port_stats_ext.idi_vaddr;
2039
2040
if (softc->pri2cos_valid) {
2041
for (i = 0; i < 8; i++) {
2042
long n = bnxt_rx_bytes_pri_arr_base_off[i] +
2043
softc->rx_pri2cos_idx[i];
2044
2045
softc->rx_bytes_pri[i] = *(rx_port_stats_ext + n);
2046
}
2047
for (i = 0; i < 8; i++) {
2048
long n = bnxt_rx_pkts_pri_arr_base_off[i] +
2049
softc->rx_pri2cos_idx[i];
2050
2051
softc->rx_packets_pri[i] = *(rx_port_stats_ext + n);
2052
}
2053
for (i = 0; i < 8; i++) {
2054
long n = bnxt_tx_bytes_pri_arr_base_off[i] +
2055
softc->tx_pri2cos_idx[i];
2056
2057
softc->tx_bytes_pri[i] = *(tx_port_stats_ext + n);
2058
}
2059
for (i = 0; i < 8; i++) {
2060
long n = bnxt_tx_pkts_pri_arr_base_off[i] +
2061
softc->tx_pri2cos_idx[i];
2062
2063
softc->tx_packets_pri[i] = *(tx_port_stats_ext + n);
2064
}
2065
}
2066
2067
return rc;
2068
}
2069
2070
int
2071
bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
2072
struct bnxt_vnic_info *vnic)
2073
{
2074
struct hwrm_cfa_l2_set_rx_mask_input req = {0};
2075
uint32_t mask = vnic->rx_mask;
2076
2077
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
2078
2079
req.vnic_id = htole32(vnic->id);
2080
req.mask = htole32(mask);
2081
req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
2082
req.num_mc_entries = htole32(vnic->mc_list_count);
2083
return hwrm_send_message(softc, &req, sizeof(req));
2084
}
2085
2086
int
2087
bnxt_hwrm_l2_filter_free(struct bnxt_softc *softc, uint64_t filter_id)
2088
{
2089
struct hwrm_cfa_l2_filter_free_input req = {0};
2090
int rc = 0;
2091
2092
if (filter_id == -1)
2093
return rc;
2094
2095
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_FREE);
2096
2097
req.l2_filter_id = htole64(filter_id);
2098
2099
BNXT_HWRM_LOCK(softc);
2100
rc = _hwrm_send_message(softc, &req, sizeof(req));
2101
if (rc)
2102
goto fail;
2103
2104
fail:
2105
BNXT_HWRM_UNLOCK(softc);
2106
return (rc);
2107
}
2108
2109
int
2110
bnxt_hwrm_free_filter(struct bnxt_softc *softc)
2111
{
2112
struct bnxt_vnic_info *vnic = &softc->vnic_info;
2113
struct bnxt_vlan_tag *tag;
2114
int rc = 0;
2115
2116
rc = bnxt_hwrm_l2_filter_free(softc, softc->vnic_info.filter_id);
2117
if (rc)
2118
goto end;
2119
2120
SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
2121
rc = bnxt_hwrm_l2_filter_free(softc, tag->filter_id);
2122
if (rc)
2123
goto end;
2124
tag->filter_id = -1;
2125
}
2126
2127
end:
2128
return rc;
2129
}
2130
2131
int
2132
bnxt_hwrm_l2_filter_alloc(struct bnxt_softc *softc, uint16_t vlan_tag,
2133
uint64_t *filter_id)
2134
{
2135
struct hwrm_cfa_l2_filter_alloc_input req = {0};
2136
struct hwrm_cfa_l2_filter_alloc_output *resp;
2137
struct bnxt_vnic_info *vnic = &softc->vnic_info;
2138
uint32_t enables = 0;
2139
int rc = 0;
2140
2141
if (*filter_id != -1) {
2142
device_printf(softc->dev, "Attempt to re-allocate l2 ctx "
2143
"filter (fid: 0x%jx)\n", (uintmax_t)*filter_id);
2144
return EDOOFUS;
2145
}
2146
2147
resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
2148
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
2149
2150
req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
2151
enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
2152
| HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
2153
| HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
2154
2155
if (vlan_tag != 0xffff) {
2156
enables |=
2157
HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN |
2158
HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN_MASK |
2159
HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_NUM_VLANS;
2160
req.l2_ivlan_mask = 0xffff;
2161
req.l2_ivlan = vlan_tag;
2162
req.num_vlans = 1;
2163
}
2164
2165
req.enables = htole32(enables);
2166
req.dst_id = htole16(vnic->id);
2167
memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
2168
ETHER_ADDR_LEN);
2169
memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
2170
2171
BNXT_HWRM_LOCK(softc);
2172
rc = _hwrm_send_message(softc, &req, sizeof(req));
2173
if (rc)
2174
goto fail;
2175
2176
*filter_id = le64toh(resp->l2_filter_id);
2177
fail:
2178
BNXT_HWRM_UNLOCK(softc);
2179
return (rc);
2180
}
2181
2182
int
2183
bnxt_hwrm_set_filter(struct bnxt_softc *softc)
2184
{
2185
struct bnxt_vnic_info *vnic = &softc->vnic_info;
2186
struct bnxt_vlan_tag *tag;
2187
int rc = 0;
2188
2189
rc = bnxt_hwrm_l2_filter_alloc(softc, 0xffff, &vnic->filter_id);
2190
if (rc)
2191
goto end;
2192
2193
SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
2194
rc = bnxt_hwrm_l2_filter_alloc(softc, tag->tag,
2195
&tag->filter_id);
2196
if (rc)
2197
goto end;
2198
}
2199
2200
end:
2201
return rc;
2202
}
2203
2204
int
2205
bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
2206
uint32_t hash_type)
2207
{
2208
struct hwrm_vnic_rss_cfg_input req = {0};
2209
2210
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
2211
2212
if (BNXT_CHIP_P7(softc))
2213
req.flags |= HWRM_VNIC_RSS_CFG_INPUT_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT;
2214
2215
req.hash_type = htole32(hash_type);
2216
req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
2217
req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
2218
req.rss_ctx_idx = htole16(vnic->rss_id);
2219
req.hash_mode_flags = HWRM_FUNC_SPD_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
2220
if (BNXT_CHIP_P5_PLUS(softc)) {
2221
req.vnic_id = htole16(vnic->id);
2222
req.ring_table_pair_index = 0x0;
2223
}
2224
2225
return hwrm_send_message(softc, &req, sizeof(req));
2226
}
2227
2228
int
2229
bnxt_hwrm_reserve_pf_rings(struct bnxt_softc *softc)
2230
{
2231
struct hwrm_func_cfg_input req = {0};
2232
2233
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
2234
2235
req.fid = htole16(0xffff);
2236
req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RSSCOS_CTXS);
2237
req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_CMPL_RINGS);
2238
req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_TX_RINGS);
2239
req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RX_RINGS);
2240
req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_VNICS);
2241
req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_MSIX);
2242
req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_STAT_CTXS);
2243
req.num_msix = htole16(BNXT_MAX_NUM_QUEUES);
2244
req.num_rsscos_ctxs = htole16(0x8);
2245
req.num_cmpl_rings = htole16(BNXT_MAX_NUM_QUEUES * 2);
2246
req.num_tx_rings = htole16(BNXT_MAX_NUM_QUEUES);
2247
req.num_rx_rings = htole16(BNXT_MAX_NUM_QUEUES);
2248
req.num_vnics = htole16(BNXT_MAX_NUM_QUEUES);
2249
req.num_stat_ctxs = htole16(BNXT_MAX_NUM_QUEUES * 2);
2250
2251
return hwrm_send_message(softc, &req, sizeof(req));
2252
}
2253
2254
int
2255
bnxt_cfg_async_cr(struct bnxt_softc *softc)
2256
{
2257
int rc = 0;
2258
struct hwrm_func_cfg_input req = {0};
2259
2260
if (!BNXT_PF(softc))
2261
return 0;
2262
2263
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
2264
2265
req.fid = htole16(0xffff);
2266
req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
2267
if (BNXT_CHIP_P5_PLUS(softc))
2268
req.async_event_cr = htole16(softc->nq_rings[0].ring.phys_id);
2269
else
2270
req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
2271
2272
rc = hwrm_send_message(softc, &req, sizeof(req));
2273
2274
return rc;
2275
}
2276
2277
void
2278
bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
2279
{
2280
softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
2281
2282
softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
2283
2284
softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
2285
HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
2286
2287
softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
2288
HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
2289
2290
softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
2291
}
2292
2293
int
2294
bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
2295
{
2296
struct hwrm_vnic_tpa_cfg_input req = {0};
2297
uint32_t flags;
2298
2299
if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
2300
return 0;
2301
}
2302
2303
if (!(softc->flags & BNXT_FLAG_TPA))
2304
return 0;
2305
2306
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
2307
2308
if (softc->hw_lro.enable) {
2309
flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
2310
HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
2311
HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
2312
HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
2313
2314
if (softc->hw_lro.is_mode_gro)
2315
flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
2316
else
2317
flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
2318
2319
req.flags = htole32(flags);
2320
2321
req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
2322
HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
2323
HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
2324
2325
req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
2326
req.max_aggs = htole16(softc->hw_lro.max_aggs);
2327
req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
2328
}
2329
2330
req.vnic_id = htole16(softc->vnic_info.id);
2331
2332
return hwrm_send_message(softc, &req, sizeof(req));
2333
}
2334
2335
int
2336
bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
2337
uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
2338
uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
2339
uint32_t *fw_ver)
2340
{
2341
struct hwrm_nvm_find_dir_entry_input req = {0};
2342
struct hwrm_nvm_find_dir_entry_output *resp =
2343
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2344
int rc = 0;
2345
uint32_t old_timeo;
2346
2347
MPASS(ordinal);
2348
2349
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
2350
if (use_index) {
2351
req.enables = htole32(
2352
HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
2353
req.dir_idx = htole16(*index);
2354
}
2355
req.dir_type = htole16(type);
2356
req.dir_ordinal = htole16(*ordinal);
2357
req.dir_ext = htole16(ext);
2358
req.opt_ordinal = search_opt;
2359
2360
BNXT_HWRM_LOCK(softc);
2361
old_timeo = softc->hwrm_cmd_timeo;
2362
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2363
rc = _hwrm_send_message(softc, &req, sizeof(req));
2364
softc->hwrm_cmd_timeo = old_timeo;
2365
if (rc)
2366
goto exit;
2367
2368
if (item_length)
2369
*item_length = le32toh(resp->dir_item_length);
2370
if (data_length)
2371
*data_length = le32toh(resp->dir_data_length);
2372
if (fw_ver)
2373
*fw_ver = le32toh(resp->fw_ver);
2374
*ordinal = le16toh(resp->dir_ordinal);
2375
if (index)
2376
*index = le16toh(resp->dir_idx);
2377
2378
exit:
2379
BNXT_HWRM_UNLOCK(softc);
2380
return (rc);
2381
}
2382
2383
int
2384
bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
2385
uint32_t length, struct iflib_dma_info *data)
2386
{
2387
struct hwrm_nvm_read_input req = {0};
2388
int rc;
2389
uint32_t old_timeo;
2390
2391
if (length > data->idi_size) {
2392
rc = EINVAL;
2393
goto exit;
2394
}
2395
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
2396
req.host_dest_addr = htole64(data->idi_paddr);
2397
req.dir_idx = htole16(index);
2398
req.offset = htole32(offset);
2399
req.len = htole32(length);
2400
BNXT_HWRM_LOCK(softc);
2401
old_timeo = softc->hwrm_cmd_timeo;
2402
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2403
rc = _hwrm_send_message(softc, &req, sizeof(req));
2404
softc->hwrm_cmd_timeo = old_timeo;
2405
BNXT_HWRM_UNLOCK(softc);
2406
if (rc)
2407
goto exit;
2408
bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
2409
2410
goto exit;
2411
2412
exit:
2413
return rc;
2414
}
2415
2416
int
2417
bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
2418
void *data, bool cpyin, uint32_t length)
2419
{
2420
struct hwrm_nvm_modify_input req = {0};
2421
struct iflib_dma_info dma_data;
2422
int rc;
2423
uint32_t old_timeo;
2424
2425
if (length == 0 || !data)
2426
return EINVAL;
2427
rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
2428
BUS_DMA_NOWAIT);
2429
if (rc)
2430
return ENOMEM;
2431
if (cpyin) {
2432
rc = copyin(data, dma_data.idi_vaddr, length);
2433
if (rc)
2434
goto exit;
2435
}
2436
else
2437
memcpy(dma_data.idi_vaddr, data, length);
2438
bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
2439
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2440
2441
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
2442
req.host_src_addr = htole64(dma_data.idi_paddr);
2443
req.dir_idx = htole16(index);
2444
req.offset = htole32(offset);
2445
req.len = htole32(length);
2446
BNXT_HWRM_LOCK(softc);
2447
old_timeo = softc->hwrm_cmd_timeo;
2448
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2449
rc = _hwrm_send_message(softc, &req, sizeof(req));
2450
softc->hwrm_cmd_timeo = old_timeo;
2451
BNXT_HWRM_UNLOCK(softc);
2452
2453
exit:
2454
iflib_dma_free(&dma_data);
2455
return rc;
2456
}
2457
2458
int
2459
bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
2460
uint8_t *selfreset)
2461
{
2462
struct hwrm_fw_reset_input req = {0};
2463
struct hwrm_fw_reset_output *resp =
2464
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2465
int rc;
2466
2467
MPASS(selfreset);
2468
2469
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
2470
req.embedded_proc_type = processor;
2471
req.selfrst_status = *selfreset;
2472
2473
BNXT_HWRM_LOCK(softc);
2474
rc = _hwrm_send_message(softc, &req, sizeof(req));
2475
if (rc)
2476
goto exit;
2477
*selfreset = resp->selfrst_status;
2478
2479
exit:
2480
BNXT_HWRM_UNLOCK(softc);
2481
return rc;
2482
}
2483
2484
int
2485
bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
2486
{
2487
struct hwrm_fw_qstatus_input req = {0};
2488
struct hwrm_fw_qstatus_output *resp =
2489
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2490
int rc;
2491
2492
MPASS(selfreset);
2493
2494
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
2495
req.embedded_proc_type = type;
2496
2497
BNXT_HWRM_LOCK(softc);
2498
rc = _hwrm_send_message(softc, &req, sizeof(req));
2499
if (rc)
2500
goto exit;
2501
*selfreset = resp->selfrst_status;
2502
2503
exit:
2504
BNXT_HWRM_UNLOCK(softc);
2505
return rc;
2506
}
2507
2508
int
2509
bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
2510
uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
2511
uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
2512
uint16_t *index)
2513
{
2514
struct hwrm_nvm_write_input req = {0};
2515
struct hwrm_nvm_write_output *resp =
2516
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2517
struct iflib_dma_info dma_data;
2518
int rc;
2519
uint32_t old_timeo;
2520
2521
if (data_length) {
2522
rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
2523
BUS_DMA_NOWAIT);
2524
if (rc)
2525
return ENOMEM;
2526
if (cpyin) {
2527
rc = copyin(data, dma_data.idi_vaddr, data_length);
2528
if (rc)
2529
goto early_exit;
2530
}
2531
else
2532
memcpy(dma_data.idi_vaddr, data, data_length);
2533
bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
2534
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2535
}
2536
else
2537
dma_data.idi_paddr = 0;
2538
2539
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
2540
2541
req.host_src_addr = htole64(dma_data.idi_paddr);
2542
req.dir_type = htole16(type);
2543
req.dir_ordinal = htole16(ordinal);
2544
req.dir_ext = htole16(ext);
2545
req.dir_attr = htole16(attr);
2546
req.dir_data_length = htole32(data_length);
2547
req.option = htole16(option);
2548
if (keep) {
2549
req.flags =
2550
htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
2551
}
2552
if (item_length)
2553
req.dir_item_length = htole32(*item_length);
2554
2555
BNXT_HWRM_LOCK(softc);
2556
old_timeo = softc->hwrm_cmd_timeo;
2557
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2558
rc = _hwrm_send_message(softc, &req, sizeof(req));
2559
softc->hwrm_cmd_timeo = old_timeo;
2560
if (rc)
2561
goto exit;
2562
if (item_length)
2563
*item_length = le32toh(resp->dir_item_length);
2564
if (index)
2565
*index = le16toh(resp->dir_idx);
2566
2567
exit:
2568
BNXT_HWRM_UNLOCK(softc);
2569
early_exit:
2570
if (data_length)
2571
iflib_dma_free(&dma_data);
2572
return rc;
2573
}
2574
2575
int
2576
bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
2577
{
2578
struct hwrm_nvm_erase_dir_entry_input req = {0};
2579
uint32_t old_timeo;
2580
int rc;
2581
2582
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
2583
req.dir_idx = htole16(index);
2584
BNXT_HWRM_LOCK(softc);
2585
old_timeo = softc->hwrm_cmd_timeo;
2586
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2587
rc = _hwrm_send_message(softc, &req, sizeof(req));
2588
softc->hwrm_cmd_timeo = old_timeo;
2589
BNXT_HWRM_UNLOCK(softc);
2590
return rc;
2591
}
2592
2593
int
2594
bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
2595
uint32_t *entry_length)
2596
{
2597
struct hwrm_nvm_get_dir_info_input req = {0};
2598
struct hwrm_nvm_get_dir_info_output *resp =
2599
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2600
int rc;
2601
uint32_t old_timeo;
2602
2603
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
2604
2605
BNXT_HWRM_LOCK(softc);
2606
old_timeo = softc->hwrm_cmd_timeo;
2607
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2608
rc = _hwrm_send_message(softc, &req, sizeof(req));
2609
softc->hwrm_cmd_timeo = old_timeo;
2610
if (rc)
2611
goto exit;
2612
2613
if (entries)
2614
*entries = le32toh(resp->entries);
2615
if (entry_length)
2616
*entry_length = le32toh(resp->entry_length);
2617
2618
exit:
2619
BNXT_HWRM_UNLOCK(softc);
2620
return rc;
2621
}
2622
2623
int
2624
bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
2625
uint32_t *entry_length, struct iflib_dma_info *dma_data)
2626
{
2627
struct hwrm_nvm_get_dir_entries_input req = {0};
2628
uint32_t ent;
2629
uint32_t ent_len;
2630
int rc;
2631
uint32_t old_timeo;
2632
2633
if (!entries)
2634
entries = &ent;
2635
if (!entry_length)
2636
entry_length = &ent_len;
2637
2638
rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
2639
if (rc)
2640
goto exit;
2641
if (*entries * *entry_length > dma_data->idi_size) {
2642
rc = EINVAL;
2643
goto exit;
2644
}
2645
2646
/*
2647
* TODO: There's a race condition here that could blow up DMA memory...
2648
* we need to allocate the max size, not the currently in use
2649
* size. The command should totally have a max size here.
2650
*/
2651
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
2652
req.host_dest_addr = htole64(dma_data->idi_paddr);
2653
BNXT_HWRM_LOCK(softc);
2654
old_timeo = softc->hwrm_cmd_timeo;
2655
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2656
rc = _hwrm_send_message(softc, &req, sizeof(req));
2657
softc->hwrm_cmd_timeo = old_timeo;
2658
BNXT_HWRM_UNLOCK(softc);
2659
if (rc)
2660
goto exit;
2661
bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
2662
BUS_DMASYNC_POSTWRITE);
2663
2664
exit:
2665
return rc;
2666
}
2667
2668
int
2669
bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
2670
uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
2671
uint32_t *reserved_size, uint32_t *available_size)
2672
{
2673
struct hwrm_nvm_get_dev_info_input req = {0};
2674
struct hwrm_nvm_get_dev_info_output *resp =
2675
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2676
int rc;
2677
uint32_t old_timeo;
2678
2679
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
2680
2681
BNXT_HWRM_LOCK(softc);
2682
old_timeo = softc->hwrm_cmd_timeo;
2683
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2684
rc = _hwrm_send_message(softc, &req, sizeof(req));
2685
softc->hwrm_cmd_timeo = old_timeo;
2686
if (rc)
2687
goto exit;
2688
2689
if (mfg_id)
2690
*mfg_id = le16toh(resp->manufacturer_id);
2691
if (device_id)
2692
*device_id = le16toh(resp->device_id);
2693
if (sector_size)
2694
*sector_size = le32toh(resp->sector_size);
2695
if (nvram_size)
2696
*nvram_size = le32toh(resp->nvram_size);
2697
if (reserved_size)
2698
*reserved_size = le32toh(resp->reserved_size);
2699
if (available_size)
2700
*available_size = le32toh(resp->available_size);
2701
2702
exit:
2703
BNXT_HWRM_UNLOCK(softc);
2704
return rc;
2705
}
2706
2707
int
2708
bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
2709
uint32_t install_type, uint64_t *installed_items, uint8_t *result,
2710
uint8_t *problem_item, uint8_t *reset_required)
2711
{
2712
struct hwrm_nvm_install_update_input req = {0};
2713
struct hwrm_nvm_install_update_output *resp =
2714
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2715
int rc;
2716
uint32_t old_timeo;
2717
2718
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
2719
req.install_type = htole32(install_type);
2720
2721
BNXT_HWRM_LOCK(softc);
2722
old_timeo = softc->hwrm_cmd_timeo;
2723
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2724
rc = _hwrm_send_message(softc, &req, sizeof(req));
2725
softc->hwrm_cmd_timeo = old_timeo;
2726
if (rc)
2727
goto exit;
2728
2729
if (installed_items)
2730
*installed_items = le32toh(resp->installed_items);
2731
if (result)
2732
*result = resp->result;
2733
if (problem_item)
2734
*problem_item = resp->problem_item;
2735
if (reset_required)
2736
*reset_required = resp->reset_required;
2737
2738
exit:
2739
BNXT_HWRM_UNLOCK(softc);
2740
return rc;
2741
}
2742
2743
int
2744
bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
2745
uint16_t ordinal, uint16_t ext)
2746
{
2747
struct hwrm_nvm_verify_update_input req = {0};
2748
uint32_t old_timeo;
2749
int rc;
2750
2751
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
2752
2753
req.dir_type = htole16(type);
2754
req.dir_ordinal = htole16(ordinal);
2755
req.dir_ext = htole16(ext);
2756
2757
BNXT_HWRM_LOCK(softc);
2758
old_timeo = softc->hwrm_cmd_timeo;
2759
softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2760
rc = _hwrm_send_message(softc, &req, sizeof(req));
2761
softc->hwrm_cmd_timeo = old_timeo;
2762
BNXT_HWRM_UNLOCK(softc);
2763
return rc;
2764
}
2765
2766
int
2767
bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
2768
uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
2769
uint16_t *millisecond, uint16_t *zone)
2770
{
2771
struct hwrm_fw_get_time_input req = {0};
2772
struct hwrm_fw_get_time_output *resp =
2773
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2774
int rc;
2775
2776
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
2777
2778
BNXT_HWRM_LOCK(softc);
2779
rc = _hwrm_send_message(softc, &req, sizeof(req));
2780
if (rc)
2781
goto exit;
2782
2783
if (year)
2784
*year = le16toh(resp->year);
2785
if (month)
2786
*month = resp->month;
2787
if (day)
2788
*day = resp->day;
2789
if (hour)
2790
*hour = resp->hour;
2791
if (minute)
2792
*minute = resp->minute;
2793
if (second)
2794
*second = resp->second;
2795
if (millisecond)
2796
*millisecond = le16toh(resp->millisecond);
2797
if (zone)
2798
*zone = le16toh(resp->zone);
2799
2800
exit:
2801
BNXT_HWRM_UNLOCK(softc);
2802
return rc;
2803
}
2804
2805
int
2806
bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
2807
uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
2808
uint16_t millisecond, uint16_t zone)
2809
{
2810
struct hwrm_fw_set_time_input req = {0};
2811
2812
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
2813
2814
req.year = htole16(year);
2815
req.month = month;
2816
req.day = day;
2817
req.hour = hour;
2818
req.minute = minute;
2819
req.second = second;
2820
req.millisecond = htole16(millisecond);
2821
req.zone = htole16(zone);
2822
return hwrm_send_message(softc, &req, sizeof(req));
2823
}
2824
2825
int bnxt_read_sfp_module_eeprom_info(struct bnxt_softc *softc, uint16_t i2c_addr,
2826
uint16_t page_number, uint8_t bank,bool bank_sel_en, uint16_t start_addr,
2827
uint16_t data_length, uint8_t *buf)
2828
{
2829
struct hwrm_port_phy_i2c_read_output *output =
2830
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2831
struct hwrm_port_phy_i2c_read_input req = {0};
2832
int rc = 0, byte_offset = 0;
2833
2834
BNXT_HWRM_LOCK(softc);
2835
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_I2C_READ);
2836
2837
req.i2c_slave_addr = i2c_addr;
2838
req.page_number = htole16(page_number);
2839
req.port_id = htole16(softc->pf.port_id);
2840
do {
2841
uint16_t xfer_size;
2842
2843
xfer_size = min_t(uint16_t, data_length, BNXT_MAX_PHY_I2C_RESP_SIZE);
2844
data_length -= xfer_size;
2845
req.page_offset = htole16(start_addr + byte_offset);
2846
req.data_length = xfer_size;
2847
req.bank_number = bank;
2848
req.enables = htole32((start_addr + byte_offset ?
2849
HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_PAGE_OFFSET : 0) |
2850
(bank_sel_en ?
2851
HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_BANK_NUMBER : 0));
2852
rc = _hwrm_send_message(softc, &req, sizeof(req));
2853
if (!rc)
2854
memcpy(buf + byte_offset, output->data, xfer_size);
2855
byte_offset += xfer_size;
2856
} while (!rc && data_length > 0);
2857
2858
BNXT_HWRM_UNLOCK(softc);
2859
2860
return rc;
2861
}
2862
2863
int
2864
bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
2865
{
2866
struct bnxt_link_info *link_info = &softc->link_info;
2867
struct hwrm_port_phy_qcfg_input req = {0};
2868
struct hwrm_port_phy_qcfg_output *resp =
2869
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2870
int rc = 0;
2871
2872
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
2873
2874
BNXT_HWRM_LOCK(softc);
2875
rc = _hwrm_send_message(softc, &req, sizeof(req));
2876
if (rc)
2877
goto exit;
2878
2879
memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp));
2880
link_info->phy_link_status = resp->link;
2881
link_info->duplex = resp->duplex_cfg;
2882
link_info->auto_mode = resp->auto_mode;
2883
2884
/*
2885
* When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1,
2886
* the advertisement of pause is enabled.
2887
* 1. When the auto_mode is not set to none and this flag is set to 1,
2888
* then the auto_pause bits on this port are being advertised and
2889
* autoneg pause results are being interpreted.
2890
* 2. When the auto_mode is not set to none and this flag is set to 0,
2891
* the pause is forced as indicated in force_pause, and also
2892
* advertised as auto_pause bits, but the autoneg results are not
2893
* interpreted since the pause configuration is being forced.
2894
* 3. When the auto_mode is set to none and this flag is set to 1,
2895
* auto_pause bits should be ignored and should be set to 0.
2896
*/
2897
2898
link_info->flow_ctrl.autoneg = false;
2899
link_info->flow_ctrl.tx = false;
2900
link_info->flow_ctrl.rx = false;
2901
2902
if ((resp->auto_mode) &&
2903
(resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
2904
link_info->flow_ctrl.autoneg = true;
2905
}
2906
2907
if (link_info->flow_ctrl.autoneg) {
2908
if (resp->auto_pause & BNXT_PAUSE_TX)
2909
link_info->flow_ctrl.tx = true;
2910
if (resp->auto_pause & BNXT_PAUSE_RX)
2911
link_info->flow_ctrl.rx = true;
2912
} else {
2913
if (resp->force_pause & BNXT_PAUSE_TX)
2914
link_info->flow_ctrl.tx = true;
2915
if (resp->force_pause & BNXT_PAUSE_RX)
2916
link_info->flow_ctrl.rx = true;
2917
}
2918
2919
link_info->duplex_setting = resp->duplex_cfg;
2920
if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) {
2921
link_info->link_speed = le16toh(resp->link_speed);
2922
if (softc->phy_flags & BNXT_PHY_FL_SPEEDS2)
2923
link_info->active_lanes = resp->active_lanes;
2924
} else {
2925
link_info->link_speed = 0;
2926
link_info->active_lanes = 0;
2927
}
2928
link_info->force_link_speed = le16toh(resp->force_link_speed);
2929
link_info->auto_link_speeds = le16toh(resp->auto_link_speed);
2930
link_info->support_speeds = le16toh(resp->support_speeds);
2931
link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
2932
link_info->preemphasis = le32toh(resp->preemphasis);
2933
link_info->phy_ver[0] = resp->phy_maj;
2934
link_info->phy_ver[1] = resp->phy_min;
2935
link_info->phy_ver[2] = resp->phy_bld;
2936
snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
2937
"%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
2938
link_info->phy_ver[2]);
2939
strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
2940
BNXT_NAME_SIZE);
2941
strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
2942
BNXT_NAME_SIZE);
2943
link_info->media_type = resp->media_type;
2944
link_info->phy_type = resp->phy_type;
2945
link_info->transceiver = resp->xcvr_pkg_type;
2946
link_info->phy_addr = resp->eee_config_phy_addr &
2947
HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
2948
link_info->module_status = resp->module_status;
2949
link_info->support_pam4_speeds = le16toh(resp->support_pam4_speeds);
2950
link_info->auto_pam4_link_speeds = le16toh(resp->auto_pam4_link_speed_mask);
2951
link_info->force_pam4_link_speed = le16toh(resp->force_pam4_link_speed);
2952
2953
if (softc->hwrm_spec_code >= 0x10504)
2954
link_info->active_fec_sig_mode = resp->active_fec_signal_mode;
2955
2956
link_info->support_speeds2 = le16toh(resp->support_speeds2);
2957
link_info->auto_link_speeds2 = le16toh(resp->auto_link_speeds2);
2958
link_info->force_link_speeds2 = le16toh(resp->force_link_speeds2);
2959
2960
exit:
2961
BNXT_HWRM_UNLOCK(softc);
2962
return rc;
2963
}
2964
2965
static bool
2966
bnxt_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp)
2967
{
2968
if (!resp->supported_speeds_auto_mode &&
2969
!resp->supported_speeds_force_mode &&
2970
!resp->supported_pam4_speeds_auto_mode &&
2971
!resp->supported_pam4_speeds_force_mode &&
2972
!resp->supported_speeds2_auto_mode &&
2973
!resp->supported_speeds2_force_mode)
2974
return true;
2975
2976
return false;
2977
}
2978
2979
int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc)
2980
{
2981
struct bnxt_link_info *link_info = &softc->link_info;
2982
struct hwrm_port_phy_qcaps_output *resp =
2983
(void *)softc->hwrm_cmd_resp.idi_vaddr;
2984
struct hwrm_port_phy_qcaps_input req = {};
2985
int rc;
2986
2987
if (softc->hwrm_spec_code < 0x10201)
2988
return 0;
2989
2990
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCAPS);
2991
2992
BNXT_HWRM_LOCK(softc);
2993
rc = _hwrm_send_message(softc, &req, sizeof(req));
2994
if (rc)
2995
goto exit;
2996
2997
softc->phy_flags = resp->flags | (resp->flags2 << 8);
2998
if (resp->flags & HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_EEE_SUPPORTED) {
2999
3000
softc->lpi_tmr_lo = le32toh(resp->tx_lpi_timer_low) &
3001
HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_LOW_MASK;
3002
softc->lpi_tmr_hi = le32toh(resp->valid_tx_lpi_timer_high) &
3003
HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_HIGH_MASK;
3004
}
3005
3006
if (softc->hwrm_spec_code >= 0x10a01) {
3007
if (bnxt_phy_qcaps_no_speed(resp)) {
3008
link_info->phy_state = BNXT_PHY_STATE_DISABLED;
3009
device_printf(softc->dev, "Ethernet link disabled\n");
3010
} else if (link_info->phy_state == BNXT_PHY_STATE_DISABLED) {
3011
link_info->phy_state = BNXT_PHY_STATE_ENABLED;
3012
device_printf(softc->dev, "Ethernet link enabled\n");
3013
/* Phy re-enabled, reprobe the speeds */
3014
link_info->support_auto_speeds = 0;
3015
link_info->support_pam4_auto_speeds = 0;
3016
link_info->support_auto_speeds2 = 0;
3017
}
3018
}
3019
if (resp->supported_speeds_auto_mode)
3020
link_info->support_auto_speeds =
3021
le16toh(resp->supported_speeds_auto_mode);
3022
if (resp->supported_speeds_force_mode)
3023
link_info->support_force_speeds =
3024
le16toh(resp->supported_speeds_force_mode);
3025
if (resp->supported_pam4_speeds_auto_mode)
3026
link_info->support_pam4_auto_speeds =
3027
le16toh(resp->supported_pam4_speeds_auto_mode);
3028
if (resp->supported_pam4_speeds_force_mode)
3029
link_info->support_pam4_force_speeds =
3030
le16toh(resp->supported_pam4_speeds_force_mode);
3031
3032
if (resp->supported_speeds2_auto_mode)
3033
link_info->support_auto_speeds2 =
3034
le16toh(resp->supported_speeds2_auto_mode);
3035
3036
if (resp->supported_speeds2_force_mode)
3037
link_info->support_force_speeds2 =
3038
le16toh(resp->supported_speeds2_force_mode);
3039
3040
exit:
3041
BNXT_HWRM_UNLOCK(softc);
3042
return rc;
3043
}
3044
3045
uint16_t
3046
bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
3047
{
3048
struct hwrm_wol_filter_qcfg_input req = {0};
3049
struct hwrm_wol_filter_qcfg_output *resp =
3050
(void *)softc->hwrm_cmd_resp.idi_vaddr;
3051
uint16_t next_handle = 0;
3052
int rc;
3053
3054
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
3055
req.port_id = htole16(softc->pf.port_id);
3056
req.handle = htole16(handle);
3057
rc = hwrm_send_message(softc, &req, sizeof(req));
3058
if (!rc) {
3059
next_handle = le16toh(resp->next_handle);
3060
if (next_handle != 0) {
3061
if (resp->wol_type ==
3062
HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
3063
softc->wol = 1;
3064
softc->wol_filter_id = resp->wol_filter_id;
3065
}
3066
}
3067
}
3068
return next_handle;
3069
}
3070
3071
int
3072
bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
3073
{
3074
struct hwrm_wol_filter_alloc_input req = {0};
3075
struct hwrm_wol_filter_alloc_output *resp =
3076
(void *)softc->hwrm_cmd_resp.idi_vaddr;
3077
int rc;
3078
3079
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
3080
req.port_id = htole16(softc->pf.port_id);
3081
req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
3082
req.enables =
3083
htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
3084
memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
3085
rc = hwrm_send_message(softc, &req, sizeof(req));
3086
if (!rc)
3087
softc->wol_filter_id = resp->wol_filter_id;
3088
3089
return rc;
3090
}
3091
3092
int
3093
bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
3094
{
3095
struct hwrm_wol_filter_free_input req = {0};
3096
3097
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
3098
req.port_id = htole16(softc->pf.port_id);
3099
req.enables =
3100
htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
3101
req.wol_filter_id = softc->wol_filter_id;
3102
return hwrm_send_message(softc, &req, sizeof(req));
3103
}
3104
3105
static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
3106
uint32_t buf_tmrs, uint16_t flags,
3107
struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
3108
{
3109
req->flags = htole16(flags);
3110
req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
3111
req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
3112
req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
3113
req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
3114
/* Minimum time between 2 interrupts set to buf_tmr x 2 */
3115
req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
3116
req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
3117
req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
3118
}
3119
3120
int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
3121
{
3122
int i, rc = 0;
3123
struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
3124
req_tx = {0}, *req;
3125
uint16_t max_buf, max_buf_irq;
3126
uint16_t buf_tmr, buf_tmr_irq;
3127
uint32_t flags;
3128
3129
bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
3130
HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
3131
bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
3132
HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
3133
3134
/* Each rx completion (2 records) should be DMAed immediately.
3135
* DMA 1/4 of the completion buffers at a time.
3136
*/
3137
max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
3138
/* max_buf must not be zero */
3139
max_buf = clamp_t(uint16_t, max_buf, 1, 63);
3140
max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
3141
buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
3142
/* buf timer set to 1/4 of interrupt timer */
3143
buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
3144
buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
3145
buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
3146
3147
flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
3148
3149
/* RING_IDLE generates more IRQs for lower latency. Enable it only
3150
* if coal_usecs is less than 25 us.
3151
*/
3152
if (softc->rx_coal_usecs < 25)
3153
flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
3154
3155
bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
3156
buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
3157
3158
/* max_buf must not be zero */
3159
max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
3160
max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
3161
buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
3162
/* buf timer set to 1/4 of interrupt timer */
3163
buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
3164
buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
3165
buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
3166
flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
3167
bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
3168
buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
3169
3170
for (i = 0; i < softc->nrxqsets; i++) {
3171
3172
req = &req_rx;
3173
req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
3174
3175
rc = hwrm_send_message(softc, req, sizeof(*req));
3176
if (rc)
3177
break;
3178
}
3179
return rc;
3180
}
3181
3182
void bnxt_hwrm_ring_info_get(struct bnxt_softc *softc, uint8_t ring_type,
3183
uint32_t ring_id, uint32_t *prod, uint32_t *cons)
3184
{
3185
hwrm_dbg_ring_info_get_input_t req = {0};
3186
hwrm_dbg_ring_info_get_output_t *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
3187
int rc = 0;
3188
3189
*prod = *cons = 0xffffffff;
3190
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_DBG_RING_INFO_GET);
3191
req.ring_type = le32toh(ring_type);
3192
req.fw_ring_id = le32toh(ring_id);
3193
rc = hwrm_send_message(softc, &req, sizeof(req));
3194
if (!rc) {
3195
*prod = resp->producer_index;
3196
*cons = resp->consumer_index;
3197
}
3198
3199
return;
3200
}
3201
3202