.. | .. |
---|
| 1 | +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) |
---|
1 | 2 | /* QLogic qed NIC Driver |
---|
2 | 3 | * Copyright (c) 2015-2017 QLogic Corporation |
---|
3 | | - * |
---|
4 | | - * This software is available to you under a choice of one of two |
---|
5 | | - * licenses. You may choose to be licensed under the terms of the GNU |
---|
6 | | - * General Public License (GPL) Version 2, available from the file |
---|
7 | | - * COPYING in the main directory of this source tree, or the |
---|
8 | | - * OpenIB.org BSD license below: |
---|
9 | | - * |
---|
10 | | - * Redistribution and use in source and binary forms, with or |
---|
11 | | - * without modification, are permitted provided that the following |
---|
12 | | - * conditions are met: |
---|
13 | | - * |
---|
14 | | - * - Redistributions of source code must retain the above |
---|
15 | | - * copyright notice, this list of conditions and the following |
---|
16 | | - * disclaimer. |
---|
17 | | - * |
---|
18 | | - * - Redistributions in binary form must reproduce the above |
---|
19 | | - * copyright notice, this list of conditions and the following |
---|
20 | | - * disclaimer in the documentation and /or other materials |
---|
21 | | - * provided with the distribution. |
---|
22 | | - * |
---|
23 | | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
---|
24 | | - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
---|
25 | | - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
---|
26 | | - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
---|
27 | | - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
---|
28 | | - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
---|
29 | | - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
---|
30 | | - * SOFTWARE. |
---|
| 4 | + * Copyright (c) 2019-2020 Marvell International Ltd. |
---|
31 | 5 | */ |
---|
32 | 6 | |
---|
33 | 7 | #include <linux/types.h> |
---|
.. | .. |
---|
392 | 366 | } |
---|
393 | 367 | |
---|
394 | 368 | /* DMAE */ |
---|
| 369 | +#define QED_DMAE_FLAGS_IS_SET(params, flag) \ |
---|
| 370 | + ((params) != NULL && GET_FIELD((params)->flags, QED_DMAE_PARAMS_##flag)) |
---|
| 371 | + |
---|
395 | 372 | static void qed_dmae_opcode(struct qed_hwfn *p_hwfn, |
---|
396 | 373 | const u8 is_src_type_grc, |
---|
397 | 374 | const u8 is_dst_type_grc, |
---|
398 | 375 | struct qed_dmae_params *p_params) |
---|
399 | 376 | { |
---|
| 377 | + u8 src_pfid, dst_pfid, port_id; |
---|
400 | 378 | u16 opcode_b = 0; |
---|
401 | 379 | u32 opcode = 0; |
---|
402 | 380 | |
---|
.. | .. |
---|
404 | 382 | * 0- The source is the PCIe |
---|
405 | 383 | * 1- The source is the GRC. |
---|
406 | 384 | */ |
---|
407 | | - opcode |= (is_src_type_grc ? DMAE_CMD_SRC_MASK_GRC |
---|
408 | | - : DMAE_CMD_SRC_MASK_PCIE) << |
---|
409 | | - DMAE_CMD_SRC_SHIFT; |
---|
410 | | - opcode |= ((p_hwfn->rel_pf_id & DMAE_CMD_SRC_PF_ID_MASK) << |
---|
411 | | - DMAE_CMD_SRC_PF_ID_SHIFT); |
---|
| 385 | + SET_FIELD(opcode, DMAE_CMD_SRC, |
---|
| 386 | + (is_src_type_grc ? dmae_cmd_src_grc : dmae_cmd_src_pcie)); |
---|
| 387 | + src_pfid = QED_DMAE_FLAGS_IS_SET(p_params, SRC_PF_VALID) ? |
---|
| 388 | + p_params->src_pfid : p_hwfn->rel_pf_id; |
---|
| 389 | + SET_FIELD(opcode, DMAE_CMD_SRC_PF_ID, src_pfid); |
---|
412 | 390 | |
---|
413 | 391 | /* The destination of the DMA can be: 0-None 1-PCIe 2-GRC 3-None */ |
---|
414 | | - opcode |= (is_dst_type_grc ? DMAE_CMD_DST_MASK_GRC |
---|
415 | | - : DMAE_CMD_DST_MASK_PCIE) << |
---|
416 | | - DMAE_CMD_DST_SHIFT; |
---|
417 | | - opcode |= ((p_hwfn->rel_pf_id & DMAE_CMD_DST_PF_ID_MASK) << |
---|
418 | | - DMAE_CMD_DST_PF_ID_SHIFT); |
---|
| 392 | + SET_FIELD(opcode, DMAE_CMD_DST, |
---|
| 393 | + (is_dst_type_grc ? dmae_cmd_dst_grc : dmae_cmd_dst_pcie)); |
---|
| 394 | + dst_pfid = QED_DMAE_FLAGS_IS_SET(p_params, DST_PF_VALID) ? |
---|
| 395 | + p_params->dst_pfid : p_hwfn->rel_pf_id; |
---|
| 396 | + SET_FIELD(opcode, DMAE_CMD_DST_PF_ID, dst_pfid); |
---|
| 397 | + |
---|
419 | 398 | |
---|
420 | 399 | /* Whether to write a completion word to the completion destination: |
---|
421 | 400 | * 0-Do not write a completion word |
---|
422 | 401 | * 1-Write the completion word |
---|
423 | 402 | */ |
---|
424 | | - opcode |= (DMAE_CMD_COMP_WORD_EN_MASK << DMAE_CMD_COMP_WORD_EN_SHIFT); |
---|
425 | | - opcode |= (DMAE_CMD_SRC_ADDR_RESET_MASK << |
---|
426 | | - DMAE_CMD_SRC_ADDR_RESET_SHIFT); |
---|
| 403 | + SET_FIELD(opcode, DMAE_CMD_COMP_WORD_EN, 1); |
---|
| 404 | + SET_FIELD(opcode, DMAE_CMD_SRC_ADDR_RESET, 1); |
---|
427 | 405 | |
---|
428 | | - if (p_params->flags & QED_DMAE_FLAG_COMPLETION_DST) |
---|
429 | | - opcode |= (1 << DMAE_CMD_COMP_FUNC_SHIFT); |
---|
| 406 | + if (QED_DMAE_FLAGS_IS_SET(p_params, COMPLETION_DST)) |
---|
| 407 | + SET_FIELD(opcode, DMAE_CMD_COMP_FUNC, 1); |
---|
430 | 408 | |
---|
431 | | - opcode |= (DMAE_CMD_ENDIANITY << DMAE_CMD_ENDIANITY_MODE_SHIFT); |
---|
| 409 | + /* swapping mode 3 - big endian */ |
---|
| 410 | + SET_FIELD(opcode, DMAE_CMD_ENDIANITY_MODE, DMAE_CMD_ENDIANITY); |
---|
432 | 411 | |
---|
433 | | - opcode |= ((p_hwfn->port_id) << DMAE_CMD_PORT_ID_SHIFT); |
---|
| 412 | + port_id = (QED_DMAE_FLAGS_IS_SET(p_params, PORT_VALID)) ? |
---|
| 413 | + p_params->port_id : p_hwfn->port_id; |
---|
| 414 | + SET_FIELD(opcode, DMAE_CMD_PORT_ID, port_id); |
---|
434 | 415 | |
---|
435 | 416 | /* reset source address in next go */ |
---|
436 | | - opcode |= (DMAE_CMD_SRC_ADDR_RESET_MASK << |
---|
437 | | - DMAE_CMD_SRC_ADDR_RESET_SHIFT); |
---|
| 417 | + SET_FIELD(opcode, DMAE_CMD_SRC_ADDR_RESET, 1); |
---|
438 | 418 | |
---|
439 | 419 | /* reset dest address in next go */ |
---|
440 | | - opcode |= (DMAE_CMD_DST_ADDR_RESET_MASK << |
---|
441 | | - DMAE_CMD_DST_ADDR_RESET_SHIFT); |
---|
| 420 | + SET_FIELD(opcode, DMAE_CMD_DST_ADDR_RESET, 1); |
---|
442 | 421 | |
---|
443 | 422 | /* SRC/DST VFID: all 1's - pf, otherwise VF id */ |
---|
444 | | - if (p_params->flags & QED_DMAE_FLAG_VF_SRC) { |
---|
445 | | - opcode |= 1 << DMAE_CMD_SRC_VF_ID_VALID_SHIFT; |
---|
446 | | - opcode_b |= p_params->src_vfid << DMAE_CMD_SRC_VF_ID_SHIFT; |
---|
| 423 | + if (QED_DMAE_FLAGS_IS_SET(p_params, SRC_VF_VALID)) { |
---|
| 424 | + SET_FIELD(opcode, DMAE_CMD_SRC_VF_ID_VALID, 1); |
---|
| 425 | + SET_FIELD(opcode_b, DMAE_CMD_SRC_VF_ID, p_params->src_vfid); |
---|
447 | 426 | } else { |
---|
448 | | - opcode_b |= DMAE_CMD_SRC_VF_ID_MASK << |
---|
449 | | - DMAE_CMD_SRC_VF_ID_SHIFT; |
---|
| 427 | + SET_FIELD(opcode_b, DMAE_CMD_SRC_VF_ID, 0xFF); |
---|
450 | 428 | } |
---|
451 | | - |
---|
452 | | - if (p_params->flags & QED_DMAE_FLAG_VF_DST) { |
---|
453 | | - opcode |= 1 << DMAE_CMD_DST_VF_ID_VALID_SHIFT; |
---|
454 | | - opcode_b |= p_params->dst_vfid << DMAE_CMD_DST_VF_ID_SHIFT; |
---|
| 429 | + if (QED_DMAE_FLAGS_IS_SET(p_params, DST_VF_VALID)) { |
---|
| 430 | + SET_FIELD(opcode, DMAE_CMD_DST_VF_ID_VALID, 1); |
---|
| 431 | + SET_FIELD(opcode_b, DMAE_CMD_DST_VF_ID, p_params->dst_vfid); |
---|
455 | 432 | } else { |
---|
456 | | - opcode_b |= DMAE_CMD_DST_VF_ID_MASK << DMAE_CMD_DST_VF_ID_SHIFT; |
---|
| 433 | + SET_FIELD(opcode_b, DMAE_CMD_DST_VF_ID, 0xFF); |
---|
457 | 434 | } |
---|
458 | 435 | |
---|
459 | 436 | p_hwfn->dmae_info.p_dmae_cmd->opcode = cpu_to_le32(opcode); |
---|
.. | .. |
---|
703 | 680 | int qed_status = 0; |
---|
704 | 681 | u32 offset = 0; |
---|
705 | 682 | |
---|
| 683 | + if (p_hwfn->cdev->recov_in_prog) { |
---|
| 684 | + DP_VERBOSE(p_hwfn, |
---|
| 685 | + NETIF_MSG_HW, |
---|
| 686 | + "Recovery is in progress. Avoid DMAE transaction [{src: addr 0x%llx, type %d}, {dst: addr 0x%llx, type %d}, size %d].\n", |
---|
| 687 | + src_addr, src_type, dst_addr, dst_type, |
---|
| 688 | + size_in_dwords); |
---|
| 689 | + |
---|
| 690 | + /* Let the flow complete w/o any error handling */ |
---|
| 691 | + return 0; |
---|
| 692 | + } |
---|
| 693 | + |
---|
706 | 694 | qed_dmae_opcode(p_hwfn, |
---|
707 | 695 | (src_type == QED_DMAE_ADDRESS_GRC), |
---|
708 | 696 | (dst_type == QED_DMAE_ADDRESS_GRC), |
---|
.. | .. |
---|
722 | 710 | for (i = 0; i <= cnt_split; i++) { |
---|
723 | 711 | offset = length_limit * i; |
---|
724 | 712 | |
---|
725 | | - if (!(p_params->flags & QED_DMAE_FLAG_RW_REPL_SRC)) { |
---|
| 713 | + if (!QED_DMAE_FLAGS_IS_SET(p_params, RW_REPL_SRC)) { |
---|
726 | 714 | if (src_type == QED_DMAE_ADDRESS_GRC) |
---|
727 | 715 | src_addr_split = src_addr + offset; |
---|
728 | 716 | else |
---|
.. | .. |
---|
748 | 736 | dst_type, |
---|
749 | 737 | length_cur); |
---|
750 | 738 | if (qed_status) { |
---|
751 | | - DP_NOTICE(p_hwfn, |
---|
752 | | - "qed_dmae_execute_sub_operation Failed with error 0x%x. source_addr 0x%llx, destination addr 0x%llx, size_in_dwords 0x%x\n", |
---|
753 | | - qed_status, src_addr, dst_addr, length_cur); |
---|
| 739 | + qed_hw_err_notify(p_hwfn, p_ptt, QED_HW_ERR_DMAE_FAIL, |
---|
| 740 | + "qed_dmae_execute_sub_operation Failed with error 0x%x. source_addr 0x%llx, destination addr 0x%llx, size_in_dwords 0x%x\n", |
---|
| 741 | + qed_status, src_addr, |
---|
| 742 | + dst_addr, length_cur); |
---|
754 | 743 | break; |
---|
755 | 744 | } |
---|
756 | 745 | } |
---|
.. | .. |
---|
760 | 749 | |
---|
761 | 750 | int qed_dmae_host2grc(struct qed_hwfn *p_hwfn, |
---|
762 | 751 | struct qed_ptt *p_ptt, |
---|
763 | | - u64 source_addr, u32 grc_addr, u32 size_in_dwords, u32 flags) |
---|
| 752 | + u64 source_addr, u32 grc_addr, u32 size_in_dwords, |
---|
| 753 | + struct qed_dmae_params *p_params) |
---|
764 | 754 | { |
---|
765 | 755 | u32 grc_addr_in_dw = grc_addr / sizeof(u32); |
---|
766 | | - struct qed_dmae_params params; |
---|
767 | 756 | int rc; |
---|
768 | 757 | |
---|
769 | | - memset(¶ms, 0, sizeof(struct qed_dmae_params)); |
---|
770 | | - params.flags = flags; |
---|
771 | 758 | |
---|
772 | 759 | mutex_lock(&p_hwfn->dmae_info.mutex); |
---|
773 | 760 | |
---|
.. | .. |
---|
775 | 762 | grc_addr_in_dw, |
---|
776 | 763 | QED_DMAE_ADDRESS_HOST_VIRT, |
---|
777 | 764 | QED_DMAE_ADDRESS_GRC, |
---|
778 | | - size_in_dwords, ¶ms); |
---|
| 765 | + size_in_dwords, p_params); |
---|
779 | 766 | |
---|
780 | 767 | mutex_unlock(&p_hwfn->dmae_info.mutex); |
---|
781 | 768 | |
---|
.. | .. |
---|
785 | 772 | int qed_dmae_grc2host(struct qed_hwfn *p_hwfn, |
---|
786 | 773 | struct qed_ptt *p_ptt, |
---|
787 | 774 | u32 grc_addr, |
---|
788 | | - dma_addr_t dest_addr, u32 size_in_dwords, u32 flags) |
---|
| 775 | + dma_addr_t dest_addr, u32 size_in_dwords, |
---|
| 776 | + struct qed_dmae_params *p_params) |
---|
789 | 777 | { |
---|
790 | 778 | u32 grc_addr_in_dw = grc_addr / sizeof(u32); |
---|
791 | | - struct qed_dmae_params params; |
---|
792 | 779 | int rc; |
---|
793 | 780 | |
---|
794 | | - memset(¶ms, 0, sizeof(struct qed_dmae_params)); |
---|
795 | | - params.flags = flags; |
---|
796 | 781 | |
---|
797 | 782 | mutex_lock(&p_hwfn->dmae_info.mutex); |
---|
798 | 783 | |
---|
799 | 784 | rc = qed_dmae_execute_command(p_hwfn, p_ptt, grc_addr_in_dw, |
---|
800 | 785 | dest_addr, QED_DMAE_ADDRESS_GRC, |
---|
801 | 786 | QED_DMAE_ADDRESS_HOST_VIRT, |
---|
802 | | - size_in_dwords, ¶ms); |
---|
| 787 | + size_in_dwords, p_params); |
---|
803 | 788 | |
---|
804 | 789 | mutex_unlock(&p_hwfn->dmae_info.mutex); |
---|
805 | 790 | |
---|
.. | .. |
---|
827 | 812 | return rc; |
---|
828 | 813 | } |
---|
829 | 814 | |
---|
| 815 | +void qed_hw_err_notify(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, |
---|
| 816 | + enum qed_hw_err_type err_type, const char *fmt, ...) |
---|
| 817 | +{ |
---|
| 818 | + char buf[QED_HW_ERR_MAX_STR_SIZE]; |
---|
| 819 | + va_list vl; |
---|
| 820 | + int len; |
---|
| 821 | + |
---|
| 822 | + if (fmt) { |
---|
| 823 | + va_start(vl, fmt); |
---|
| 824 | + len = vsnprintf(buf, QED_HW_ERR_MAX_STR_SIZE, fmt, vl); |
---|
| 825 | + va_end(vl); |
---|
| 826 | + |
---|
| 827 | + if (len > QED_HW_ERR_MAX_STR_SIZE - 1) |
---|
| 828 | + len = QED_HW_ERR_MAX_STR_SIZE - 1; |
---|
| 829 | + |
---|
| 830 | + DP_NOTICE(p_hwfn, "%s", buf); |
---|
| 831 | + } |
---|
| 832 | + |
---|
| 833 | + /* Fan failure cannot be masked by handling of another HW error */ |
---|
| 834 | + if (p_hwfn->cdev->recov_in_prog && |
---|
| 835 | + err_type != QED_HW_ERR_FAN_FAIL) { |
---|
| 836 | + DP_VERBOSE(p_hwfn, |
---|
| 837 | + NETIF_MSG_DRV, |
---|
| 838 | + "Recovery is in progress. Avoid notifying about HW error %d.\n", |
---|
| 839 | + err_type); |
---|
| 840 | + return; |
---|
| 841 | + } |
---|
| 842 | + |
---|
| 843 | + qed_hw_error_occurred(p_hwfn, err_type); |
---|
| 844 | + |
---|
| 845 | + if (fmt) |
---|
| 846 | + qed_mcp_send_raw_debug_data(p_hwfn, p_ptt, buf, len); |
---|
| 847 | +} |
---|
| 848 | + |
---|
830 | 849 | int qed_dmae_sanity(struct qed_hwfn *p_hwfn, |
---|
831 | 850 | struct qed_ptt *p_ptt, const char *phase) |
---|
832 | 851 | { |
---|
833 | 852 | u32 size = PAGE_SIZE / 2, val; |
---|
834 | | - struct qed_dmae_params params; |
---|
835 | 853 | int rc = 0; |
---|
836 | 854 | dma_addr_t p_phys; |
---|
837 | 855 | void *p_virt; |
---|
.. | .. |
---|
864 | 882 | (u64)p_phys, |
---|
865 | 883 | p_virt, (u64)(p_phys + size), (u8 *)p_virt + size, size); |
---|
866 | 884 | |
---|
867 | | - memset(¶ms, 0, sizeof(params)); |
---|
868 | 885 | rc = qed_dmae_host2host(p_hwfn, p_ptt, p_phys, p_phys + size, |
---|
869 | | - size / 4 /* size_in_dwords */, ¶ms); |
---|
| 886 | + size / 4, NULL); |
---|
870 | 887 | if (rc) { |
---|
871 | 888 | DP_NOTICE(p_hwfn, |
---|
872 | 889 | "DMAE sanity [%s]: qed_dmae_host2host() failed. rc = %d.\n", |
---|