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 #include "efx.h" 33 #include "efx_impl.h" 34 35 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 36 37 __checkReturn efx_rc_t 38 ef10_intr_init( 39 __in efx_nic_t *enp, 40 __in efx_intr_type_t type, 41 __in efsys_mem_t *esmp) 42 { 43 _NOTE(ARGUNUSED(enp, type, esmp)) 44 return (0); 45 } 46 47 void 48 ef10_intr_enable( 49 __in efx_nic_t *enp) 50 { 51 _NOTE(ARGUNUSED(enp)) 52 } 53 54 void 55 ef10_intr_disable( 56 __in efx_nic_t *enp) 57 { 58 _NOTE(ARGUNUSED(enp)) 59 } 60 61 void 62 ef10_intr_disable_unlocked( 63 __in efx_nic_t *enp) 64 { 65 _NOTE(ARGUNUSED(enp)) 66 } 67 68 static __checkReturn efx_rc_t 69 efx_mcdi_trigger_interrupt( 70 __in efx_nic_t *enp, 71 __in unsigned int level) 72 { 73 efx_mcdi_req_t req; 74 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_TRIGGER_INTERRUPT_IN_LEN, 75 MC_CMD_TRIGGER_INTERRUPT_OUT_LEN); 76 efx_rc_t rc; 77 78 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 79 enp->en_family == EFX_FAMILY_MEDFORD || 80 enp->en_family == EFX_FAMILY_MEDFORD2); 81 82 if (level >= enp->en_nic_cfg.enc_intr_limit) { 83 rc = EINVAL; 84 goto fail1; 85 } 86 87 req.emr_cmd = MC_CMD_TRIGGER_INTERRUPT; 88 req.emr_in_buf = payload; 89 req.emr_in_length = MC_CMD_TRIGGER_INTERRUPT_IN_LEN; 90 req.emr_out_buf = payload; 91 req.emr_out_length = MC_CMD_TRIGGER_INTERRUPT_OUT_LEN; 92 93 MCDI_IN_SET_DWORD(req, TRIGGER_INTERRUPT_IN_INTR_LEVEL, level); 94 95 efx_mcdi_execute(enp, &req); 96 97 if (req.emr_rc != 0) { 98 rc = req.emr_rc; 99 goto fail2; 100 } 101 102 return (0); 103 104 fail2: 105 EFSYS_PROBE(fail2); 106 107 fail1: 108 EFSYS_PROBE1(fail1, efx_rc_t, rc); 109 110 return (rc); 111 } 112 113 __checkReturn efx_rc_t 114 ef10_intr_trigger( 115 __in efx_nic_t *enp, 116 __in unsigned int level) 117 { 118 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 119 efx_rc_t rc; 120 121 if (encp->enc_bug41750_workaround) { 122 /* 123 * bug 41750: Test interrupts don't work on Greenport 124 * bug 50084: Test interrupts don't work on VFs 125 */ 126 rc = ENOTSUP; 127 goto fail1; 128 } 129 130 if ((rc = efx_mcdi_trigger_interrupt(enp, level)) != 0) 131 goto fail2; 132 133 return (0); 134 135 fail2: 136 EFSYS_PROBE(fail2); 137 fail1: 138 EFSYS_PROBE1(fail1, efx_rc_t, rc); 139 140 return (rc); 141 } 142 143 void 144 ef10_intr_status_line( 145 __in efx_nic_t *enp, 146 __out boolean_t *fatalp, 147 __out uint32_t *qmaskp) 148 { 149 efx_dword_t dword; 150 151 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 152 enp->en_family == EFX_FAMILY_MEDFORD || 153 enp->en_family == EFX_FAMILY_MEDFORD2); 154 155 /* Read the queue mask and implicitly acknowledge the interrupt. */ 156 EFX_BAR_READD(enp, ER_DZ_BIU_INT_ISR_REG, &dword, B_FALSE); 157 *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 158 159 EFSYS_PROBE1(qmask, uint32_t, *qmaskp); 160 161 *fatalp = B_FALSE; 162 } 163 164 void 165 ef10_intr_status_message( 166 __in efx_nic_t *enp, 167 __in unsigned int message, 168 __out boolean_t *fatalp) 169 { 170 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 171 enp->en_family == EFX_FAMILY_MEDFORD || 172 enp->en_family == EFX_FAMILY_MEDFORD2); 173 174 _NOTE(ARGUNUSED(enp, message)) 175 176 /* EF10 fatal errors are reported via events */ 177 *fatalp = B_FALSE; 178 } 179 180 void 181 ef10_intr_fatal( 182 __in efx_nic_t *enp) 183 { 184 /* EF10 fatal errors are reported via events */ 185 _NOTE(ARGUNUSED(enp)) 186 } 187 188 void 189 ef10_intr_fini( 190 __in efx_nic_t *enp) 191 { 192 _NOTE(ARGUNUSED(enp)) 193 } 194 195 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 196