1 /* 2 * Copyright (c) 2012-2015 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include "efx.h" 32 #include "efx_impl.h" 33 34 #if EFSYS_OPT_HUNTINGTON 35 36 #if EFSYS_OPT_BIST 37 38 __checkReturn efx_rc_t 39 hunt_bist_enable_offline( 40 __in efx_nic_t *enp) 41 { 42 efx_rc_t rc; 43 44 if ((rc = efx_mcdi_bist_enable_offline(enp)) != 0) 45 goto fail1; 46 47 return (0); 48 49 fail1: 50 EFSYS_PROBE1(fail1, efx_rc_t, rc); 51 52 return (rc); 53 } 54 55 __checkReturn efx_rc_t 56 hunt_bist_start( 57 __in efx_nic_t *enp, 58 __in efx_bist_type_t type) 59 { 60 efx_rc_t rc; 61 62 if ((rc = efx_mcdi_bist_start(enp, type)) != 0) 63 goto fail1; 64 65 return (0); 66 67 fail1: 68 EFSYS_PROBE1(fail1, efx_rc_t, rc); 69 70 return (rc); 71 } 72 73 __checkReturn efx_rc_t 74 hunt_bist_poll( 75 __in efx_nic_t *enp, 76 __in efx_bist_type_t type, 77 __out efx_bist_result_t *resultp, 78 __out_opt __drv_when(count > 0, __notnull) 79 uint32_t *value_maskp, 80 __out_ecount_opt(count) __drv_when(count > 0, __notnull) 81 unsigned long *valuesp, 82 __in size_t count) 83 { 84 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 85 efx_mcdi_req_t req; 86 uint8_t payload[MAX(MC_CMD_POLL_BIST_IN_LEN, 87 MCDI_CTL_SDU_LEN_MAX)]; 88 uint32_t value_mask = 0; 89 uint32_t result; 90 efx_rc_t rc; 91 _NOTE(ARGUNUSED(type)) 92 93 (void) memset(payload, 0, sizeof (payload)); 94 req.emr_cmd = MC_CMD_POLL_BIST; 95 req.emr_in_buf = payload; 96 req.emr_in_length = MC_CMD_POLL_BIST_IN_LEN; 97 req.emr_out_buf = payload; 98 req.emr_out_length = MCDI_CTL_SDU_LEN_MAX; 99 100 efx_mcdi_execute(enp, &req); 101 102 if (req.emr_rc != 0) { 103 rc = req.emr_rc; 104 goto fail1; 105 } 106 107 if (req.emr_out_length_used < MC_CMD_POLL_BIST_OUT_RESULT_OFST + 4) { 108 rc = EMSGSIZE; 109 goto fail2; 110 } 111 112 if (count > 0) 113 (void) memset(valuesp, '\0', count * sizeof (unsigned long)); 114 115 result = MCDI_OUT_DWORD(req, POLL_BIST_OUT_RESULT); 116 117 if (result == MC_CMD_POLL_BIST_FAILED && 118 req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MEM_LEN && 119 count > EFX_BIST_MEM_ECC_FATAL) { 120 if (valuesp != NULL) { 121 valuesp[EFX_BIST_MEM_TEST] = 122 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_TEST); 123 valuesp[EFX_BIST_MEM_ADDR] = 124 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ADDR); 125 valuesp[EFX_BIST_MEM_BUS] = 126 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_BUS); 127 valuesp[EFX_BIST_MEM_EXPECT] = 128 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_EXPECT); 129 valuesp[EFX_BIST_MEM_ACTUAL] = 130 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ACTUAL); 131 valuesp[EFX_BIST_MEM_ECC] = 132 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC); 133 valuesp[EFX_BIST_MEM_ECC_PARITY] = 134 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC_PARITY); 135 valuesp[EFX_BIST_MEM_ECC_FATAL] = 136 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC_FATAL); 137 } 138 value_mask |= (1 << EFX_BIST_MEM_TEST) | 139 (1 << EFX_BIST_MEM_ADDR) | 140 (1 << EFX_BIST_MEM_BUS) | 141 (1 << EFX_BIST_MEM_EXPECT) | 142 (1 << EFX_BIST_MEM_ACTUAL) | 143 (1 << EFX_BIST_MEM_ECC) | 144 (1 << EFX_BIST_MEM_ECC_PARITY) | 145 (1 << EFX_BIST_MEM_ECC_FATAL); 146 } else if (result == MC_CMD_POLL_BIST_FAILED && 147 encp->enc_phy_type == EFX_PHY_XFI_FARMI && 148 req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MRSFP_LEN && 149 count > EFX_BIST_FAULT_CODE) { 150 if (valuesp != NULL) 151 valuesp[EFX_BIST_FAULT_CODE] = 152 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MRSFP_TEST); 153 value_mask |= 1 << EFX_BIST_FAULT_CODE; 154 } 155 156 if (value_maskp != NULL) 157 *value_maskp = value_mask; 158 159 EFSYS_ASSERT(resultp != NULL); 160 if (result == MC_CMD_POLL_BIST_RUNNING) 161 *resultp = EFX_BIST_RESULT_RUNNING; 162 else if (result == MC_CMD_POLL_BIST_PASSED) 163 *resultp = EFX_BIST_RESULT_PASSED; 164 else 165 *resultp = EFX_BIST_RESULT_FAILED; 166 167 return (0); 168 169 fail2: 170 EFSYS_PROBE(fail2); 171 fail1: 172 EFSYS_PROBE1(fail1, efx_rc_t, rc); 173 174 return (rc); 175 } 176 177 void 178 hunt_bist_stop( 179 __in efx_nic_t *enp, 180 __in efx_bist_type_t type) 181 { 182 /* There is no way to stop BIST on Huntinton. */ 183 _NOTE(ARGUNUSED(enp, type)) 184 } 185 186 #endif /* EFSYS_OPT_BIST */ 187 188 #endif /* EFSYS_OPT_HUNTINGTON */