4 * Copyright (C) Cavium networks Ltd. 2016.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
16 * * Neither the name of Cavium networks nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include "nicvf_plat.h"
40 #define NICVF_MBOX_PF_RESPONSE_DELAY_US (1000)
42 static const char *mbox_message
[NIC_MBOX_MSG_MAX
] = {
43 [NIC_MBOX_MSG_INVALID
] = "NIC_MBOX_MSG_INVALID",
44 [NIC_MBOX_MSG_READY
] = "NIC_MBOX_MSG_READY",
45 [NIC_MBOX_MSG_ACK
] = "NIC_MBOX_MSG_ACK",
46 [NIC_MBOX_MSG_NACK
] = "NIC_MBOX_MSG_ACK",
47 [NIC_MBOX_MSG_QS_CFG
] = "NIC_MBOX_MSG_QS_CFG",
48 [NIC_MBOX_MSG_RQ_CFG
] = "NIC_MBOX_MSG_RQ_CFG",
49 [NIC_MBOX_MSG_SQ_CFG
] = "NIC_MBOX_MSG_SQ_CFG",
50 [NIC_MBOX_MSG_RQ_DROP_CFG
] = "NIC_MBOX_MSG_RQ_DROP_CFG",
51 [NIC_MBOX_MSG_SET_MAC
] = "NIC_MBOX_MSG_SET_MAC",
52 [NIC_MBOX_MSG_SET_MAX_FRS
] = "NIC_MBOX_MSG_SET_MAX_FRS",
53 [NIC_MBOX_MSG_CPI_CFG
] = "NIC_MBOX_MSG_CPI_CFG",
54 [NIC_MBOX_MSG_RSS_SIZE
] = "NIC_MBOX_MSG_RSS_SIZE",
55 [NIC_MBOX_MSG_RSS_CFG
] = "NIC_MBOX_MSG_RSS_CFG",
56 [NIC_MBOX_MSG_RSS_CFG_CONT
] = "NIC_MBOX_MSG_RSS_CFG_CONT",
57 [NIC_MBOX_MSG_RQ_BP_CFG
] = "NIC_MBOX_MSG_RQ_BP_CFG",
58 [NIC_MBOX_MSG_RQ_SW_SYNC
] = "NIC_MBOX_MSG_RQ_SW_SYNC",
59 [NIC_MBOX_MSG_BGX_LINK_CHANGE
] = "NIC_MBOX_MSG_BGX_LINK_CHANGE",
60 [NIC_MBOX_MSG_ALLOC_SQS
] = "NIC_MBOX_MSG_ALLOC_SQS",
61 [NIC_MBOX_MSG_LOOPBACK
] = "NIC_MBOX_MSG_LOOPBACK",
62 [NIC_MBOX_MSG_RESET_STAT_COUNTER
] = "NIC_MBOX_MSG_RESET_STAT_COUNTER",
63 [NIC_MBOX_MSG_CFG_DONE
] = "NIC_MBOX_MSG_CFG_DONE",
64 [NIC_MBOX_MSG_SHUTDOWN
] = "NIC_MBOX_MSG_SHUTDOWN",
65 [NIC_MBOX_MSG_RES_BIT
] = "NIC_MBOX_MSG_RES_BIT",
66 [NIC_MBOX_MSG_RSS_SIZE_RES_BIT
] = "NIC_MBOX_MSG_RSS_SIZE",
67 [NIC_MBOX_MSG_ALLOC_SQS_RES_BIT
] = "NIC_MBOX_MSG_ALLOC_SQS",
70 static inline const char * __attribute__((unused
))
71 nicvf_mbox_msg_str(int msg
)
73 assert(msg
>= 0 && msg
< NIC_MBOX_MSG_MAX
);
74 /* undefined messages */
75 if (mbox_message
[msg
] == NULL
)
77 return mbox_message
[msg
];
81 nicvf_mbox_send_msg_to_pf_raw(struct nicvf
*nic
, struct nic_mbx
*mbx
)
87 mbx_addr
= NIC_VF_PF_MAILBOX_0_1
;
88 mbx_data
= (uint64_t *)mbx
;
89 for (i
= 0; i
< NIC_PF_VF_MAILBOX_SIZE
; i
++) {
90 nicvf_reg_write(nic
, mbx_addr
, *mbx_data
);
92 mbx_addr
+= sizeof(uint64_t);
94 nicvf_mbox_log("msg sent %s (VF%d)",
95 nicvf_mbox_msg_str(mbx
->msg
.msg
), nic
->vf_id
);
99 nicvf_mbox_send_async_msg_to_pf(struct nicvf
*nic
, struct nic_mbx
*mbx
)
101 nicvf_mbox_send_msg_to_pf_raw(nic
, mbx
);
102 /* Messages without ack are racy!*/
103 nicvf_delay_us(NICVF_MBOX_PF_RESPONSE_DELAY_US
);
107 nicvf_mbox_send_msg_to_pf(struct nicvf
*nic
, struct nic_mbx
*mbx
)
113 for (i
= 0; i
< retry
; i
++) {
114 nic
->pf_acked
= false;
115 nic
->pf_nacked
= false;
118 nicvf_mbox_send_msg_to_pf_raw(nic
, mbx
);
119 /* Give some time to get PF response */
120 nicvf_delay_us(NICVF_MBOX_PF_RESPONSE_DELAY_US
);
121 timeout
= NIC_MBOX_MSG_TIMEOUT
;
122 while (timeout
> 0) {
123 /* Periodic poll happens from nicvf_interrupt() */
131 nicvf_delay_us(NICVF_MBOX_PF_RESPONSE_DELAY_US
);
134 nicvf_log_error("PF didn't ack to msg 0x%02x %s VF%d (%d/%d)",
135 mbx
->msg
.msg
, nicvf_mbox_msg_str(mbx
->msg
.msg
),
136 nic
->vf_id
, i
, retry
);
143 nicvf_handle_mbx_intr(struct nicvf
*nic
)
146 uint64_t *mbx_data
= (uint64_t *)&mbx
;
147 uint64_t mbx_addr
= NIC_VF_PF_MAILBOX_0_1
;
150 for (i
= 0; i
< NIC_PF_VF_MAILBOX_SIZE
; i
++) {
151 *mbx_data
= nicvf_reg_read(nic
, mbx_addr
);
153 mbx_addr
+= sizeof(uint64_t);
156 /* Overwrite the message so we won't receive it again */
157 nicvf_reg_write(nic
, NIC_VF_PF_MAILBOX_0_1
, 0x0);
159 nicvf_mbox_log("msg received id=0x%hhx %s (VF%d)", mbx
.msg
.msg
,
160 nicvf_mbox_msg_str(mbx
.msg
.msg
), nic
->vf_id
);
162 switch (mbx
.msg
.msg
) {
163 case NIC_MBOX_MSG_READY
:
164 nic
->vf_id
= mbx
.nic_cfg
.vf_id
& 0x7F;
165 nic
->tns_mode
= mbx
.nic_cfg
.tns_mode
& 0x7F;
166 nic
->node
= mbx
.nic_cfg
.node_id
;
167 nic
->sqs_mode
= mbx
.nic_cfg
.sqs_mode
;
168 nic
->loopback_supported
= mbx
.nic_cfg
.loopback_supported
;
169 ether_addr_copy((struct ether_addr
*)mbx
.nic_cfg
.mac_addr
,
170 (struct ether_addr
*)nic
->mac_addr
);
171 nic
->pf_acked
= true;
173 case NIC_MBOX_MSG_ACK
:
174 nic
->pf_acked
= true;
176 case NIC_MBOX_MSG_NACK
:
177 nic
->pf_nacked
= true;
179 case NIC_MBOX_MSG_RSS_SIZE_RES_BIT
:
180 nic
->rss_info
.rss_size
= mbx
.rss_size
.ind_tbl_size
;
181 nic
->pf_acked
= true;
183 case NIC_MBOX_MSG_BGX_LINK_CHANGE
:
184 nic
->link_up
= mbx
.link_status
.link_up
;
185 nic
->duplex
= mbx
.link_status
.duplex
;
186 nic
->speed
= mbx
.link_status
.speed
;
187 nic
->pf_acked
= true;
189 case NIC_MBOX_MSG_ALLOC_SQS_RES_BIT
:
191 if (mbx
.sqs_alloc
.qs_count
!= nic
->sqs_count
) {
192 nicvf_log_error("Received %" PRIu8
"/%" PRIu8
194 mbx
.sqs_alloc
.qs_count
,
198 for (i
= 0; i
< mbx
.sqs_alloc
.qs_count
; i
++) {
199 if (mbx
.sqs_alloc
.svf
[i
] != nic
->snicvf
[i
]->vf_id
) {
200 nicvf_log_error("Received secondary qset[%zu] "
201 "ID %" PRIu8
" expected %"
202 PRIu8
, i
, mbx
.sqs_alloc
.svf
[i
],
203 nic
->snicvf
[i
]->vf_id
);
207 nic
->pf_acked
= true;
210 nicvf_log_error("Invalid message from PF, msg_id=0x%hhx %s",
211 mbx
.msg
.msg
, nicvf_mbox_msg_str(mbx
.msg
.msg
));
220 * Checks if VF is able to communicate with PF
221 * and also gets the VNIC number this VF is associated to.
224 nicvf_mbox_check_pf_ready(struct nicvf
*nic
)
226 struct nic_mbx mbx
= { .msg
= {.msg
= NIC_MBOX_MSG_READY
} };
228 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
232 nicvf_mbox_set_mac_addr(struct nicvf
*nic
,
233 const uint8_t mac
[NICVF_MAC_ADDR_SIZE
])
235 struct nic_mbx mbx
= { .msg
= {0} };
238 mbx
.msg
.msg
= NIC_MBOX_MSG_SET_MAC
;
239 mbx
.mac
.vf_id
= nic
->vf_id
;
240 for (i
= 0; i
< 6; i
++)
241 mbx
.mac
.mac_addr
[i
] = mac
[i
];
243 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
247 nicvf_mbox_config_cpi(struct nicvf
*nic
, uint32_t qcnt
)
249 struct nic_mbx mbx
= { .msg
= { 0 } };
251 mbx
.msg
.msg
= NIC_MBOX_MSG_CPI_CFG
;
252 mbx
.cpi_cfg
.vf_id
= nic
->vf_id
;
253 mbx
.cpi_cfg
.cpi_alg
= nic
->cpi_alg
;
254 mbx
.cpi_cfg
.rq_cnt
= qcnt
;
256 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
260 nicvf_mbox_get_rss_size(struct nicvf
*nic
)
262 struct nic_mbx mbx
= { .msg
= { 0 } };
264 mbx
.msg
.msg
= NIC_MBOX_MSG_RSS_SIZE
;
265 mbx
.rss_size
.vf_id
= nic
->vf_id
;
267 /* Result will be stored in nic->rss_info.rss_size */
268 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
272 nicvf_mbox_config_rss(struct nicvf
*nic
)
274 struct nic_mbx mbx
= { .msg
= { 0 } };
275 struct nicvf_rss_reta_info
*rss
= &nic
->rss_info
;
276 size_t tot_len
= rss
->rss_size
;
281 mbx
.rss_cfg
.vf_id
= nic
->vf_id
;
282 mbx
.rss_cfg
.hash_bits
= rss
->hash_bits
;
283 mbx
.rss_cfg
.tbl_len
= 0;
284 mbx
.rss_cfg
.tbl_offset
= 0;
286 while (cur_idx
< tot_len
) {
287 cur_len
= nicvf_min(tot_len
- cur_idx
,
288 (size_t)RSS_IND_TBL_LEN_PER_MBX_MSG
);
289 mbx
.msg
.msg
= (cur_idx
> 0) ?
290 NIC_MBOX_MSG_RSS_CFG_CONT
: NIC_MBOX_MSG_RSS_CFG
;
291 mbx
.rss_cfg
.tbl_offset
= cur_idx
;
292 mbx
.rss_cfg
.tbl_len
= cur_len
;
293 for (i
= 0; i
< cur_len
; i
++)
294 mbx
.rss_cfg
.ind_tbl
[i
] = rss
->ind_tbl
[cur_idx
++];
296 if (nicvf_mbox_send_msg_to_pf(nic
, &mbx
))
297 return NICVF_ERR_RSS_TBL_UPDATE
;
304 nicvf_mbox_rq_config(struct nicvf
*nic
, uint16_t qidx
,
305 struct pf_rq_cfg
*pf_rq_cfg
)
307 struct nic_mbx mbx
= { .msg
= { 0 } };
309 mbx
.msg
.msg
= NIC_MBOX_MSG_RQ_CFG
;
310 mbx
.rq
.qs_num
= nic
->vf_id
;
311 mbx
.rq
.rq_num
= qidx
;
312 mbx
.rq
.cfg
= pf_rq_cfg
->value
;
313 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
317 nicvf_mbox_sq_config(struct nicvf
*nic
, uint16_t qidx
)
319 struct nic_mbx mbx
= { .msg
= { 0 } };
321 mbx
.msg
.msg
= NIC_MBOX_MSG_SQ_CFG
;
322 mbx
.sq
.qs_num
= nic
->vf_id
;
323 mbx
.sq
.sq_num
= qidx
;
324 mbx
.sq
.sqs_mode
= nic
->sqs_mode
;
325 mbx
.sq
.cfg
= (nic
->vf_id
<< 3) | qidx
;
326 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
330 nicvf_mbox_qset_config(struct nicvf
*nic
, struct pf_qs_cfg
*qs_cfg
)
332 struct nic_mbx mbx
= { .msg
= { 0 } };
334 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
337 /* Send a mailbox msg to PF to config Qset */
338 mbx
.msg
.msg
= NIC_MBOX_MSG_QS_CFG
;
339 mbx
.qs
.num
= nic
->vf_id
;
340 mbx
.qs
.sqs_count
= nic
->sqs_count
;
341 mbx
.qs
.cfg
= qs_cfg
->value
;
342 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
346 nicvf_mbox_request_sqs(struct nicvf
*nic
)
348 struct nic_mbx mbx
= { .msg
= { 0 } };
352 assert(nic
->sqs_count
> 0);
353 assert(nic
->sqs_count
<= MAX_SQS_PER_VF
);
355 mbx
.sqs_alloc
.msg
= NIC_MBOX_MSG_ALLOC_SQS
;
356 mbx
.sqs_alloc
.spec
= 1;
357 mbx
.sqs_alloc
.qs_count
= nic
->sqs_count
;
359 /* Set no of Rx/Tx queues in each of the SQsets */
360 for (i
= 0; i
< nic
->sqs_count
; i
++)
361 mbx
.sqs_alloc
.svf
[i
] = nic
->snicvf
[i
]->vf_id
;
363 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
367 nicvf_mbox_rq_drop_config(struct nicvf
*nic
, uint16_t qidx
, bool enable
)
369 struct nic_mbx mbx
= { .msg
= { 0 } };
370 struct pf_rq_drop_cfg
*drop_cfg
;
372 /* Enable CQ drop to reserve sufficient CQEs for all tx packets */
373 mbx
.msg
.msg
= NIC_MBOX_MSG_RQ_DROP_CFG
;
374 mbx
.rq
.qs_num
= nic
->vf_id
;
375 mbx
.rq
.rq_num
= qidx
;
376 drop_cfg
= (struct pf_rq_drop_cfg
*)&mbx
.rq
.cfg
;
379 drop_cfg
->cq_red
= 1;
380 drop_cfg
->cq_drop
= 2;
382 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
386 nicvf_mbox_update_hw_max_frs(struct nicvf
*nic
, uint16_t mtu
)
388 struct nic_mbx mbx
= { .msg
= { 0 } };
390 mbx
.msg
.msg
= NIC_MBOX_MSG_SET_MAX_FRS
;
391 mbx
.frs
.max_frs
= mtu
;
392 mbx
.frs
.vf_id
= nic
->vf_id
;
393 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
397 nicvf_mbox_rq_sync(struct nicvf
*nic
)
399 struct nic_mbx mbx
= { .msg
= { 0 } };
401 /* Make sure all packets in the pipeline are written back into mem */
402 mbx
.msg
.msg
= NIC_MBOX_MSG_RQ_SW_SYNC
;
404 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
408 nicvf_mbox_rq_bp_config(struct nicvf
*nic
, uint16_t qidx
, bool enable
)
410 struct nic_mbx mbx
= { .msg
= { 0 } };
412 mbx
.msg
.msg
= NIC_MBOX_MSG_RQ_BP_CFG
;
413 mbx
.rq
.qs_num
= nic
->vf_id
;
414 mbx
.rq
.rq_num
= qidx
;
417 mbx
.rq
.cfg
= (1ULL << 63) | (1ULL << 62) | (nic
->vf_id
<< 0);
418 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
422 nicvf_mbox_loopback_config(struct nicvf
*nic
, bool enable
)
424 struct nic_mbx mbx
= { .msg
= { 0 } };
426 mbx
.lbk
.msg
= NIC_MBOX_MSG_LOOPBACK
;
427 mbx
.lbk
.vf_id
= nic
->vf_id
;
428 mbx
.lbk
.enable
= enable
;
429 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
433 nicvf_mbox_reset_stat_counters(struct nicvf
*nic
, uint16_t rx_stat_mask
,
434 uint8_t tx_stat_mask
, uint16_t rq_stat_mask
,
435 uint16_t sq_stat_mask
)
437 struct nic_mbx mbx
= { .msg
= { 0 } };
439 mbx
.reset_stat
.msg
= NIC_MBOX_MSG_RESET_STAT_COUNTER
;
440 mbx
.reset_stat
.rx_stat_mask
= rx_stat_mask
;
441 mbx
.reset_stat
.tx_stat_mask
= tx_stat_mask
;
442 mbx
.reset_stat
.rq_stat_mask
= rq_stat_mask
;
443 mbx
.reset_stat
.sq_stat_mask
= sq_stat_mask
;
444 return nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
448 nicvf_mbox_shutdown(struct nicvf
*nic
)
450 struct nic_mbx mbx
= { .msg
= { 0 } };
452 mbx
.msg
.msg
= NIC_MBOX_MSG_SHUTDOWN
;
453 nicvf_mbox_send_msg_to_pf(nic
, &mbx
);
457 nicvf_mbox_cfg_done(struct nicvf
*nic
)
459 struct nic_mbx mbx
= { .msg
= { 0 } };
461 mbx
.msg
.msg
= NIC_MBOX_MSG_CFG_DONE
;
462 nicvf_mbox_send_async_msg_to_pf(nic
, &mbx
);