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