1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 3 * Copyright(c) 2010-2017 Intel Corporation 4 */ 5 6 #include "ngbe_type.h" 7 8 #include "ngbe_mbx.h" 9 10 /** 11 * ngbe_read_mbx - Reads a message from the mailbox 12 * @hw: pointer to the HW structure 13 * @msg: The message buffer 14 * @size: Length of buffer 15 * @mbx_id: id of mailbox to read 16 * 17 * returns 0 if it successfully read message from buffer 18 **/ 19 s32 ngbe_read_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 20 { 21 struct ngbe_mbx_info *mbx = &hw->mbx; 22 s32 ret_val = NGBE_ERR_MBX; 23 24 /* limit read to size of mailbox */ 25 if (size > mbx->size) 26 size = mbx->size; 27 28 if (mbx->read) 29 ret_val = mbx->read(hw, msg, size, mbx_id); 30 31 return ret_val; 32 } 33 34 /** 35 * ngbe_write_mbx - Write a message to the mailbox 36 * @hw: pointer to the HW structure 37 * @msg: The message buffer 38 * @size: Length of buffer 39 * @mbx_id: id of mailbox to write 40 * 41 * returns 0 if it successfully copied message into the buffer 42 **/ 43 s32 ngbe_write_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 44 { 45 struct ngbe_mbx_info *mbx = &hw->mbx; 46 s32 ret_val = 0; 47 48 if (size > mbx->size) { 49 ret_val = NGBE_ERR_MBX; 50 DEBUGOUT("Invalid mailbox message size %d", size); 51 } else if (mbx->write) { 52 ret_val = mbx->write(hw, msg, size, mbx_id); 53 } 54 55 return ret_val; 56 } 57 58 /** 59 * ngbe_check_for_msg - checks to see if someone sent us mail 60 * @hw: pointer to the HW structure 61 * @mbx_id: id of mailbox to check 62 * 63 * returns 0 if the Status bit was found or else ERR_MBX 64 **/ 65 s32 ngbe_check_for_msg(struct ngbe_hw *hw, u16 mbx_id) 66 { 67 struct ngbe_mbx_info *mbx = &hw->mbx; 68 s32 ret_val = NGBE_ERR_MBX; 69 70 if (mbx->check_for_msg) 71 ret_val = mbx->check_for_msg(hw, mbx_id); 72 73 return ret_val; 74 } 75 76 /** 77 * ngbe_check_for_ack - checks to see if someone sent us ACK 78 * @hw: pointer to the HW structure 79 * @mbx_id: id of mailbox to check 80 * 81 * returns 0 if the Status bit was found or else ERR_MBX 82 **/ 83 s32 ngbe_check_for_ack(struct ngbe_hw *hw, u16 mbx_id) 84 { 85 struct ngbe_mbx_info *mbx = &hw->mbx; 86 s32 ret_val = NGBE_ERR_MBX; 87 88 if (mbx->check_for_ack) 89 ret_val = mbx->check_for_ack(hw, mbx_id); 90 91 return ret_val; 92 } 93 94 /** 95 * ngbe_check_for_rst - checks to see if other side has reset 96 * @hw: pointer to the HW structure 97 * @mbx_id: id of mailbox to check 98 * 99 * returns 0 if the Status bit was found or else ERR_MBX 100 **/ 101 s32 ngbe_check_for_rst(struct ngbe_hw *hw, u16 mbx_id) 102 { 103 struct ngbe_mbx_info *mbx = &hw->mbx; 104 s32 ret_val = NGBE_ERR_MBX; 105 106 if (mbx->check_for_rst) 107 ret_val = mbx->check_for_rst(hw, mbx_id); 108 109 return ret_val; 110 } 111 112 /** 113 * ngbe_poll_for_msg - Wait for message notification 114 * @hw: pointer to the HW structure 115 * @mbx_id: id of mailbox to write 116 * 117 * returns SUCCESS if it successfully received a message notification 118 **/ 119 STATIC s32 ngbe_poll_for_msg(struct ngbe_hw *hw, u16 mbx_id) 120 { 121 struct ngbe_mbx_info *mbx = &hw->mbx; 122 int countdown = mbx->timeout; 123 124 if (!countdown || !mbx->check_for_msg) 125 goto out; 126 127 while (countdown && mbx->check_for_msg(hw, mbx_id)) { 128 countdown--; 129 if (!countdown) 130 break; 131 usec_delay(mbx->usec_delay); 132 } 133 134 if (countdown == 0) 135 DEBUGOUT("Polling for VF%d mailbox message timedout", mbx_id); 136 137 out: 138 return countdown ? 0 : NGBE_ERR_MBX; 139 } 140 141 /** 142 * ngbe_poll_for_ack - Wait for message acknowledgment 143 * @hw: pointer to the HW structure 144 * @mbx_id: id of mailbox to write 145 * 146 * returns SUCCESS if it successfully received a message acknowledgment 147 **/ 148 STATIC s32 ngbe_poll_for_ack(struct ngbe_hw *hw, u16 mbx_id) 149 { 150 struct ngbe_mbx_info *mbx = &hw->mbx; 151 int countdown = mbx->timeout; 152 153 if (!countdown || !mbx->check_for_ack) 154 goto out; 155 156 while (countdown && mbx->check_for_ack(hw, mbx_id)) { 157 countdown--; 158 if (!countdown) 159 break; 160 usec_delay(mbx->usec_delay); 161 } 162 163 if (countdown == 0) 164 DEBUGOUT("Polling for VF%d mailbox ack timedout", mbx_id); 165 166 out: 167 return countdown ? 0 : NGBE_ERR_MBX; 168 } 169 170 /** 171 * ngbe_read_posted_mbx - Wait for message notification and receive message 172 * @hw: pointer to the HW structure 173 * @msg: The message buffer 174 * @size: Length of buffer 175 * @mbx_id: id of mailbox to write 176 * 177 * returns SUCCESS if it successfully received a message notification and 178 * copied it into the receive buffer. 179 **/ 180 s32 ngbe_read_posted_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 181 { 182 struct ngbe_mbx_info *mbx = &hw->mbx; 183 s32 ret_val = NGBE_ERR_MBX; 184 185 if (!mbx->read) 186 goto out; 187 188 ret_val = ngbe_poll_for_msg(hw, mbx_id); 189 190 /* if ack received read message, otherwise we timed out */ 191 if (!ret_val) 192 ret_val = mbx->read(hw, msg, size, mbx_id); 193 out: 194 return ret_val; 195 } 196 197 /** 198 * ngbe_write_posted_mbx - Write a message to the mailbox, wait for ack 199 * @hw: pointer to the HW structure 200 * @msg: The message buffer 201 * @size: Length of buffer 202 * @mbx_id: id of mailbox to write 203 * 204 * returns SUCCESS if it successfully copied message into the buffer and 205 * received an ack to that message within delay * timeout period 206 **/ 207 s32 ngbe_write_posted_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, 208 u16 mbx_id) 209 { 210 struct ngbe_mbx_info *mbx = &hw->mbx; 211 s32 ret_val = NGBE_ERR_MBX; 212 213 /* exit if either we can't write or there isn't a defined timeout */ 214 if (!mbx->write || !mbx->timeout) 215 goto out; 216 217 /* send msg */ 218 ret_val = mbx->write(hw, msg, size, mbx_id); 219 220 /* if msg sent wait until we receive an ack */ 221 if (!ret_val) 222 ret_val = ngbe_poll_for_ack(hw, mbx_id); 223 out: 224 return ret_val; 225 } 226 227 /** 228 * ngbe_read_v2p_mailbox - read v2p mailbox 229 * @hw: pointer to the HW structure 230 * 231 * This function is used to read the v2p mailbox without losing the read to 232 * clear status bits. 233 **/ 234 STATIC u32 ngbe_read_v2p_mailbox(struct ngbe_hw *hw) 235 { 236 u32 v2p_mailbox = rd32(hw, NGBE_VFMBCTL); 237 238 v2p_mailbox |= hw->mbx.v2p_mailbox; 239 hw->mbx.v2p_mailbox |= v2p_mailbox & NGBE_VFMBCTL_R2C_BITS; 240 241 return v2p_mailbox; 242 } 243 244 /** 245 * ngbe_check_for_bit_vf - Determine if a status bit was set 246 * @hw: pointer to the HW structure 247 * @mask: bitmask for bits to be tested and cleared 248 * 249 * This function is used to check for the read to clear bits within 250 * the V2P mailbox. 251 **/ 252 STATIC s32 ngbe_check_for_bit_vf(struct ngbe_hw *hw, u32 mask) 253 { 254 u32 v2p_mailbox = ngbe_read_v2p_mailbox(hw); 255 s32 ret_val = NGBE_ERR_MBX; 256 257 if (v2p_mailbox & mask) 258 ret_val = 0; 259 260 hw->mbx.v2p_mailbox &= ~mask; 261 262 return ret_val; 263 } 264 265 /** 266 * ngbe_check_for_msg_vf - checks to see if the PF has sent mail 267 * @hw: pointer to the HW structure 268 * @mbx_id: id of mailbox to check 269 * 270 * returns SUCCESS if the PF has set the Status bit or else ERR_MBX 271 **/ 272 s32 ngbe_check_for_msg_vf(struct ngbe_hw *hw, u16 mbx_id) 273 { 274 s32 ret_val = NGBE_ERR_MBX; 275 276 UNREFERENCED_PARAMETER(mbx_id); 277 278 if (!ngbe_check_for_bit_vf(hw, NGBE_VFMBCTL_PFSTS)) { 279 ret_val = 0; 280 hw->mbx.stats.reqs++; 281 } 282 283 return ret_val; 284 } 285 286 /** 287 * ngbe_check_for_ack_vf - checks to see if the PF has ACK'd 288 * @hw: pointer to the HW structure 289 * @mbx_id: id of mailbox to check 290 * 291 * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX 292 **/ 293 s32 ngbe_check_for_ack_vf(struct ngbe_hw *hw, u16 mbx_id) 294 { 295 s32 ret_val = NGBE_ERR_MBX; 296 297 UNREFERENCED_PARAMETER(mbx_id); 298 299 if (!ngbe_check_for_bit_vf(hw, NGBE_VFMBCTL_PFACK)) { 300 ret_val = 0; 301 hw->mbx.stats.acks++; 302 } 303 304 return ret_val; 305 } 306 307 /** 308 * ngbe_check_for_rst_vf - checks to see if the PF has reset 309 * @hw: pointer to the HW structure 310 * @mbx_id: id of mailbox to check 311 * 312 * returns true if the PF has set the reset done bit or else false 313 **/ 314 s32 ngbe_check_for_rst_vf(struct ngbe_hw *hw, u16 mbx_id) 315 { 316 s32 ret_val = NGBE_ERR_MBX; 317 318 UNREFERENCED_PARAMETER(mbx_id); 319 320 if (!ngbe_check_for_bit_vf(hw, (NGBE_VFMBCTL_RSTD | 321 NGBE_VFMBCTL_RSTI))) { 322 ret_val = 0; 323 hw->mbx.stats.rsts++; 324 } 325 326 return ret_val; 327 } 328 329 /** 330 * ngbe_obtain_mbx_lock_vf - obtain mailbox lock 331 * @hw: pointer to the HW structure 332 * 333 * return SUCCESS if we obtained the mailbox lock 334 **/ 335 STATIC s32 ngbe_obtain_mbx_lock_vf(struct ngbe_hw *hw) 336 { 337 s32 ret_val = NGBE_ERR_MBX; 338 339 /* Take ownership of the buffer */ 340 wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_VFU); 341 342 /* reserve mailbox for vf use */ 343 if (ngbe_read_v2p_mailbox(hw) & NGBE_VFMBCTL_VFU) 344 ret_val = 0; 345 346 return ret_val; 347 } 348 349 /** 350 * ngbe_write_mbx_vf - Write a message to the mailbox 351 * @hw: pointer to the HW structure 352 * @msg: The message buffer 353 * @size: Length of buffer 354 * @mbx_id: id of mailbox to write 355 * 356 * returns SUCCESS if it successfully copied message into the buffer 357 **/ 358 s32 ngbe_write_mbx_vf(struct ngbe_hw *hw, u32 *msg, u16 size, 359 u16 mbx_id) 360 { 361 s32 ret_val; 362 u16 i; 363 364 UNREFERENCED_PARAMETER(mbx_id); 365 366 /* lock the mailbox to prevent pf/vf race condition */ 367 ret_val = ngbe_obtain_mbx_lock_vf(hw); 368 if (ret_val) 369 goto out_no_write; 370 371 /* flush msg and acks as we are overwriting the message buffer */ 372 ngbe_check_for_msg_vf(hw, 0); 373 ngbe_check_for_ack_vf(hw, 0); 374 375 /* copy the caller specified message to the mailbox memory buffer */ 376 for (i = 0; i < size; i++) 377 wr32a(hw, NGBE_VFMBX, i, msg[i]); 378 379 /* update stats */ 380 hw->mbx.stats.msgs_tx++; 381 382 /* Drop VFU and interrupt the PF to tell it a message has been sent */ 383 wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_REQ); 384 385 out_no_write: 386 return ret_val; 387 } 388 389 /** 390 * ngbe_read_mbx_vf - Reads a message from the inbox intended for vf 391 * @hw: pointer to the HW structure 392 * @msg: The message buffer 393 * @size: Length of buffer 394 * @mbx_id: id of mailbox to read 395 * 396 * returns SUCCESS if it successfully read message from buffer 397 **/ 398 s32 ngbe_read_mbx_vf(struct ngbe_hw *hw, u32 *msg, u16 size, 399 u16 mbx_id) 400 { 401 s32 ret_val = 0; 402 u16 i; 403 404 UNREFERENCED_PARAMETER(mbx_id); 405 406 /* lock the mailbox to prevent pf/vf race condition */ 407 ret_val = ngbe_obtain_mbx_lock_vf(hw); 408 if (ret_val) 409 goto out_no_read; 410 411 /* copy the message from the mailbox memory buffer */ 412 for (i = 0; i < size; i++) 413 msg[i] = rd32a(hw, NGBE_VFMBX, i); 414 415 /* Acknowledge receipt and release mailbox, then we're done */ 416 wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_ACK); 417 418 /* update stats */ 419 hw->mbx.stats.msgs_rx++; 420 421 out_no_read: 422 return ret_val; 423 } 424 425 /** 426 * ngbe_init_mbx_params_vf - set initial values for vf mailbox 427 * @hw: pointer to the HW structure 428 * 429 * Initializes the hw->mbx struct to correct values for vf mailbox 430 */ 431 void ngbe_init_mbx_params_vf(struct ngbe_hw *hw) 432 { 433 struct ngbe_mbx_info *mbx = &hw->mbx; 434 435 /* start mailbox as timed out and let the reset_hw call set the timeout 436 * value to begin communications 437 */ 438 mbx->timeout = 0; 439 mbx->usec_delay = NGBE_VF_MBX_INIT_DELAY; 440 441 mbx->size = NGBE_P2VMBX_SIZE; 442 443 mbx->stats.msgs_tx = 0; 444 mbx->stats.msgs_rx = 0; 445 mbx->stats.reqs = 0; 446 mbx->stats.acks = 0; 447 mbx->stats.rsts = 0; 448 } 449 450 STATIC s32 ngbe_check_for_bit_pf(struct ngbe_hw *hw, u32 mask) 451 { 452 u32 mbvficr = rd32(hw, NGBE_MBVFICR); 453 s32 ret_val = NGBE_ERR_MBX; 454 455 if (mbvficr & mask) { 456 ret_val = 0; 457 wr32(hw, NGBE_MBVFICR, mask); 458 } 459 460 return ret_val; 461 } 462 463 /** 464 * ngbe_check_for_msg_pf - checks to see if the VF has sent mail 465 * @hw: pointer to the HW structure 466 * @vf_number: the VF index 467 * 468 * returns 0 if the VF has set the Status bit or else ERR_MBX 469 **/ 470 s32 ngbe_check_for_msg_pf(struct ngbe_hw *hw, u16 vf_number) 471 { 472 s32 ret_val = NGBE_ERR_MBX; 473 u32 vf_bit = vf_number; 474 475 if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFREQ_VF1 << vf_bit)) { 476 ret_val = 0; 477 hw->mbx.stats.reqs++; 478 } 479 480 return ret_val; 481 } 482 483 /** 484 * ngbe_check_for_ack_pf - checks to see if the VF has ACKed 485 * @hw: pointer to the HW structure 486 * @vf_number: the VF index 487 * 488 * returns 0 if the VF has set the Status bit or else ERR_MBX 489 **/ 490 s32 ngbe_check_for_ack_pf(struct ngbe_hw *hw, u16 vf_number) 491 { 492 s32 ret_val = NGBE_ERR_MBX; 493 u32 vf_bit = vf_number; 494 495 if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFACK_VF1 << vf_bit)) { 496 ret_val = 0; 497 hw->mbx.stats.acks++; 498 } 499 500 return ret_val; 501 } 502 503 /** 504 * ngbe_check_for_rst_pf - checks to see if the VF has reset 505 * @hw: pointer to the HW structure 506 * @vf_number: the VF index 507 * 508 * returns 0 if the VF has set the Status bit or else ERR_MBX 509 **/ 510 s32 ngbe_check_for_rst_pf(struct ngbe_hw *hw, u16 vf_number) 511 { 512 u32 vflre = 0; 513 s32 ret_val = NGBE_ERR_MBX; 514 515 vflre = rd32(hw, NGBE_FLRVFE); 516 if (vflre & (1 << vf_number)) { 517 ret_val = 0; 518 wr32(hw, NGBE_FLRVFEC, (1 << vf_number)); 519 hw->mbx.stats.rsts++; 520 } 521 522 return ret_val; 523 } 524 525 /** 526 * ngbe_obtain_mbx_lock_pf - obtain mailbox lock 527 * @hw: pointer to the HW structure 528 * @vf_number: the VF index 529 * 530 * return 0 if we obtained the mailbox lock 531 **/ 532 STATIC s32 ngbe_obtain_mbx_lock_pf(struct ngbe_hw *hw, u16 vf_number) 533 { 534 s32 ret_val = NGBE_ERR_MBX; 535 u32 p2v_mailbox; 536 537 /* Take ownership of the buffer */ 538 wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_PFU); 539 540 /* reserve mailbox for vf use */ 541 p2v_mailbox = rd32(hw, NGBE_MBCTL(vf_number)); 542 if (p2v_mailbox & NGBE_MBCTL_PFU) 543 ret_val = 0; 544 else 545 DEBUGOUT("Failed to obtain mailbox lock for VF%d", vf_number); 546 547 548 return ret_val; 549 } 550 551 /** 552 * ngbe_write_mbx_pf - Places a message in the mailbox 553 * @hw: pointer to the HW structure 554 * @msg: The message buffer 555 * @size: Length of buffer 556 * @vf_number: the VF index 557 * 558 * returns 0 if it successfully copied message into the buffer 559 **/ 560 s32 ngbe_write_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number) 561 { 562 s32 ret_val; 563 u16 i; 564 565 /* lock the mailbox to prevent pf/vf race condition */ 566 ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number); 567 if (ret_val) 568 goto out_no_write; 569 570 /* flush msg and acks as we are overwriting the message buffer */ 571 ngbe_check_for_msg_pf(hw, vf_number); 572 ngbe_check_for_ack_pf(hw, vf_number); 573 574 /* copy the caller specified message to the mailbox memory buffer */ 575 for (i = 0; i < size; i++) 576 wr32a(hw, NGBE_MBMEM(vf_number), i, msg[i]); 577 578 /* Interrupt VF to tell it a message has been sent and release buffer*/ 579 wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_STS); 580 581 /* update stats */ 582 hw->mbx.stats.msgs_tx++; 583 584 out_no_write: 585 return ret_val; 586 } 587 588 /** 589 * ngbe_read_mbx_pf - Read a message from the mailbox 590 * @hw: pointer to the HW structure 591 * @msg: The message buffer 592 * @size: Length of buffer 593 * @vf_number: the VF index 594 * 595 * This function copies a message from the mailbox buffer to the caller's 596 * memory buffer. The presumption is that the caller knows that there was 597 * a message due to a VF request so no polling for message is needed. 598 **/ 599 s32 ngbe_read_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number) 600 { 601 s32 ret_val; 602 u16 i; 603 604 /* lock the mailbox to prevent pf/vf race condition */ 605 ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number); 606 if (ret_val) 607 goto out_no_read; 608 609 /* copy the message to the mailbox memory buffer */ 610 for (i = 0; i < size; i++) 611 msg[i] = rd32a(hw, NGBE_MBMEM(vf_number), i); 612 613 /* Acknowledge the message and release buffer */ 614 wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_ACK); 615 616 /* update stats */ 617 hw->mbx.stats.msgs_rx++; 618 619 out_no_read: 620 return ret_val; 621 } 622 623 /** 624 * ngbe_init_mbx_params_pf - set initial values for pf mailbox 625 * @hw: pointer to the HW structure 626 * 627 * Initializes the hw->mbx struct to correct values for pf mailbox 628 */ 629 void ngbe_init_mbx_params_pf(struct ngbe_hw *hw) 630 { 631 struct ngbe_mbx_info *mbx = &hw->mbx; 632 633 mbx->timeout = 0; 634 mbx->usec_delay = 0; 635 636 mbx->size = NGBE_P2VMBX_SIZE; 637 638 mbx->stats.msgs_tx = 0; 639 mbx->stats.msgs_rx = 0; 640 mbx->stats.reqs = 0; 641 mbx->stats.acks = 0; 642 mbx->stats.rsts = 0; 643 } 644