1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2020 Xilinx, Inc. 4 * Copyright(c) 2009-2019 Solarflare Communications Inc. 5 */ 6 7 #ifndef _SYS_EFX_MCDI_H 8 #define _SYS_EFX_MCDI_H 9 10 #include "efx.h" 11 #include "efx_regs_mcdi.h" 12 13 #if EFSYS_OPT_NAMES 14 #include "efx_regs_mcdi_strs.h" 15 #endif /* EFSYS_OPT_NAMES */ 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 /* 22 * A reboot/assertion causes the MCDI status word to be set after the 23 * command word is set or a REBOOT event is sent. If we notice a reboot 24 * via these mechanisms then wait 10ms for the status word to be set. 25 */ 26 #define EFX_MCDI_STATUS_SLEEP_US 10000 27 28 struct efx_mcdi_req_s { 29 boolean_t emr_quiet; 30 /* Inputs: Command #, input buffer and length */ 31 unsigned int emr_cmd; 32 uint8_t *emr_in_buf; 33 size_t emr_in_length; 34 /* Outputs: retcode, buffer, length and length used */ 35 efx_rc_t emr_rc; 36 uint8_t *emr_out_buf; 37 size_t emr_out_length; 38 size_t emr_out_length_used; 39 /* Internals: low level transport details */ 40 unsigned int emr_err_code; 41 unsigned int emr_err_arg; 42 #if EFSYS_OPT_MCDI_PROXY_AUTH 43 uint32_t emr_proxy_handle; 44 #endif 45 }; 46 47 typedef struct efx_mcdi_iface_s { 48 unsigned int emi_port; 49 unsigned int emi_max_version; 50 unsigned int emi_seq; 51 efx_mcdi_req_t *emi_pending_req; 52 boolean_t emi_ev_cpl; 53 boolean_t emi_new_epoch; 54 int emi_aborted; 55 uint32_t emi_poll_cnt; 56 uint32_t emi_mc_reboot_status; 57 } efx_mcdi_iface_t; 58 59 LIBEFX_INTERNAL 60 extern void 61 efx_mcdi_execute( 62 __in efx_nic_t *enp, 63 __inout efx_mcdi_req_t *emrp); 64 65 LIBEFX_INTERNAL 66 extern void 67 efx_mcdi_execute_quiet( 68 __in efx_nic_t *enp, 69 __inout efx_mcdi_req_t *emrp); 70 71 LIBEFX_INTERNAL 72 extern void 73 efx_mcdi_ev_cpl( 74 __in efx_nic_t *enp, 75 __in unsigned int seq, 76 __in unsigned int outlen, 77 __in int errcode); 78 79 #if EFSYS_OPT_MCDI_PROXY_AUTH 80 LIBEFX_API 81 extern __checkReturn efx_rc_t 82 efx_mcdi_get_proxy_handle( 83 __in efx_nic_t *enp, 84 __in efx_mcdi_req_t *emrp, 85 __out uint32_t *handlep); 86 87 LIBEFX_INTERNAL 88 extern void 89 efx_mcdi_ev_proxy_response( 90 __in efx_nic_t *enp, 91 __in unsigned int handle, 92 __in unsigned int status); 93 #endif 94 95 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER 96 LIBEFX_INTERNAL 97 extern void 98 efx_mcdi_ev_proxy_request( 99 __in efx_nic_t *enp, 100 __in unsigned int index); 101 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */ 102 103 LIBEFX_INTERNAL 104 extern void 105 efx_mcdi_ev_death( 106 __in efx_nic_t *enp, 107 __in int rc); 108 109 LIBEFX_INTERNAL 110 extern __checkReturn efx_rc_t 111 efx_mcdi_request_errcode( 112 __in unsigned int err); 113 114 LIBEFX_INTERNAL 115 extern void 116 efx_mcdi_raise_exception( 117 __in efx_nic_t *enp, 118 __in_opt efx_mcdi_req_t *emrp, 119 __in int rc); 120 121 typedef enum efx_mcdi_boot_e { 122 EFX_MCDI_BOOT_PRIMARY, 123 EFX_MCDI_BOOT_SECONDARY, 124 EFX_MCDI_BOOT_ROM, 125 } efx_mcdi_boot_t; 126 127 LIBEFX_INTERNAL 128 extern __checkReturn efx_rc_t 129 efx_mcdi_version( 130 __in efx_nic_t *enp, 131 __out_ecount_opt(4) uint16_t versionp[4], 132 __out_opt uint32_t *buildp, 133 __out_opt efx_mcdi_boot_t *statusp); 134 135 LIBEFX_INTERNAL 136 extern __checkReturn efx_rc_t 137 efx_mcdi_get_capabilities( 138 __in efx_nic_t *enp, 139 __out_opt uint32_t *flagsp, 140 __out_opt uint16_t *rx_dpcpu_fw_idp, 141 __out_opt uint16_t *tx_dpcpu_fw_idp, 142 __out_opt uint32_t *flags2p, 143 __out_opt uint32_t *tso2ncp); 144 145 LIBEFX_INTERNAL 146 extern __checkReturn efx_rc_t 147 efx_mcdi_read_assertion( 148 __in efx_nic_t *enp); 149 150 LIBEFX_INTERNAL 151 extern __checkReturn efx_rc_t 152 efx_mcdi_exit_assertion_handler( 153 __in efx_nic_t *enp); 154 155 LIBEFX_INTERNAL 156 extern __checkReturn efx_rc_t 157 efx_mcdi_drv_attach( 158 __in efx_nic_t *enp, 159 __in boolean_t attach); 160 161 LIBEFX_INTERNAL 162 extern __checkReturn efx_rc_t 163 efx_mcdi_get_board_cfg( 164 __in efx_nic_t *enp, 165 __out_opt uint32_t *board_typep, 166 __out_opt efx_dword_t *capabilitiesp, 167 __out_ecount_opt(6) uint8_t mac_addrp[6]); 168 169 LIBEFX_INTERNAL 170 extern __checkReturn efx_rc_t 171 efx_mcdi_get_phy_cfg( 172 __in efx_nic_t *enp); 173 174 LIBEFX_INTERNAL 175 extern __checkReturn efx_rc_t 176 efx_mcdi_firmware_update_supported( 177 __in efx_nic_t *enp, 178 __out boolean_t *supportedp); 179 180 LIBEFX_INTERNAL 181 extern __checkReturn efx_rc_t 182 efx_mcdi_macaddr_change_supported( 183 __in efx_nic_t *enp, 184 __out boolean_t *supportedp); 185 186 LIBEFX_INTERNAL 187 extern __checkReturn efx_rc_t 188 efx_mcdi_link_control_supported( 189 __in efx_nic_t *enp, 190 __out boolean_t *supportedp); 191 192 LIBEFX_INTERNAL 193 extern __checkReturn efx_rc_t 194 efx_mcdi_mac_spoofing_supported( 195 __in efx_nic_t *enp, 196 __out boolean_t *supportedp); 197 198 199 #if EFSYS_OPT_BIST 200 #if EFX_OPTS_EF10() 201 LIBEFX_INTERNAL 202 extern __checkReturn efx_rc_t 203 efx_mcdi_bist_enable_offline( 204 __in efx_nic_t *enp); 205 #endif /* EFX_OPTS_EF10() */ 206 LIBEFX_INTERNAL 207 extern __checkReturn efx_rc_t 208 efx_mcdi_bist_start( 209 __in efx_nic_t *enp, 210 __in efx_bist_type_t type); 211 #endif /* EFSYS_OPT_BIST */ 212 213 LIBEFX_INTERNAL 214 extern __checkReturn efx_rc_t 215 efx_mcdi_get_resource_limits( 216 __in efx_nic_t *enp, 217 __out_opt uint32_t *nevqp, 218 __out_opt uint32_t *nrxqp, 219 __out_opt uint32_t *ntxqp); 220 221 LIBEFX_INTERNAL 222 extern __checkReturn efx_rc_t 223 efx_mcdi_log_ctrl( 224 __in efx_nic_t *enp); 225 226 LIBEFX_INTERNAL 227 extern __checkReturn efx_rc_t 228 efx_mcdi_mac_stats_clear( 229 __in efx_nic_t *enp); 230 231 LIBEFX_INTERNAL 232 extern __checkReturn efx_rc_t 233 efx_mcdi_mac_stats_upload( 234 __in efx_nic_t *enp, 235 __in efsys_mem_t *esmp); 236 237 LIBEFX_INTERNAL 238 extern __checkReturn efx_rc_t 239 efx_mcdi_mac_stats_periodic( 240 __in efx_nic_t *enp, 241 __in efsys_mem_t *esmp, 242 __in uint16_t period_ms, 243 __in boolean_t events); 244 245 246 #if EFSYS_OPT_LOOPBACK 247 LIBEFX_INTERNAL 248 extern __checkReturn efx_rc_t 249 efx_mcdi_get_loopback_modes( 250 __in efx_nic_t *enp); 251 #endif /* EFSYS_OPT_LOOPBACK */ 252 253 LIBEFX_INTERNAL 254 extern __checkReturn efx_rc_t 255 efx_mcdi_phy_module_get_info( 256 __in efx_nic_t *enp, 257 __in uint8_t dev_addr, 258 __in size_t offset, 259 __in size_t len, 260 __out_bcount(len) uint8_t *data); 261 262 #define MCDI_IN(_emr, _type, _ofst) \ 263 ((_type *)((_emr).emr_in_buf + (_ofst))) 264 265 #define MCDI_IN2(_emr, _type, _ofst) \ 266 MCDI_IN(_emr, _type, MC_CMD_ ## _ofst ## _OFST) 267 268 #define MCDI_IN_SET_BYTE(_emr, _ofst, _value) \ 269 EFX_POPULATE_BYTE_1(*MCDI_IN2(_emr, efx_byte_t, _ofst), \ 270 EFX_BYTE_0, _value) 271 272 #define MCDI_IN_SET_WORD(_emr, _ofst, _value) \ 273 EFX_POPULATE_WORD_1(*MCDI_IN2(_emr, efx_word_t, _ofst), \ 274 EFX_WORD_0, _value) 275 276 #define MCDI_IN_SET_DWORD(_emr, _ofst, _value) \ 277 EFX_POPULATE_DWORD_1(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 278 EFX_DWORD_0, _value) 279 280 #define MCDI_IN_SET_DWORD_FIELD(_emr, _ofst, _field, _value) \ 281 EFX_SET_DWORD_FIELD(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 282 MC_CMD_ ## _field, _value) 283 284 #define MCDI_IN_POPULATE_DWORD_1(_emr, _ofst, _field1, _value1) \ 285 EFX_POPULATE_DWORD_1(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 286 MC_CMD_ ## _field1, _value1) 287 288 #define MCDI_IN_POPULATE_DWORD_2(_emr, _ofst, _field1, _value1, \ 289 _field2, _value2) \ 290 EFX_POPULATE_DWORD_2(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 291 MC_CMD_ ## _field1, _value1, \ 292 MC_CMD_ ## _field2, _value2) 293 294 #define MCDI_IN_POPULATE_DWORD_3(_emr, _ofst, _field1, _value1, \ 295 _field2, _value2, _field3, _value3) \ 296 EFX_POPULATE_DWORD_3(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 297 MC_CMD_ ## _field1, _value1, \ 298 MC_CMD_ ## _field2, _value2, \ 299 MC_CMD_ ## _field3, _value3) 300 301 #define MCDI_IN_POPULATE_DWORD_4(_emr, _ofst, _field1, _value1, \ 302 _field2, _value2, _field3, _value3, _field4, _value4) \ 303 EFX_POPULATE_DWORD_4(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 304 MC_CMD_ ## _field1, _value1, \ 305 MC_CMD_ ## _field2, _value2, \ 306 MC_CMD_ ## _field3, _value3, \ 307 MC_CMD_ ## _field4, _value4) 308 309 #define MCDI_IN_POPULATE_DWORD_5(_emr, _ofst, _field1, _value1, \ 310 _field2, _value2, _field3, _value3, _field4, _value4, \ 311 _field5, _value5) \ 312 EFX_POPULATE_DWORD_5(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 313 MC_CMD_ ## _field1, _value1, \ 314 MC_CMD_ ## _field2, _value2, \ 315 MC_CMD_ ## _field3, _value3, \ 316 MC_CMD_ ## _field4, _value4, \ 317 MC_CMD_ ## _field5, _value5) 318 319 #define MCDI_IN_POPULATE_DWORD_6(_emr, _ofst, _field1, _value1, \ 320 _field2, _value2, _field3, _value3, _field4, _value4, \ 321 _field5, _value5, _field6, _value6) \ 322 EFX_POPULATE_DWORD_6(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 323 MC_CMD_ ## _field1, _value1, \ 324 MC_CMD_ ## _field2, _value2, \ 325 MC_CMD_ ## _field3, _value3, \ 326 MC_CMD_ ## _field4, _value4, \ 327 MC_CMD_ ## _field5, _value5, \ 328 MC_CMD_ ## _field6, _value6) 329 330 #define MCDI_IN_POPULATE_DWORD_7(_emr, _ofst, _field1, _value1, \ 331 _field2, _value2, _field3, _value3, _field4, _value4, \ 332 _field5, _value5, _field6, _value6, _field7, _value7) \ 333 EFX_POPULATE_DWORD_7(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 334 MC_CMD_ ## _field1, _value1, \ 335 MC_CMD_ ## _field2, _value2, \ 336 MC_CMD_ ## _field3, _value3, \ 337 MC_CMD_ ## _field4, _value4, \ 338 MC_CMD_ ## _field5, _value5, \ 339 MC_CMD_ ## _field6, _value6, \ 340 MC_CMD_ ## _field7, _value7) 341 342 #define MCDI_IN_POPULATE_DWORD_8(_emr, _ofst, _field1, _value1, \ 343 _field2, _value2, _field3, _value3, _field4, _value4, \ 344 _field5, _value5, _field6, _value6, _field7, _value7, \ 345 _field8, _value8) \ 346 EFX_POPULATE_DWORD_8(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 347 MC_CMD_ ## _field1, _value1, \ 348 MC_CMD_ ## _field2, _value2, \ 349 MC_CMD_ ## _field3, _value3, \ 350 MC_CMD_ ## _field4, _value4, \ 351 MC_CMD_ ## _field5, _value5, \ 352 MC_CMD_ ## _field6, _value6, \ 353 MC_CMD_ ## _field7, _value7, \ 354 MC_CMD_ ## _field8, _value8) 355 356 #define MCDI_IN_POPULATE_DWORD_9(_emr, _ofst, _field1, _value1, \ 357 _field2, _value2, _field3, _value3, _field4, _value4, \ 358 _field5, _value5, _field6, _value6, _field7, _value7, \ 359 _field8, _value8, _field9, _value9) \ 360 EFX_POPULATE_DWORD_9(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 361 MC_CMD_ ## _field1, _value1, \ 362 MC_CMD_ ## _field2, _value2, \ 363 MC_CMD_ ## _field3, _value3, \ 364 MC_CMD_ ## _field4, _value4, \ 365 MC_CMD_ ## _field5, _value5, \ 366 MC_CMD_ ## _field6, _value6, \ 367 MC_CMD_ ## _field7, _value7, \ 368 MC_CMD_ ## _field8, _value8, \ 369 MC_CMD_ ## _field9, _value9) 370 371 #define MCDI_IN_POPULATE_DWORD_10(_emr, _ofst, _field1, _value1, \ 372 _field2, _value2, _field3, _value3, _field4, _value4, \ 373 _field5, _value5, _field6, _value6, _field7, _value7, \ 374 _field8, _value8, _field9, _value9, _field10, _value10) \ 375 EFX_POPULATE_DWORD_10(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ 376 MC_CMD_ ## _field1, _value1, \ 377 MC_CMD_ ## _field2, _value2, \ 378 MC_CMD_ ## _field3, _value3, \ 379 MC_CMD_ ## _field4, _value4, \ 380 MC_CMD_ ## _field5, _value5, \ 381 MC_CMD_ ## _field6, _value6, \ 382 MC_CMD_ ## _field7, _value7, \ 383 MC_CMD_ ## _field8, _value8, \ 384 MC_CMD_ ## _field9, _value9, \ 385 MC_CMD_ ## _field10, _value10) 386 387 /* 388 * Native setters (MCDI_IN_SET_*_NATIVE) are used when MCDI field is in 389 * network order to avoid conversion to little-endian that is done in 390 * other setters. 391 */ 392 #define MCDI_IN_SET_WORD_NATIVE(_emr, _ofst, _value) \ 393 MCDI_IN2((_emr), efx_word_t, _ofst)->ew_u16[0] = (_value) 394 395 #define MCDI_IN_SET_DWORD_NATIVE(_emr, _ofst, _value) \ 396 MCDI_IN2((_emr), efx_dword_t, _ofst)->ed_u32[0] = (_value) 397 398 #define MCDI_OUT(_emr, _type, _ofst) \ 399 ((_type *)((_emr).emr_out_buf + (_ofst))) 400 401 #define MCDI_OUT2(_emr, _type, _ofst) \ 402 MCDI_OUT(_emr, _type, MC_CMD_ ## _ofst ## _OFST) 403 404 #define MCDI_OUT_BYTE(_emr, _ofst) \ 405 EFX_BYTE_FIELD(*MCDI_OUT2(_emr, efx_byte_t, _ofst), \ 406 EFX_BYTE_0) 407 408 #define MCDI_OUT_WORD(_emr, _ofst) \ 409 EFX_WORD_FIELD(*MCDI_OUT2(_emr, efx_word_t, _ofst), \ 410 EFX_WORD_0) 411 412 #define MCDI_OUT_WORD_FIELD(_emr, _ofst, _field) \ 413 EFX_WORD_FIELD(*MCDI_OUT2(_emr, efx_word_t, _ofst), \ 414 MC_CMD_ ## _field) 415 416 #define MCDI_OUT_DWORD(_emr, _ofst) \ 417 EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst), \ 418 EFX_DWORD_0) 419 420 #define MCDI_OUT_DWORD_FIELD(_emr, _ofst, _field) \ 421 EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst), \ 422 MC_CMD_ ## _field) 423 424 #define MCDI_EV_FIELD(_eqp, _field) \ 425 EFX_QWORD_FIELD(*_eqp, MCDI_EVENT_ ## _field) 426 427 #define MCDI_CMD_DWORD_FIELD(_edp, _field) \ 428 EFX_DWORD_FIELD(*_edp, MC_CMD_ ## _field) 429 430 #define EFX_MCDI_HAVE_PRIVILEGE(mask, priv) \ 431 (((mask) & (MC_CMD_PRIVILEGE_MASK_IN_GRP_ ## priv)) == \ 432 (MC_CMD_PRIVILEGE_MASK_IN_GRP_ ## priv)) 433 434 #define EFX_MCDI_BUF_SIZE(_in_len, _out_len) \ 435 EFX_P2ROUNDUP(size_t, \ 436 MAX(MAX(_in_len, _out_len), (2 * sizeof (efx_dword_t))),\ 437 sizeof (efx_dword_t)) 438 439 /* 440 * The buffer size must be a multiple of dword to ensure that MCDI works 441 * properly with Siena based boards (which use on-chip buffer). Also, it 442 * should be at minimum the size of two dwords to allow space for extended 443 * error responses if the request/response buffer sizes are smaller. 444 */ 445 #define EFX_MCDI_DECLARE_BUF(_name, _in_len, _out_len) \ 446 uint8_t _name[EFX_MCDI_BUF_SIZE(_in_len, _out_len)] = {0} 447 448 typedef enum efx_mcdi_feature_id_e { 449 EFX_MCDI_FEATURE_FW_UPDATE = 0, 450 EFX_MCDI_FEATURE_LINK_CONTROL, 451 EFX_MCDI_FEATURE_MACADDR_CHANGE, 452 EFX_MCDI_FEATURE_MAC_SPOOFING, 453 EFX_MCDI_FEATURE_NIDS 454 } efx_mcdi_feature_id_t; 455 456 #ifdef __cplusplus 457 } 458 #endif 459 460 #endif /* _SYS_EFX_MCDI_H */ 461