1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2020 Xilinx, Inc. 4 * Copyright(c) 2012-2019 Solarflare Communications Inc. 5 */ 6 7 #include "efx.h" 8 #include "efx_impl.h" 9 10 11 #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() 12 13 #if EFSYS_OPT_MCDI 14 15 #ifndef WITH_MCDI_V2 16 #error "WITH_MCDI_V2 required for EF10 MCDIv2 commands." 17 #endif 18 19 20 __checkReturn efx_rc_t 21 ef10_mcdi_init( 22 __in efx_nic_t *enp, 23 __in const efx_mcdi_transport_t *emtp) 24 { 25 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 26 efsys_mem_t *esmp = emtp->emt_dma_mem; 27 efx_dword_t dword; 28 efx_rc_t rc; 29 30 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp)); 31 EFSYS_ASSERT(enp->en_features & EFX_FEATURE_MCDI_DMA); 32 33 /* 34 * All EF10 firmware supports MCDIv2 and MCDIv1. 35 * Medford BootROM supports MCDIv2 and MCDIv1. 36 * Huntington BootROM supports MCDIv1 only. 37 */ 38 emip->emi_max_version = 2; 39 40 /* A host DMA buffer is required for EF10 MCDI */ 41 if (esmp == NULL) { 42 rc = EINVAL; 43 goto fail1; 44 } 45 46 /* 47 * Ensure that the MC doorbell is in a known state before issuing MCDI 48 * commands. The recovery algorithm requires that the MC command buffer 49 * must be 256 byte aligned. See bug24769. 50 */ 51 if ((EFSYS_MEM_ADDR(esmp) & 0xFF) != 0) { 52 rc = EINVAL; 53 goto fail2; 54 } 55 EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 1); 56 switch (enp->en_family) { 57 #if EFSYS_OPT_RIVERHEAD 58 case EFX_FAMILY_RIVERHEAD: 59 EFX_BAR_FCW_WRITED(enp, ER_GZ_MC_DB_HWRD_REG, &dword); 60 break; 61 #endif /* EFSYS_OPT_RIVERHEAD */ 62 default: 63 EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE); 64 break; 65 } 66 67 /* Save initial MC reboot status */ 68 (void) ef10_mcdi_poll_reboot(enp); 69 70 /* Start a new epoch (allow fresh MCDI requests to succeed) */ 71 efx_mcdi_new_epoch(enp); 72 73 return (0); 74 75 fail2: 76 EFSYS_PROBE(fail2); 77 fail1: 78 EFSYS_PROBE1(fail1, efx_rc_t, rc); 79 80 return (rc); 81 } 82 83 void 84 ef10_mcdi_fini( 85 __in efx_nic_t *enp) 86 { 87 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 88 89 emip->emi_new_epoch = B_FALSE; 90 } 91 92 /* 93 * In older firmware all commands are processed in a single thread, so a long 94 * running command for one PCIe function can block processing for another 95 * function (see bug 61269). 96 * 97 * In newer firmware that supports multithreaded MCDI processing, we can extend 98 * the timeout for long-running requests which we know firmware may choose to 99 * process in a background thread. 100 */ 101 #define EF10_MCDI_CMD_TIMEOUT_US (10 * 1000 * 1000) 102 #define EF10_MCDI_CMD_LONG_TIMEOUT_US (60 * 1000 * 1000) 103 104 void 105 ef10_mcdi_get_timeout( 106 __in efx_nic_t *enp, 107 __in efx_mcdi_req_t *emrp, 108 __out uint32_t *timeoutp) 109 { 110 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 111 112 switch (emrp->emr_cmd) { 113 case MC_CMD_POLL_BIST: 114 case MC_CMD_NVRAM_ERASE: 115 case MC_CMD_LICENSING_V3: 116 case MC_CMD_NVRAM_UPDATE_FINISH: 117 if (encp->enc_nvram_update_verify_result_supported != B_FALSE) { 118 /* 119 * Potentially longer running commands, which firmware 120 * may choose to process in a background thread. 121 */ 122 *timeoutp = EF10_MCDI_CMD_LONG_TIMEOUT_US; 123 break; 124 } 125 /* FALLTHRU */ 126 default: 127 *timeoutp = EF10_MCDI_CMD_TIMEOUT_US; 128 break; 129 } 130 } 131 132 void 133 ef10_mcdi_send_request( 134 __in efx_nic_t *enp, 135 __in_bcount(hdr_len) void *hdrp, 136 __in size_t hdr_len, 137 __in_bcount(sdu_len) void *sdup, 138 __in size_t sdu_len) 139 { 140 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 141 efsys_mem_t *esmp = emtp->emt_dma_mem; 142 efx_dword_t dword; 143 unsigned int pos; 144 145 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp)); 146 147 /* Write the header */ 148 for (pos = 0; pos < hdr_len; pos += sizeof (efx_dword_t)) { 149 dword = *(efx_dword_t *)((uint8_t *)hdrp + pos); 150 EFSYS_MEM_WRITED(esmp, pos, &dword); 151 } 152 153 /* Write the payload */ 154 for (pos = 0; pos < sdu_len; pos += sizeof (efx_dword_t)) { 155 dword = *(efx_dword_t *)((uint8_t *)sdup + pos); 156 EFSYS_MEM_WRITED(esmp, hdr_len + pos, &dword); 157 } 158 159 /* Guarantee ordering of memory (MCDI request) and PIO (MC doorbell) */ 160 EFSYS_DMA_SYNC_FOR_DEVICE(esmp, 0, hdr_len + sdu_len); 161 EFSYS_PIO_WRITE_BARRIER(); 162 163 /* Ring the doorbell to post the command DMA address to the MC */ 164 EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 165 EFSYS_MEM_ADDR(esmp) >> 32); 166 switch (enp->en_family) { 167 #if EFSYS_OPT_RIVERHEAD 168 case EFX_FAMILY_RIVERHEAD: 169 EFX_BAR_FCW_WRITED(enp, ER_GZ_MC_DB_LWRD_REG, &dword); 170 break; 171 #endif /* EFSYS_OPT_RIVERHEAD */ 172 default: 173 EFX_BAR_WRITED(enp, ER_DZ_MC_DB_LWRD_REG, &dword, B_FALSE); 174 break; 175 } 176 177 EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 178 EFSYS_MEM_ADDR(esmp) & 0xffffffff); 179 switch (enp->en_family) { 180 #if EFSYS_OPT_RIVERHEAD 181 case EFX_FAMILY_RIVERHEAD: 182 EFX_BAR_FCW_WRITED(enp, ER_GZ_MC_DB_HWRD_REG, &dword); 183 break; 184 #endif /* EFSYS_OPT_RIVERHEAD */ 185 default: 186 EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE); 187 break; 188 } 189 } 190 191 __checkReturn boolean_t 192 ef10_mcdi_poll_response( 193 __in efx_nic_t *enp) 194 { 195 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 196 efsys_mem_t *esmp = emtp->emt_dma_mem; 197 efx_dword_t hdr; 198 199 EFSYS_MEM_READD(esmp, 0, &hdr); 200 EFSYS_MEM_READ_BARRIER(); 201 202 return (EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE) ? B_TRUE : B_FALSE); 203 } 204 205 void 206 ef10_mcdi_read_response( 207 __in efx_nic_t *enp, 208 __out_bcount(length) void *bufferp, 209 __in size_t offset, 210 __in size_t length) 211 { 212 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 213 efsys_mem_t *esmp = emtp->emt_dma_mem; 214 unsigned int pos = 0; 215 efx_dword_t data; 216 size_t remaining = length; 217 218 while (remaining > 0) { 219 size_t chunk = MIN(remaining, sizeof (data)); 220 221 EFSYS_MEM_READD(esmp, offset + pos, &data); 222 memcpy((uint8_t *)bufferp + pos, &data, chunk); 223 pos += chunk; 224 remaining -= chunk; 225 } 226 } 227 228 efx_rc_t 229 ef10_mcdi_poll_reboot( 230 __in efx_nic_t *enp) 231 { 232 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 233 efx_dword_t dword; 234 uint32_t old_status; 235 uint32_t new_status; 236 efx_rc_t rc; 237 238 old_status = emip->emi_mc_reboot_status; 239 240 /* Update MC reboot status word */ 241 switch (enp->en_family) { 242 #if EFSYS_OPT_RIVERHEAD 243 case EFX_FAMILY_RIVERHEAD: 244 EFX_BAR_FCW_READD(enp, ER_GZ_MC_SFT_STATUS, &dword); 245 break; 246 #endif /* EFSYS_OPT_RIVERHEAD */ 247 default: 248 EFX_BAR_READD(enp, ER_DZ_BIU_MC_SFT_STATUS_REG, 249 &dword, B_FALSE); 250 break; 251 } 252 new_status = dword.ed_u32[0]; 253 254 /* MC has rebooted if the value has changed */ 255 if (new_status != old_status) { 256 emip->emi_mc_reboot_status = new_status; 257 258 /* 259 * FIXME: Ignore detected MC REBOOT for now. 260 * 261 * The Siena support for checking for MC reboot from status 262 * flags is broken - see comments in siena_mcdi_poll_reboot(). 263 * As the generic MCDI code is shared the EF10 reboot 264 * detection suffers similar problems. 265 * 266 * Do not report an error when the boot status changes until 267 * this can be handled by common code drivers (and reworked to 268 * support Siena too). 269 */ 270 _NOTE(CONSTANTCONDITION) 271 if (B_FALSE) { 272 rc = EIO; 273 goto fail1; 274 } 275 } 276 277 return (0); 278 279 fail1: 280 EFSYS_PROBE1(fail1, efx_rc_t, rc); 281 282 return (rc); 283 } 284 285 __checkReturn efx_rc_t 286 ef10_mcdi_feature_supported( 287 __in efx_nic_t *enp, 288 __in efx_mcdi_feature_id_t id, 289 __out boolean_t *supportedp) 290 { 291 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 292 uint32_t privilege_mask = encp->enc_privilege_mask; 293 efx_rc_t rc; 294 295 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp)); 296 297 /* 298 * Use privilege mask state at MCDI attach. 299 */ 300 301 switch (id) { 302 case EFX_MCDI_FEATURE_FW_UPDATE: 303 /* 304 * Admin privilege must be used prior to introduction of 305 * specific flag. 306 */ 307 *supportedp = 308 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN); 309 break; 310 case EFX_MCDI_FEATURE_LINK_CONTROL: 311 /* 312 * Admin privilege used prior to introduction of 313 * specific flag. 314 */ 315 *supportedp = 316 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, LINK) || 317 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN); 318 break; 319 case EFX_MCDI_FEATURE_MACADDR_CHANGE: 320 /* 321 * Admin privilege must be used prior to introduction of 322 * mac spoofing privilege (at v4.6), which is used up to 323 * introduction of change mac spoofing privilege (at v4.7) 324 */ 325 *supportedp = 326 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, CHANGE_MAC) || 327 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING) || 328 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN); 329 break; 330 case EFX_MCDI_FEATURE_MAC_SPOOFING: 331 /* 332 * Admin privilege must be used prior to introduction of 333 * mac spoofing privilege (at v4.6), which is used up to 334 * introduction of mac spoofing TX privilege (at v4.7) 335 */ 336 *supportedp = 337 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING_TX) || 338 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING) || 339 EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN); 340 break; 341 default: 342 rc = ENOTSUP; 343 goto fail1; 344 } 345 346 return (0); 347 348 fail1: 349 EFSYS_PROBE1(fail1, efx_rc_t, rc); 350 351 return (rc); 352 } 353 354 #endif /* EFSYS_OPT_MCDI */ 355 356 #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */ 357