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