hunt_phy.c revision 300840
1/*- 2 * Copyright (c) 2012-2016 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 <sys/cdefs.h> 32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/hunt_phy.c 300840 2016-05-27 11:44:40Z arybchik $"); 33 34#include "efx.h" 35#include "efx_impl.h" 36 37#if EFSYS_OPT_HUNTINGTON 38 39#if EFSYS_OPT_BIST 40 41 __checkReturn efx_rc_t 42hunt_bist_enable_offline( 43 __in efx_nic_t *enp) 44{ 45 efx_rc_t rc; 46 47 if ((rc = efx_mcdi_bist_enable_offline(enp)) != 0) 48 goto fail1; 49 50 return (0); 51 52fail1: 53 EFSYS_PROBE1(fail1, efx_rc_t, rc); 54 55 return (rc); 56} 57 58 __checkReturn efx_rc_t 59hunt_bist_start( 60 __in efx_nic_t *enp, 61 __in efx_bist_type_t type) 62{ 63 efx_rc_t rc; 64 65 if ((rc = efx_mcdi_bist_start(enp, type)) != 0) 66 goto fail1; 67 68 return (0); 69 70fail1: 71 EFSYS_PROBE1(fail1, efx_rc_t, rc); 72 73 return (rc); 74} 75 76 __checkReturn efx_rc_t 77hunt_bist_poll( 78 __in efx_nic_t *enp, 79 __in efx_bist_type_t type, 80 __out efx_bist_result_t *resultp, 81 __out_opt __drv_when(count > 0, __notnull) 82 uint32_t *value_maskp, 83 __out_ecount_opt(count) __drv_when(count > 0, __notnull) 84 unsigned long *valuesp, 85 __in size_t count) 86{ 87 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 88 efx_mcdi_req_t req; 89 uint8_t payload[MAX(MC_CMD_POLL_BIST_IN_LEN, 90 MCDI_CTL_SDU_LEN_MAX)]; 91 uint32_t value_mask = 0; 92 uint32_t result; 93 efx_rc_t rc; 94 95 _NOTE(ARGUNUSED(type)) 96 97 (void) memset(payload, 0, sizeof (payload)); 98 req.emr_cmd = MC_CMD_POLL_BIST; 99 req.emr_in_buf = payload; 100 req.emr_in_length = MC_CMD_POLL_BIST_IN_LEN; 101 req.emr_out_buf = payload; 102 req.emr_out_length = MCDI_CTL_SDU_LEN_MAX; 103 104 efx_mcdi_execute(enp, &req); 105 106 if (req.emr_rc != 0) { 107 rc = req.emr_rc; 108 goto fail1; 109 } 110 111 if (req.emr_out_length_used < MC_CMD_POLL_BIST_OUT_RESULT_OFST + 4) { 112 rc = EMSGSIZE; 113 goto fail2; 114 } 115 116 if (count > 0) 117 (void) memset(valuesp, '\0', count * sizeof (unsigned long)); 118 119 result = MCDI_OUT_DWORD(req, POLL_BIST_OUT_RESULT); 120 121 if (result == MC_CMD_POLL_BIST_FAILED && 122 req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MEM_LEN && 123 count > EFX_BIST_MEM_ECC_FATAL) { 124 if (valuesp != NULL) { 125 valuesp[EFX_BIST_MEM_TEST] = 126 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_TEST); 127 valuesp[EFX_BIST_MEM_ADDR] = 128 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ADDR); 129 valuesp[EFX_BIST_MEM_BUS] = 130 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_BUS); 131 valuesp[EFX_BIST_MEM_EXPECT] = 132 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_EXPECT); 133 valuesp[EFX_BIST_MEM_ACTUAL] = 134 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ACTUAL); 135 valuesp[EFX_BIST_MEM_ECC] = 136 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC); 137 valuesp[EFX_BIST_MEM_ECC_PARITY] = 138 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC_PARITY); 139 valuesp[EFX_BIST_MEM_ECC_FATAL] = 140 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC_FATAL); 141 } 142 value_mask |= (1 << EFX_BIST_MEM_TEST) | 143 (1 << EFX_BIST_MEM_ADDR) | 144 (1 << EFX_BIST_MEM_BUS) | 145 (1 << EFX_BIST_MEM_EXPECT) | 146 (1 << EFX_BIST_MEM_ACTUAL) | 147 (1 << EFX_BIST_MEM_ECC) | 148 (1 << EFX_BIST_MEM_ECC_PARITY) | 149 (1 << EFX_BIST_MEM_ECC_FATAL); 150 } else if (result == MC_CMD_POLL_BIST_FAILED && 151 encp->enc_phy_type == EFX_PHY_XFI_FARMI && 152 req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MRSFP_LEN && 153 count > EFX_BIST_FAULT_CODE) { 154 if (valuesp != NULL) 155 valuesp[EFX_BIST_FAULT_CODE] = 156 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MRSFP_TEST); 157 value_mask |= 1 << EFX_BIST_FAULT_CODE; 158 } 159 160 if (value_maskp != NULL) 161 *value_maskp = value_mask; 162 163 EFSYS_ASSERT(resultp != NULL); 164 if (result == MC_CMD_POLL_BIST_RUNNING) 165 *resultp = EFX_BIST_RESULT_RUNNING; 166 else if (result == MC_CMD_POLL_BIST_PASSED) 167 *resultp = EFX_BIST_RESULT_PASSED; 168 else 169 *resultp = EFX_BIST_RESULT_FAILED; 170 171 return (0); 172 173fail2: 174 EFSYS_PROBE(fail2); 175fail1: 176 EFSYS_PROBE1(fail1, efx_rc_t, rc); 177 178 return (rc); 179} 180 181 void 182hunt_bist_stop( 183 __in efx_nic_t *enp, 184 __in efx_bist_type_t type) 185{ 186 /* There is no way to stop BIST on Huntinton. */ 187 _NOTE(ARGUNUSED(enp, type)) 188} 189 190#endif /* EFSYS_OPT_BIST */ 191 192#endif /* EFSYS_OPT_HUNTINGTON */ 193