1283514Sarybchik/*- 2300607Sarybchik * Copyright (c) 2012-2016 Solarflare Communications Inc. 3283514Sarybchik * All rights reserved. 4283514Sarybchik * 5283514Sarybchik * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions are met: 7283514Sarybchik * 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9283514Sarybchik * this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11283514Sarybchik * this list of conditions and the following disclaimer in the documentation 12283514Sarybchik * and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * The views and conclusions contained in the software and documentation are 27283514Sarybchik * those of the authors and should not be interpreted as representing official 28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29283514Sarybchik */ 30283514Sarybchik 31283514Sarybchik#include <sys/cdefs.h> 32283514Sarybchik__FBSDID("$FreeBSD: releng/11.0/sys/dev/sfxge/common/hunt_phy.c 300840 2016-05-27 11:44:40Z arybchik $"); 33283514Sarybchik 34283514Sarybchik#include "efx.h" 35283514Sarybchik#include "efx_impl.h" 36283514Sarybchik 37283514Sarybchik#if EFSYS_OPT_HUNTINGTON 38283514Sarybchik 39283514Sarybchik#if EFSYS_OPT_BIST 40283514Sarybchik 41291436Sarybchik __checkReturn efx_rc_t 42283514Sarybchikhunt_bist_enable_offline( 43283514Sarybchik __in efx_nic_t *enp) 44283514Sarybchik{ 45291436Sarybchik efx_rc_t rc; 46283514Sarybchik 47283514Sarybchik if ((rc = efx_mcdi_bist_enable_offline(enp)) != 0) 48283514Sarybchik goto fail1; 49283514Sarybchik 50283514Sarybchik return (0); 51283514Sarybchik 52283514Sarybchikfail1: 53291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 54283514Sarybchik 55283514Sarybchik return (rc); 56283514Sarybchik} 57283514Sarybchik 58291436Sarybchik __checkReturn efx_rc_t 59283514Sarybchikhunt_bist_start( 60283514Sarybchik __in efx_nic_t *enp, 61283514Sarybchik __in efx_bist_type_t type) 62283514Sarybchik{ 63291436Sarybchik efx_rc_t rc; 64283514Sarybchik 65283514Sarybchik if ((rc = efx_mcdi_bist_start(enp, type)) != 0) 66283514Sarybchik goto fail1; 67283514Sarybchik 68283514Sarybchik return (0); 69283514Sarybchik 70283514Sarybchikfail1: 71291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 72283514Sarybchik 73283514Sarybchik return (rc); 74283514Sarybchik} 75283514Sarybchik 76291436Sarybchik __checkReturn efx_rc_t 77283514Sarybchikhunt_bist_poll( 78283514Sarybchik __in efx_nic_t *enp, 79283514Sarybchik __in efx_bist_type_t type, 80283514Sarybchik __out efx_bist_result_t *resultp, 81283514Sarybchik __out_opt __drv_when(count > 0, __notnull) 82283514Sarybchik uint32_t *value_maskp, 83283514Sarybchik __out_ecount_opt(count) __drv_when(count > 0, __notnull) 84283514Sarybchik unsigned long *valuesp, 85283514Sarybchik __in size_t count) 86283514Sarybchik{ 87283514Sarybchik efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 88283514Sarybchik efx_mcdi_req_t req; 89283514Sarybchik uint8_t payload[MAX(MC_CMD_POLL_BIST_IN_LEN, 90283514Sarybchik MCDI_CTL_SDU_LEN_MAX)]; 91283514Sarybchik uint32_t value_mask = 0; 92283514Sarybchik uint32_t result; 93291436Sarybchik efx_rc_t rc; 94283514Sarybchik 95300840Sarybchik _NOTE(ARGUNUSED(type)) 96300840Sarybchik 97283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 98283514Sarybchik req.emr_cmd = MC_CMD_POLL_BIST; 99283514Sarybchik req.emr_in_buf = payload; 100283514Sarybchik req.emr_in_length = MC_CMD_POLL_BIST_IN_LEN; 101283514Sarybchik req.emr_out_buf = payload; 102283514Sarybchik req.emr_out_length = MCDI_CTL_SDU_LEN_MAX; 103283514Sarybchik 104283514Sarybchik efx_mcdi_execute(enp, &req); 105283514Sarybchik 106283514Sarybchik if (req.emr_rc != 0) { 107283514Sarybchik rc = req.emr_rc; 108283514Sarybchik goto fail1; 109283514Sarybchik } 110283514Sarybchik 111283514Sarybchik if (req.emr_out_length_used < MC_CMD_POLL_BIST_OUT_RESULT_OFST + 4) { 112283514Sarybchik rc = EMSGSIZE; 113283514Sarybchik goto fail2; 114283514Sarybchik } 115283514Sarybchik 116283514Sarybchik if (count > 0) 117283514Sarybchik (void) memset(valuesp, '\0', count * sizeof (unsigned long)); 118283514Sarybchik 119283514Sarybchik result = MCDI_OUT_DWORD(req, POLL_BIST_OUT_RESULT); 120283514Sarybchik 121283514Sarybchik if (result == MC_CMD_POLL_BIST_FAILED && 122283514Sarybchik req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MEM_LEN && 123283514Sarybchik count > EFX_BIST_MEM_ECC_FATAL) { 124283514Sarybchik if (valuesp != NULL) { 125283514Sarybchik valuesp[EFX_BIST_MEM_TEST] = 126283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_TEST); 127283514Sarybchik valuesp[EFX_BIST_MEM_ADDR] = 128283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ADDR); 129283514Sarybchik valuesp[EFX_BIST_MEM_BUS] = 130283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_BUS); 131283514Sarybchik valuesp[EFX_BIST_MEM_EXPECT] = 132283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_EXPECT); 133283514Sarybchik valuesp[EFX_BIST_MEM_ACTUAL] = 134283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ACTUAL); 135283514Sarybchik valuesp[EFX_BIST_MEM_ECC] = 136283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC); 137283514Sarybchik valuesp[EFX_BIST_MEM_ECC_PARITY] = 138283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC_PARITY); 139283514Sarybchik valuesp[EFX_BIST_MEM_ECC_FATAL] = 140283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC_FATAL); 141283514Sarybchik } 142283514Sarybchik value_mask |= (1 << EFX_BIST_MEM_TEST) | 143283514Sarybchik (1 << EFX_BIST_MEM_ADDR) | 144283514Sarybchik (1 << EFX_BIST_MEM_BUS) | 145283514Sarybchik (1 << EFX_BIST_MEM_EXPECT) | 146283514Sarybchik (1 << EFX_BIST_MEM_ACTUAL) | 147283514Sarybchik (1 << EFX_BIST_MEM_ECC) | 148283514Sarybchik (1 << EFX_BIST_MEM_ECC_PARITY) | 149283514Sarybchik (1 << EFX_BIST_MEM_ECC_FATAL); 150283514Sarybchik } else if (result == MC_CMD_POLL_BIST_FAILED && 151283514Sarybchik encp->enc_phy_type == EFX_PHY_XFI_FARMI && 152283514Sarybchik req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MRSFP_LEN && 153283514Sarybchik count > EFX_BIST_FAULT_CODE) { 154283514Sarybchik if (valuesp != NULL) 155283514Sarybchik valuesp[EFX_BIST_FAULT_CODE] = 156283514Sarybchik MCDI_OUT_DWORD(req, POLL_BIST_OUT_MRSFP_TEST); 157283514Sarybchik value_mask |= 1 << EFX_BIST_FAULT_CODE; 158283514Sarybchik } 159283514Sarybchik 160283514Sarybchik if (value_maskp != NULL) 161283514Sarybchik *value_maskp = value_mask; 162283514Sarybchik 163283514Sarybchik EFSYS_ASSERT(resultp != NULL); 164283514Sarybchik if (result == MC_CMD_POLL_BIST_RUNNING) 165283514Sarybchik *resultp = EFX_BIST_RESULT_RUNNING; 166283514Sarybchik else if (result == MC_CMD_POLL_BIST_PASSED) 167283514Sarybchik *resultp = EFX_BIST_RESULT_PASSED; 168283514Sarybchik else 169283514Sarybchik *resultp = EFX_BIST_RESULT_FAILED; 170283514Sarybchik 171283514Sarybchik return (0); 172283514Sarybchik 173283514Sarybchikfail2: 174283514Sarybchik EFSYS_PROBE(fail2); 175283514Sarybchikfail1: 176291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 177283514Sarybchik 178283514Sarybchik return (rc); 179283514Sarybchik} 180283514Sarybchik 181283514Sarybchik void 182283514Sarybchikhunt_bist_stop( 183283514Sarybchik __in efx_nic_t *enp, 184283514Sarybchik __in efx_bist_type_t type) 185283514Sarybchik{ 186283514Sarybchik /* There is no way to stop BIST on Huntinton. */ 187283514Sarybchik _NOTE(ARGUNUSED(enp, type)) 188283514Sarybchik} 189283514Sarybchik 190283514Sarybchik#endif /* EFSYS_OPT_BIST */ 191283514Sarybchik 192283514Sarybchik#endif /* EFSYS_OPT_HUNTINGTON */ 193