ef10_nic.c revision 294079
1249259Sdim/*- 2249259Sdim * Copyright (c) 2012-2015 Solarflare Communications Inc. 3249259Sdim * All rights reserved. 4249259Sdim * 5249259Sdim * Redistribution and use in source and binary forms, with or without 6249259Sdim * modification, are permitted provided that the following conditions are met: 7249259Sdim * 8249259Sdim * 1. Redistributions of source code must retain the above copyright notice, 9249259Sdim * this list of conditions and the following disclaimer. 10249259Sdim * 2. Redistributions in binary form must reproduce the above copyright notice, 11249259Sdim * this list of conditions and the following disclaimer in the documentation 12249259Sdim * and/or other materials provided with the distribution. 13249259Sdim * 14249259Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15249259Sdim * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16249259Sdim * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17249259Sdim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18249259Sdim * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19249259Sdim * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20249259Sdim * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21249259Sdim * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22249259Sdim * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23249259Sdim * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24249259Sdim * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25249259Sdim * 26249259Sdim * The views and conclusions contained in the software and documentation are 27249259Sdim * those of the authors and should not be interpreted as representing official 28249259Sdim * policies, either expressed or implied, of the FreeBSD Project. 29249259Sdim */ 30249259Sdim 31249259Sdim#include <sys/cdefs.h> 32249259Sdim__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/hunt_nic.c 294079 2016-01-15 06:27:51Z arybchik $"); 33249259Sdim 34249259Sdim#include "efx.h" 35249259Sdim#include "efx_impl.h" 36249259Sdim#if EFSYS_OPT_MON_MCDI 37249259Sdim#include "mcdi_mon.h" 38249259Sdim#endif 39296417Sdim 40249259Sdim#if EFSYS_OPT_HUNTINGTON 41249259Sdim 42249259Sdim#include "ef10_tlv_layout.h" 43249259Sdim 44296417Sdim __checkReturn efx_rc_t 45249259Sdimefx_mcdi_get_port_assignment( 46249259Sdim __in efx_nic_t *enp, 47249259Sdim __out uint32_t *portp) 48249259Sdim{ 49249259Sdim efx_mcdi_req_t req; 50249259Sdim uint8_t payload[MAX(MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN, 51249259Sdim MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN)]; 52249259Sdim efx_rc_t rc; 53249259Sdim 54249259Sdim EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 55249259Sdim enp->en_family == EFX_FAMILY_MEDFORD); 56249259Sdim 57249259Sdim (void) memset(payload, 0, sizeof (payload)); 58249259Sdim req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT; 59249259Sdim req.emr_in_buf = payload; 60249259Sdim req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN; 61249259Sdim req.emr_out_buf = payload; 62249259Sdim req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN; 63249259Sdim 64249259Sdim efx_mcdi_execute(enp, &req); 65249259Sdim 66249259Sdim if (req.emr_rc != 0) { 67249259Sdim rc = req.emr_rc; 68249259Sdim goto fail1; 69249259Sdim } 70249259Sdim 71249259Sdim if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) { 72249259Sdim rc = EMSGSIZE; 73249259Sdim goto fail2; 74249259Sdim } 75249259Sdim 76249259Sdim *portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT); 77249259Sdim 78249259Sdim return (0); 79249259Sdim 80249259Sdimfail2: 81249259Sdim EFSYS_PROBE(fail2); 82249259Sdimfail1: 83249259Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 84249259Sdim 85249259Sdim return (rc); 86249259Sdim} 87249259Sdim 88249259Sdim __checkReturn efx_rc_t 89249259Sdimefx_mcdi_get_port_modes( 90249259Sdim __in efx_nic_t *enp, 91249259Sdim __out uint32_t *modesp) 92249259Sdim{ 93249259Sdim efx_mcdi_req_t req; 94296417Sdim uint8_t payload[MAX(MC_CMD_GET_PORT_MODES_IN_LEN, 95296417Sdim MC_CMD_GET_PORT_MODES_OUT_LEN)]; 96296417Sdim efx_rc_t rc; 97249259Sdim 98249259Sdim EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 99249259Sdim enp->en_family == EFX_FAMILY_MEDFORD); 100249259Sdim 101288943Sdim (void) memset(payload, 0, sizeof (payload)); 102288943Sdim req.emr_cmd = MC_CMD_GET_PORT_MODES; 103249259Sdim req.emr_in_buf = payload; 104249259Sdim req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN; 105249259Sdim req.emr_out_buf = payload; 106249259Sdim req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN; 107249259Sdim 108249259Sdim efx_mcdi_execute(enp, &req); 109249259Sdim 110249259Sdim if (req.emr_rc != 0) { 111249259Sdim rc = req.emr_rc; 112249259Sdim goto fail1; 113249259Sdim } 114249259Sdim 115296417Sdim /* 116249259Sdim * Require only Modes and DefaultMode fields. 117249259Sdim * (CurrentMode field was added for Medford) 118249259Sdim */ 119249259Sdim if (req.emr_out_length_used < 120249259Sdim MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) { 121249259Sdim rc = EMSGSIZE; 122249259Sdim goto fail2; 123249259Sdim } 124251662Sdim 125249259Sdim *modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES); 126249259Sdim 127249259Sdim return (0); 128249259Sdim 129249259Sdimfail2: 130280031Sdim EFSYS_PROBE(fail2); 131280031Sdimfail1: 132280031Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 133249259Sdim 134249259Sdim return (rc); 135249259Sdim} 136249259Sdim 137249259Sdim 138249259Sdimstatic __checkReturn efx_rc_t 139249259Sdimefx_mcdi_vadaptor_alloc( 140249259Sdim __in efx_nic_t *enp, 141249259Sdim __in uint32_t port_id) 142249259Sdim{ 143249259Sdim efx_mcdi_req_t req; 144249259Sdim uint8_t payload[MAX(MC_CMD_VADAPTOR_ALLOC_IN_LEN, 145249259Sdim MC_CMD_VADAPTOR_ALLOC_OUT_LEN)]; 146249259Sdim efx_rc_t rc; 147288943Sdim 148288943Sdim EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL); 149249259Sdim 150296417Sdim (void) memset(payload, 0, sizeof (payload)); 151296417Sdim req.emr_cmd = MC_CMD_VADAPTOR_ALLOC; 152296417Sdim req.emr_in_buf = payload; 153296417Sdim req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN; 154296417Sdim req.emr_out_buf = payload; 155296417Sdim req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN; 156296417Sdim 157296417Sdim MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id); 158296417Sdim MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS, 159296417Sdim VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED, 160296417Sdim enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0); 161296417Sdim 162249259Sdim efx_mcdi_execute(enp, &req); 163249259Sdim 164249259Sdim if (req.emr_rc != 0) { 165249259Sdim rc = req.emr_rc; 166296417Sdim goto fail1; 167296417Sdim } 168249259Sdim 169249259Sdim return (0); 170249259Sdim 171249259Sdimfail1: 172296417Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 173296417Sdim 174249259Sdim return (rc); 175249259Sdim} 176249259Sdim 177249259Sdimstatic __checkReturn efx_rc_t 178249259Sdimefx_mcdi_vadaptor_free( 179249259Sdim __in efx_nic_t *enp, 180249259Sdim __in uint32_t port_id) 181249259Sdim{ 182249259Sdim efx_mcdi_req_t req; 183249259Sdim uint8_t payload[MAX(MC_CMD_VADAPTOR_FREE_IN_LEN, 184249259Sdim MC_CMD_VADAPTOR_FREE_OUT_LEN)]; 185249259Sdim efx_rc_t rc; 186249259Sdim 187249259Sdim (void) memset(payload, 0, sizeof (payload)); 188249259Sdim req.emr_cmd = MC_CMD_VADAPTOR_FREE; 189249259Sdim req.emr_in_buf = payload; 190249259Sdim req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN; 191249259Sdim req.emr_out_buf = payload; 192296417Sdim req.emr_out_length = MC_CMD_VADAPTOR_FREE_OUT_LEN; 193249259Sdim 194249259Sdim MCDI_IN_SET_DWORD(req, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id); 195249259Sdim 196249259Sdim efx_mcdi_execute(enp, &req); 197249259Sdim 198249259Sdim if (req.emr_rc != 0) { 199249259Sdim rc = req.emr_rc; 200249259Sdim goto fail1; 201249259Sdim } 202249259Sdim 203249259Sdim return (0); 204249259Sdim 205249259Sdimfail1: 206249259Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 207288943Sdim 208288943Sdim return (rc); 209249259Sdim} 210276479Sdim 211249259Sdim __checkReturn efx_rc_t 212249259Sdimefx_mcdi_get_mac_address_pf( 213249259Sdim __in efx_nic_t *enp, 214249259Sdim __out_ecount_opt(6) uint8_t mac_addrp[6]) 215249259Sdim{ 216249259Sdim efx_mcdi_req_t req; 217249259Sdim uint8_t payload[MAX(MC_CMD_GET_MAC_ADDRESSES_IN_LEN, 218249259Sdim MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)]; 219249259Sdim efx_rc_t rc; 220249259Sdim 221249259Sdim EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 222249259Sdim enp->en_family == EFX_FAMILY_MEDFORD); 223296417Sdim 224249259Sdim (void) memset(payload, 0, sizeof (payload)); 225296417Sdim req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES; 226249259Sdim req.emr_in_buf = payload; 227249259Sdim req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN; 228249259Sdim req.emr_out_buf = payload; 229249259Sdim req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN; 230296417Sdim 231296417Sdim efx_mcdi_execute(enp, &req); 232249259Sdim 233296417Sdim if (req.emr_rc != 0) { 234296417Sdim rc = req.emr_rc; 235296417Sdim goto fail1; 236296417Sdim } 237280031Sdim 238249259Sdim if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) { 239249259Sdim rc = EMSGSIZE; 240249259Sdim goto fail2; 241249259Sdim } 242249259Sdim 243249259Sdim if (MCDI_OUT_DWORD(req, GET_MAC_ADDRESSES_OUT_MAC_COUNT) < 1) { 244249259Sdim rc = ENOENT; 245249259Sdim goto fail3; 246249259Sdim } 247296417Sdim 248249259Sdim if (mac_addrp != NULL) { 249249259Sdim uint8_t *addrp; 250249259Sdim 251249259Sdim addrp = MCDI_OUT2(req, uint8_t, 252280031Sdim GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE); 253249259Sdim 254249259Sdim EFX_MAC_ADDR_COPY(mac_addrp, addrp); 255296417Sdim } 256249259Sdim 257249259Sdim return (0); 258249259Sdim 259296417Sdimfail3: 260249259Sdim EFSYS_PROBE(fail3); 261249259Sdimfail2: 262249259Sdim EFSYS_PROBE(fail2); 263249259Sdimfail1: 264249259Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 265296417Sdim 266296417Sdim return (rc); 267249259Sdim} 268276479Sdim 269296417Sdim __checkReturn efx_rc_t 270249259Sdimefx_mcdi_get_mac_address_vf( 271249259Sdim __in efx_nic_t *enp, 272249259Sdim __out_ecount_opt(6) uint8_t mac_addrp[6]) 273249259Sdim{ 274296417Sdim efx_mcdi_req_t req; 275249259Sdim uint8_t payload[MAX(MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN, 276249259Sdim MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX)]; 277249259Sdim efx_rc_t rc; 278249259Sdim 279249259Sdim EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 280249259Sdim enp->en_family == EFX_FAMILY_MEDFORD); 281249259Sdim 282280031Sdim (void) memset(payload, 0, sizeof (payload)); 283296417Sdim req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES; 284249259Sdim req.emr_in_buf = payload; 285249259Sdim req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN; 286249259Sdim req.emr_out_buf = payload; 287249259Sdim req.emr_out_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX; 288249259Sdim 289249259Sdim MCDI_IN_SET_DWORD(req, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID, 290249259Sdim EVB_PORT_ID_ASSIGNED); 291249259Sdim 292280031Sdim efx_mcdi_execute(enp, &req); 293280031Sdim 294280031Sdim if (req.emr_rc != 0) { 295249259Sdim rc = req.emr_rc; 296249259Sdim goto fail1; 297249259Sdim } 298296417Sdim 299296417Sdim if (req.emr_out_length_used < 300249259Sdim MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN) { 301249259Sdim rc = EMSGSIZE; 302249259Sdim goto fail2; 303249259Sdim } 304249259Sdim 305249259Sdim if (MCDI_OUT_DWORD(req, 306249259Sdim VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT) < 1) { 307249259Sdim rc = ENOENT; 308249259Sdim goto fail3; 309249259Sdim } 310249259Sdim 311249259Sdim if (mac_addrp != NULL) { 312249259Sdim uint8_t *addrp; 313296417Sdim 314296417Sdim addrp = MCDI_OUT2(req, uint8_t, 315296417Sdim VPORT_GET_MAC_ADDRESSES_OUT_MACADDR); 316296417Sdim 317296417Sdim EFX_MAC_ADDR_COPY(mac_addrp, addrp); 318296417Sdim } 319296417Sdim 320296417Sdim return (0); 321296417Sdim 322296417Sdimfail3: 323296417Sdim EFSYS_PROBE(fail3); 324296417Sdimfail2: 325249259Sdim EFSYS_PROBE(fail2); 326249259Sdimfail1: 327249259Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 328249259Sdim 329249259Sdim return (rc); 330249259Sdim} 331249259Sdim 332249259Sdim __checkReturn efx_rc_t 333249259Sdimefx_mcdi_get_clock( 334249259Sdim __in efx_nic_t *enp, 335288943Sdim __out uint32_t *sys_freqp) 336288943Sdim{ 337249259Sdim efx_mcdi_req_t req; 338249259Sdim uint8_t payload[MAX(MC_CMD_GET_CLOCK_IN_LEN, 339249259Sdim MC_CMD_GET_CLOCK_OUT_LEN)]; 340249259Sdim efx_rc_t rc; 341249259Sdim 342249259Sdim EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 343249259Sdim enp->en_family == EFX_FAMILY_MEDFORD); 344249259Sdim 345249259Sdim (void) memset(payload, 0, sizeof (payload)); 346249259Sdim req.emr_cmd = MC_CMD_GET_CLOCK; 347249259Sdim req.emr_in_buf = payload; 348249259Sdim req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN; 349249259Sdim req.emr_out_buf = payload; 350249259Sdim req.emr_out_length = MC_CMD_GET_CLOCK_OUT_LEN; 351249259Sdim 352249259Sdim efx_mcdi_execute(enp, &req); 353249259Sdim 354249259Sdim if (req.emr_rc != 0) { 355249259Sdim rc = req.emr_rc; 356296417Sdim goto fail1; 357296417Sdim } 358296417Sdim 359249259Sdim if (req.emr_out_length_used < MC_CMD_GET_CLOCK_OUT_LEN) { 360249259Sdim rc = EMSGSIZE; 361249259Sdim goto fail2; 362249259Sdim } 363249259Sdim 364249259Sdim *sys_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_SYS_FREQ); 365288943Sdim if (*sys_freqp == 0) { 366288943Sdim rc = EINVAL; 367249259Sdim goto fail3; 368296417Sdim } 369249259Sdim 370249259Sdim return (0); 371249259Sdim 372249259Sdimfail3: 373249259Sdim EFSYS_PROBE(fail3); 374249259Sdimfail2: 375249259Sdim EFSYS_PROBE(fail2); 376249259Sdimfail1: 377249259Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 378249259Sdim 379249259Sdim return (rc); 380249259Sdim} 381249259Sdim 382249259Sdim __checkReturn efx_rc_t 383249259Sdimefx_mcdi_get_vector_cfg( 384249259Sdim __in efx_nic_t *enp, 385249259Sdim __out_opt uint32_t *vec_basep, 386249259Sdim __out_opt uint32_t *pf_nvecp, 387296417Sdim __out_opt uint32_t *vf_nvecp) 388296417Sdim{ 389296417Sdim efx_mcdi_req_t req; 390296417Sdim uint8_t payload[MAX(MC_CMD_GET_VECTOR_CFG_IN_LEN, 391249259Sdim MC_CMD_GET_VECTOR_CFG_OUT_LEN)]; 392249259Sdim efx_rc_t rc; 393249259Sdim 394249259Sdim (void) memset(payload, 0, sizeof (payload)); 395249259Sdim req.emr_cmd = MC_CMD_GET_VECTOR_CFG; 396288943Sdim req.emr_in_buf = payload; 397288943Sdim req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN; 398249259Sdim req.emr_out_buf = payload; 399296417Sdim req.emr_out_length = MC_CMD_GET_VECTOR_CFG_OUT_LEN; 400249259Sdim 401249259Sdim efx_mcdi_execute(enp, &req); 402249259Sdim 403249259Sdim if (req.emr_rc != 0) { 404249259Sdim rc = req.emr_rc; 405249259Sdim goto fail1; 406249259Sdim } 407249259Sdim 408249259Sdim if (req.emr_out_length_used < MC_CMD_GET_VECTOR_CFG_OUT_LEN) { 409249259Sdim rc = EMSGSIZE; 410249259Sdim goto fail2; 411249259Sdim } 412249259Sdim 413249259Sdim if (vec_basep != NULL) 414249259Sdim *vec_basep = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VEC_BASE); 415249259Sdim if (pf_nvecp != NULL) 416249259Sdim *pf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_PF); 417249259Sdim if (vf_nvecp != NULL) 418249259Sdim *vf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_VF); 419249259Sdim 420249259Sdim return (0); 421249259Sdim 422249259Sdimfail2: 423249259Sdim EFSYS_PROBE(fail2); 424249259Sdimfail1: 425249259Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 426249259Sdim 427249259Sdim return (rc); 428249259Sdim} 429249259Sdim 430249259Sdimstatic __checkReturn efx_rc_t 431249259Sdimefx_mcdi_get_capabilities( 432249259Sdim __in efx_nic_t *enp, 433249259Sdim __out efx_dword_t *flagsp, 434249259Sdim __out efx_dword_t *flags2p) 435249259Sdim{ 436249259Sdim efx_mcdi_req_t req; 437249259Sdim uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN, 438249259Sdim MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)]; 439276479Sdim efx_rc_t rc; 440276479Sdim 441276479Sdim (void) memset(payload, 0, sizeof (payload)); 442276479Sdim req.emr_cmd = MC_CMD_GET_CAPABILITIES; 443276479Sdim req.emr_in_buf = payload; 444276479Sdim req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN; 445276479Sdim req.emr_out_buf = payload; 446276479Sdim req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN; 447276479Sdim 448276479Sdim efx_mcdi_execute(enp, &req); 449276479Sdim 450276479Sdim if (req.emr_rc != 0) { 451276479Sdim rc = req.emr_rc; 452276479Sdim goto fail1; 453276479Sdim } 454276479Sdim 455276479Sdim if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) { 456276479Sdim rc = EMSGSIZE; 457276479Sdim goto fail2; 458276479Sdim } 459249259Sdim 460249259Sdim *flagsp = *MCDI_OUT2(req, efx_dword_t, GET_CAPABILITIES_OUT_FLAGS1); 461249259Sdim 462249259Sdim if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) 463249259Sdim EFX_ZERO_DWORD(*flags2p); 464249259Sdim else 465249259Sdim *flags2p = *MCDI_OUT2(req, efx_dword_t, 466249259Sdim GET_CAPABILITIES_V2_OUT_FLAGS2); 467249259Sdim 468249259Sdim return (0); 469249259Sdim 470249259Sdimfail2: 471249259Sdim EFSYS_PROBE(fail2); 472249259Sdimfail1: 473249259Sdim EFSYS_PROBE1(fail1, efx_rc_t, rc); 474249259Sdim 475249259Sdim return (rc); 476249259Sdim} 477249259Sdim 478296417Sdim 479296417Sdimstatic __checkReturn efx_rc_t 480296417Sdimefx_mcdi_alloc_vis( 481249259Sdim __in efx_nic_t *enp, 482249259Sdim __in uint32_t min_vi_count, 483249259Sdim __in uint32_t max_vi_count, 484249259Sdim __out uint32_t *vi_basep, 485288943Sdim __out uint32_t *vi_countp, 486288943Sdim __out uint32_t *vi_shiftp) 487249259Sdim{ 488296417Sdim efx_mcdi_req_t req; 489249259Sdim uint8_t payload[MAX(MC_CMD_ALLOC_VIS_IN_LEN, 490249259Sdim MC_CMD_ALLOC_VIS_OUT_LEN)]; 491249259Sdim efx_rc_t rc; 492249259Sdim 493249259Sdim if (vi_countp == NULL) { 494249259Sdim rc = EINVAL; 495249259Sdim goto fail1; 496249259Sdim } 497249259Sdim 498249259Sdim (void) memset(payload, 0, sizeof (payload)); 499249259Sdim req.emr_cmd = MC_CMD_ALLOC_VIS; 500249259Sdim req.emr_in_buf = payload; 501249259Sdim req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN; 502249259Sdim req.emr_out_buf = payload; 503249259Sdim req.emr_out_length = MC_CMD_ALLOC_VIS_OUT_LEN; 504288943Sdim 505288943Sdim MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count); 506288943Sdim MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count); 507249259Sdim 508249259Sdim efx_mcdi_execute(enp, &req); 509249259Sdim 510249259Sdim if (req.emr_rc != 0) { 511249259Sdim rc = req.emr_rc; 512249259Sdim goto fail2; 513249259Sdim } 514249259Sdim 515249259Sdim if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) { 516296417Sdim rc = EMSGSIZE; 517296417Sdim goto fail3; 518296417Sdim } 519296417Sdim 520249259Sdim *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE); 521249259Sdim *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT); 522249259Sdim 523 /* Report VI_SHIFT if available (always zero for Huntington) */ 524 if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN) 525 *vi_shiftp = 0; 526 else 527 *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT); 528 529 return (0); 530 531fail3: 532 EFSYS_PROBE(fail3); 533fail2: 534 EFSYS_PROBE(fail2); 535fail1: 536 EFSYS_PROBE1(fail1, efx_rc_t, rc); 537 538 return (rc); 539} 540 541 542static __checkReturn efx_rc_t 543efx_mcdi_free_vis( 544 __in efx_nic_t *enp) 545{ 546 efx_mcdi_req_t req; 547 efx_rc_t rc; 548 549 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0); 550 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0); 551 552 req.emr_cmd = MC_CMD_FREE_VIS; 553 req.emr_in_buf = NULL; 554 req.emr_in_length = 0; 555 req.emr_out_buf = NULL; 556 req.emr_out_length = 0; 557 558 efx_mcdi_execute_quiet(enp, &req); 559 560 /* Ignore ELREADY (no allocated VIs, so nothing to free) */ 561 if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) { 562 rc = req.emr_rc; 563 goto fail1; 564 } 565 566 return (0); 567 568fail1: 569 EFSYS_PROBE1(fail1, efx_rc_t, rc); 570 571 return (rc); 572} 573 574 575static __checkReturn efx_rc_t 576efx_mcdi_alloc_piobuf( 577 __in efx_nic_t *enp, 578 __out efx_piobuf_handle_t *handlep) 579{ 580 efx_mcdi_req_t req; 581 uint8_t payload[MAX(MC_CMD_ALLOC_PIOBUF_IN_LEN, 582 MC_CMD_ALLOC_PIOBUF_OUT_LEN)]; 583 efx_rc_t rc; 584 585 if (handlep == NULL) { 586 rc = EINVAL; 587 goto fail1; 588 } 589 590 (void) memset(payload, 0, sizeof (payload)); 591 req.emr_cmd = MC_CMD_ALLOC_PIOBUF; 592 req.emr_in_buf = payload; 593 req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN; 594 req.emr_out_buf = payload; 595 req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN; 596 597 efx_mcdi_execute_quiet(enp, &req); 598 599 if (req.emr_rc != 0) { 600 rc = req.emr_rc; 601 goto fail2; 602 } 603 604 if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) { 605 rc = EMSGSIZE; 606 goto fail3; 607 } 608 609 *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE); 610 611 return (0); 612 613fail3: 614 EFSYS_PROBE(fail3); 615fail2: 616 EFSYS_PROBE(fail2); 617fail1: 618 EFSYS_PROBE1(fail1, efx_rc_t, rc); 619 620 return (rc); 621} 622 623static __checkReturn efx_rc_t 624efx_mcdi_free_piobuf( 625 __in efx_nic_t *enp, 626 __in efx_piobuf_handle_t handle) 627{ 628 efx_mcdi_req_t req; 629 uint8_t payload[MAX(MC_CMD_FREE_PIOBUF_IN_LEN, 630 MC_CMD_FREE_PIOBUF_OUT_LEN)]; 631 efx_rc_t rc; 632 633 (void) memset(payload, 0, sizeof (payload)); 634 req.emr_cmd = MC_CMD_FREE_PIOBUF; 635 req.emr_in_buf = payload; 636 req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN; 637 req.emr_out_buf = payload; 638 req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN; 639 640 MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle); 641 642 efx_mcdi_execute_quiet(enp, &req); 643 644 if (req.emr_rc != 0) { 645 rc = req.emr_rc; 646 goto fail1; 647 } 648 649 return (0); 650 651fail1: 652 EFSYS_PROBE1(fail1, efx_rc_t, rc); 653 654 return (rc); 655} 656 657static __checkReturn efx_rc_t 658efx_mcdi_link_piobuf( 659 __in efx_nic_t *enp, 660 __in uint32_t vi_index, 661 __in efx_piobuf_handle_t handle) 662{ 663 efx_mcdi_req_t req; 664 uint8_t payload[MAX(MC_CMD_LINK_PIOBUF_IN_LEN, 665 MC_CMD_LINK_PIOBUF_OUT_LEN)]; 666 efx_rc_t rc; 667 668 (void) memset(payload, 0, sizeof (payload)); 669 req.emr_cmd = MC_CMD_LINK_PIOBUF; 670 req.emr_in_buf = payload; 671 req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN; 672 req.emr_out_buf = payload; 673 req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN; 674 675 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle); 676 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index); 677 678 efx_mcdi_execute(enp, &req); 679 680 if (req.emr_rc != 0) { 681 rc = req.emr_rc; 682 goto fail1; 683 } 684 685 return (0); 686 687fail1: 688 EFSYS_PROBE1(fail1, efx_rc_t, rc); 689 690 return (rc); 691} 692 693static __checkReturn efx_rc_t 694efx_mcdi_unlink_piobuf( 695 __in efx_nic_t *enp, 696 __in uint32_t vi_index) 697{ 698 efx_mcdi_req_t req; 699 uint8_t payload[MAX(MC_CMD_UNLINK_PIOBUF_IN_LEN, 700 MC_CMD_UNLINK_PIOBUF_OUT_LEN)]; 701 efx_rc_t rc; 702 703 (void) memset(payload, 0, sizeof (payload)); 704 req.emr_cmd = MC_CMD_UNLINK_PIOBUF; 705 req.emr_in_buf = payload; 706 req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN; 707 req.emr_out_buf = payload; 708 req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN; 709 710 MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index); 711 712 efx_mcdi_execute(enp, &req); 713 714 if (req.emr_rc != 0) { 715 rc = req.emr_rc; 716 goto fail1; 717 } 718 719 return (0); 720 721fail1: 722 EFSYS_PROBE1(fail1, efx_rc_t, rc); 723 724 return (rc); 725} 726 727static void 728ef10_nic_alloc_piobufs( 729 __in efx_nic_t *enp, 730 __in uint32_t max_piobuf_count) 731{ 732 efx_piobuf_handle_t *handlep; 733 unsigned int i; 734 efx_rc_t rc; 735 736 EFSYS_ASSERT3U(max_piobuf_count, <=, 737 EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle)); 738 739 enp->en_arch.ef10.ena_piobuf_count = 0; 740 741 for (i = 0; i < max_piobuf_count; i++) { 742 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 743 744 if ((rc = efx_mcdi_alloc_piobuf(enp, handlep)) != 0) 745 goto fail1; 746 747 enp->en_arch.ef10.ena_pio_alloc_map[i] = 0; 748 enp->en_arch.ef10.ena_piobuf_count++; 749 } 750 751 return; 752 753fail1: 754 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 755 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 756 757 efx_mcdi_free_piobuf(enp, *handlep); 758 *handlep = EFX_PIOBUF_HANDLE_INVALID; 759 } 760 enp->en_arch.ef10.ena_piobuf_count = 0; 761} 762 763 764static void 765ef10_nic_free_piobufs( 766 __in efx_nic_t *enp) 767{ 768 efx_piobuf_handle_t *handlep; 769 unsigned int i; 770 771 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 772 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 773 774 efx_mcdi_free_piobuf(enp, *handlep); 775 *handlep = EFX_PIOBUF_HANDLE_INVALID; 776 } 777 enp->en_arch.ef10.ena_piobuf_count = 0; 778} 779 780/* Sub-allocate a block from a piobuf */ 781 __checkReturn efx_rc_t 782ef10_nic_pio_alloc( 783 __inout efx_nic_t *enp, 784 __out uint32_t *bufnump, 785 __out efx_piobuf_handle_t *handlep, 786 __out uint32_t *blknump, 787 __out uint32_t *offsetp, 788 __out size_t *sizep) 789{ 790 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 791 efx_drv_cfg_t *edcp = &enp->en_drv_cfg; 792 uint32_t blk_per_buf; 793 uint32_t buf, blk; 794 efx_rc_t rc; 795 796 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 797 enp->en_family == EFX_FAMILY_MEDFORD); 798 EFSYS_ASSERT(bufnump); 799 EFSYS_ASSERT(handlep); 800 EFSYS_ASSERT(blknump); 801 EFSYS_ASSERT(offsetp); 802 EFSYS_ASSERT(sizep); 803 804 if ((edcp->edc_pio_alloc_size == 0) || 805 (enp->en_arch.ef10.ena_piobuf_count == 0)) { 806 rc = ENOMEM; 807 goto fail1; 808 } 809 blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size; 810 811 for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) { 812 uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf]; 813 814 if (~(*map) == 0) 815 continue; 816 817 EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map))); 818 for (blk = 0; blk < blk_per_buf; blk++) { 819 if ((*map & (1u << blk)) == 0) { 820 *map |= (1u << blk); 821 goto done; 822 } 823 } 824 } 825 rc = ENOMEM; 826 goto fail2; 827 828done: 829 *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf]; 830 *bufnump = buf; 831 *blknump = blk; 832 *sizep = edcp->edc_pio_alloc_size; 833 *offsetp = blk * (*sizep); 834 835 return (0); 836 837fail2: 838 EFSYS_PROBE(fail2); 839fail1: 840 EFSYS_PROBE1(fail1, efx_rc_t, rc); 841 842 return (rc); 843} 844 845/* Free a piobuf sub-allocated block */ 846 __checkReturn efx_rc_t 847ef10_nic_pio_free( 848 __inout efx_nic_t *enp, 849 __in uint32_t bufnum, 850 __in uint32_t blknum) 851{ 852 uint32_t *map; 853 efx_rc_t rc; 854 855 if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) || 856 (blknum >= (8 * sizeof (*map)))) { 857 rc = EINVAL; 858 goto fail1; 859 } 860 861 map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum]; 862 if ((*map & (1u << blknum)) == 0) { 863 rc = ENOENT; 864 goto fail2; 865 } 866 *map &= ~(1u << blknum); 867 868 return (0); 869 870fail2: 871 EFSYS_PROBE(fail2); 872fail1: 873 EFSYS_PROBE1(fail1, efx_rc_t, rc); 874 875 return (rc); 876} 877 878 __checkReturn efx_rc_t 879ef10_nic_pio_link( 880 __inout efx_nic_t *enp, 881 __in uint32_t vi_index, 882 __in efx_piobuf_handle_t handle) 883{ 884 return (efx_mcdi_link_piobuf(enp, vi_index, handle)); 885} 886 887 __checkReturn efx_rc_t 888ef10_nic_pio_unlink( 889 __inout efx_nic_t *enp, 890 __in uint32_t vi_index) 891{ 892 return (efx_mcdi_unlink_piobuf(enp, vi_index)); 893} 894 895 __checkReturn efx_rc_t 896ef10_get_datapath_caps( 897 __in efx_nic_t *enp) 898{ 899 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 900 efx_dword_t datapath_capabilities; 901 efx_dword_t datapath_capabilities_v2; 902 efx_rc_t rc; 903 904 if ((rc = efx_mcdi_get_capabilities(enp, &datapath_capabilities, 905 &datapath_capabilities_v2)) != 0) 906 goto fail1; 907 908 /* 909 * Huntington RXDP firmware inserts a 0 or 14 byte prefix. 910 * We only support the 14 byte prefix here. 911 */ 912 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 913 GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14) != 1) { 914 rc = ENOTSUP; 915 goto fail2; 916 } 917 encp->enc_rx_prefix_size = 14; 918 919 /* Check if the firmware supports TSO */ 920 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 921 GET_CAPABILITIES_OUT_TX_TSO) == 1) 922 encp->enc_fw_assisted_tso_enabled = B_TRUE; 923 else 924 encp->enc_fw_assisted_tso_enabled = B_FALSE; 925 926 /* Check if the firmware supports FATSOv2 */ 927 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities_v2, 928 GET_CAPABILITIES_V2_OUT_TX_TSO_V2) == 1) 929 encp->enc_fw_assisted_tso_v2_enabled = B_TRUE; 930 else 931 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE; 932 933 /* Check if the firmware has vadapter/vport/vswitch support */ 934 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 935 GET_CAPABILITIES_OUT_EVB) == 1) 936 encp->enc_datapath_cap_evb = B_TRUE; 937 else 938 encp->enc_datapath_cap_evb = B_FALSE; 939 940 /* Check if the firmware supports VLAN insertion */ 941 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 942 GET_CAPABILITIES_OUT_TX_VLAN_INSERTION) == 1) 943 encp->enc_hw_tx_insert_vlan_enabled = B_TRUE; 944 else 945 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; 946 947 /* Check if the firmware supports RX event batching */ 948 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 949 GET_CAPABILITIES_OUT_RX_BATCHING) == 1) { 950 encp->enc_rx_batching_enabled = B_TRUE; 951 encp->enc_rx_batch_max = 16; 952 } else { 953 encp->enc_rx_batching_enabled = B_FALSE; 954 } 955 956 /* Check if the firmware supports disabling scatter on RXQs */ 957 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 958 GET_CAPABILITIES_OUT_RX_DISABLE_SCATTER) == 1) { 959 encp->enc_rx_disable_scatter_supported = B_TRUE; 960 } else { 961 encp->enc_rx_disable_scatter_supported = B_FALSE; 962 } 963 964 /* Check if the firmware supports set mac with running filters */ 965 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 966 GET_CAPABILITIES_OUT_VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) 967 == 1) { 968 encp->enc_allow_set_mac_with_installed_filters = B_TRUE; 969 } else { 970 encp->enc_allow_set_mac_with_installed_filters = B_FALSE; 971 } 972 973 return (0); 974 975fail2: 976 EFSYS_PROBE(fail2); 977fail1: 978 EFSYS_PROBE1(fail1, efx_rc_t, rc); 979 980 return (rc); 981} 982 983 984 __checkReturn efx_rc_t 985ef10_get_privilege_mask( 986 __in efx_nic_t *enp, 987 __out uint32_t *maskp) 988{ 989 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 990 uint32_t mask; 991 efx_rc_t rc; 992 993 if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf, 994 &mask)) != 0) { 995 if (rc != ENOTSUP) 996 goto fail1; 997 998 /* Fallback for old firmware without privilege mask support */ 999 if (EFX_PCI_FUNCTION_IS_PF(encp)) { 1000 /* Assume PF has admin privilege */ 1001 mask = EF10_LEGACY_PF_PRIVILEGE_MASK; 1002 } else { 1003 /* VF is always unprivileged by default */ 1004 mask = EF10_LEGACY_VF_PRIVILEGE_MASK; 1005 } 1006 } 1007 1008 *maskp = mask; 1009 1010 return (0); 1011 1012fail1: 1013 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1014 1015 return (rc); 1016} 1017 1018 1019/* 1020 * The external port mapping is a one-based numbering of the external 1021 * connectors on the board. It does not distinguish off-board separated 1022 * outputs such as multi-headed cables. 1023 * The number of ports that map to each external port connector 1024 * on the board is determined by the chip family and the port modes to 1025 * which the NIC can be configured. The mapping table lists modes with 1026 * port numbering requirements in increasing order. 1027 */ 1028static struct { 1029 efx_family_t family; 1030 uint32_t modes_mask; 1031 uint32_t stride; 1032} __ef10_external_port_mappings[] = { 1033 /* Supported modes requiring 1 output per port */ 1034 { 1035 EFX_FAMILY_HUNTINGTON, 1036 (1 << TLV_PORT_MODE_10G) | 1037 (1 << TLV_PORT_MODE_10G_10G) | 1038 (1 << TLV_PORT_MODE_10G_10G_10G_10G), 1039 1 1040 }, 1041 { 1042 EFX_FAMILY_MEDFORD, 1043 (1 << TLV_PORT_MODE_10G) | 1044 (1 << TLV_PORT_MODE_10G_10G) | 1045 (1 << TLV_PORT_MODE_10G_10G_10G_10G), 1046 1 1047 }, 1048 /* Supported modes requiring 2 outputs per port */ 1049 { 1050 EFX_FAMILY_HUNTINGTON, 1051 (1 << TLV_PORT_MODE_40G) | 1052 (1 << TLV_PORT_MODE_40G_40G) | 1053 (1 << TLV_PORT_MODE_40G_10G_10G) | 1054 (1 << TLV_PORT_MODE_10G_10G_40G), 1055 2 1056 }, 1057 { 1058 EFX_FAMILY_MEDFORD, 1059 (1 << TLV_PORT_MODE_40G) | 1060 (1 << TLV_PORT_MODE_40G_40G) | 1061 (1 << TLV_PORT_MODE_40G_10G_10G) | 1062 (1 << TLV_PORT_MODE_10G_10G_40G), 1063 2 1064 }, 1065 /* Supported modes requiring 4 outputs per port */ 1066 { 1067 EFX_FAMILY_MEDFORD, 1068 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) | 1069 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2), 1070 4 1071 }, 1072}; 1073 1074 __checkReturn efx_rc_t 1075ef10_external_port_mapping( 1076 __in efx_nic_t *enp, 1077 __in uint32_t port, 1078 __out uint8_t *external_portp) 1079{ 1080 efx_rc_t rc; 1081 int i; 1082 uint32_t port_modes; 1083 uint32_t matches; 1084 uint32_t stride = 1; /* default 1-1 mapping */ 1085 1086 if ((rc = efx_mcdi_get_port_modes(enp, &port_modes)) != 0) { 1087 /* No port mode information available - use default mapping */ 1088 goto out; 1089 } 1090 1091 /* 1092 * Infer the internal port -> external port mapping from 1093 * the possible port modes for this NIC. 1094 */ 1095 for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) { 1096 if (__ef10_external_port_mappings[i].family != 1097 enp->en_family) 1098 continue; 1099 matches = (__ef10_external_port_mappings[i].modes_mask & 1100 port_modes); 1101 if (matches != 0) { 1102 stride = __ef10_external_port_mappings[i].stride; 1103 port_modes &= ~matches; 1104 } 1105 } 1106 1107 if (port_modes != 0) { 1108 /* Some advertised modes are not supported */ 1109 rc = ENOTSUP; 1110 goto fail1; 1111 } 1112 1113out: 1114 /* 1115 * Scale as required by last matched mode and then convert to 1116 * one-based numbering 1117 */ 1118 *external_portp = (uint8_t)(port / stride) + 1; 1119 return (0); 1120 1121fail1: 1122 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1123 1124 return (rc); 1125} 1126 1127 __checkReturn efx_rc_t 1128hunt_board_cfg( 1129 __in efx_nic_t *enp) 1130{ 1131 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 1132 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1133 uint8_t mac_addr[6]; 1134 uint32_t board_type = 0; 1135 ef10_link_state_t els; 1136 efx_port_t *epp = &(enp->en_port); 1137 uint32_t port; 1138 uint32_t pf; 1139 uint32_t vf; 1140 uint32_t mask; 1141 uint32_t flags; 1142 uint32_t sysclk; 1143 uint32_t base, nvec; 1144 efx_rc_t rc; 1145 1146 if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0) 1147 goto fail1; 1148 1149 /* 1150 * NOTE: The MCDI protocol numbers ports from zero. 1151 * The common code MCDI interface numbers ports from one. 1152 */ 1153 emip->emi_port = port + 1; 1154 1155 if ((rc = ef10_external_port_mapping(enp, port, 1156 &encp->enc_external_port)) != 0) 1157 goto fail2; 1158 1159 /* 1160 * Get PCIe function number from firmware (used for 1161 * per-function privilege and dynamic config info). 1162 * - PCIe PF: pf = PF number, vf = 0xffff. 1163 * - PCIe VF: pf = parent PF, vf = VF number. 1164 */ 1165 if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0) 1166 goto fail3; 1167 1168 encp->enc_pf = pf; 1169 encp->enc_vf = vf; 1170 1171 /* MAC address for this function */ 1172 if (EFX_PCI_FUNCTION_IS_PF(encp)) { 1173 rc = efx_mcdi_get_mac_address_pf(enp, mac_addr); 1174 if ((rc == 0) && (mac_addr[0] & 0x02)) { 1175 /* 1176 * If the static config does not include a global MAC 1177 * address pool then the board may return a locally 1178 * administered MAC address (this should only happen on 1179 * incorrectly programmed boards). 1180 */ 1181 rc = EINVAL; 1182 } 1183 } else { 1184 rc = efx_mcdi_get_mac_address_vf(enp, mac_addr); 1185 } 1186 if (rc != 0) 1187 goto fail4; 1188 1189 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); 1190 1191 /* Board configuration */ 1192 rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL); 1193 if (rc != 0) { 1194 /* Unprivileged functions may not be able to read board cfg */ 1195 if (rc == EACCES) 1196 board_type = 0; 1197 else 1198 goto fail5; 1199 } 1200 1201 encp->enc_board_type = board_type; 1202 encp->enc_clk_mult = 1; /* not used for Huntington */ 1203 1204 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ 1205 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) 1206 goto fail6; 1207 1208 /* Obtain the default PHY advertised capabilities */ 1209 if ((rc = hunt_phy_get_link(enp, &els)) != 0) 1210 goto fail7; 1211 epp->ep_default_adv_cap_mask = els.els_adv_cap_mask; 1212 epp->ep_adv_cap_mask = els.els_adv_cap_mask; 1213 1214 /* 1215 * Enable firmware workarounds for hardware errata. 1216 * Expected responses are: 1217 * - 0 (zero): 1218 * Success: workaround enabled or disabled as requested. 1219 * - MC_CMD_ERR_ENOSYS (reported as ENOTSUP): 1220 * Firmware does not support the MC_CMD_WORKAROUND request. 1221 * (assume that the workaround is not supported). 1222 * - MC_CMD_ERR_ENOENT (reported as ENOENT): 1223 * Firmware does not support the requested workaround. 1224 * - MC_CMD_ERR_EPERM (reported as EACCES): 1225 * Unprivileged function cannot enable/disable workarounds. 1226 * 1227 * See efx_mcdi_request_errcode() for MCDI error translations. 1228 */ 1229 1230 /* 1231 * If the bug35388 workaround is enabled, then use an indirect access 1232 * method to avoid unsafe EVQ writes. 1233 */ 1234 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG35388, B_TRUE, 1235 NULL); 1236 if ((rc == 0) || (rc == EACCES)) 1237 encp->enc_bug35388_workaround = B_TRUE; 1238 else if ((rc == ENOTSUP) || (rc == ENOENT)) 1239 encp->enc_bug35388_workaround = B_FALSE; 1240 else 1241 goto fail8; 1242 1243 /* 1244 * If the bug41750 workaround is enabled, then do not test interrupts, 1245 * as the test will fail (seen with Greenport controllers). 1246 */ 1247 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG41750, B_TRUE, 1248 NULL); 1249 if (rc == 0) { 1250 encp->enc_bug41750_workaround = B_TRUE; 1251 } else if (rc == EACCES) { 1252 /* Assume a controller with 40G ports needs the workaround. */ 1253 if (epp->ep_default_adv_cap_mask & EFX_PHY_CAP_40000FDX) 1254 encp->enc_bug41750_workaround = B_TRUE; 1255 else 1256 encp->enc_bug41750_workaround = B_FALSE; 1257 } else if ((rc == ENOTSUP) || (rc == ENOENT)) { 1258 encp->enc_bug41750_workaround = B_FALSE; 1259 } else { 1260 goto fail9; 1261 } 1262 if (EFX_PCI_FUNCTION_IS_VF(encp)) { 1263 /* Interrupt testing does not work for VFs. See bug50084. */ 1264 encp->enc_bug41750_workaround = B_TRUE; 1265 } 1266 1267 /* 1268 * If the bug26807 workaround is enabled, then firmware has enabled 1269 * support for chained multicast filters. Firmware will reset (FLR) 1270 * functions which have filters in the hardware filter table when the 1271 * workaround is enabled/disabled. 1272 * 1273 * We must recheck if the workaround is enabled after inserting the 1274 * first hardware filter, in case it has been changed since this check. 1275 */ 1276 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807, 1277 B_TRUE, &flags); 1278 if (rc == 0) { 1279 encp->enc_bug26807_workaround = B_TRUE; 1280 if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) { 1281 /* 1282 * Other functions had installed filters before the 1283 * workaround was enabled, and they have been reset 1284 * by firmware. 1285 */ 1286 EFSYS_PROBE(bug26807_workaround_flr_done); 1287 /* FIXME: bump MC warm boot count ? */ 1288 } 1289 } else if (rc == EACCES) { 1290 /* 1291 * Unprivileged functions cannot enable the workaround in older 1292 * firmware. 1293 */ 1294 encp->enc_bug26807_workaround = B_FALSE; 1295 } else if ((rc == ENOTSUP) || (rc == ENOENT)) { 1296 encp->enc_bug26807_workaround = B_FALSE; 1297 } else { 1298 goto fail10; 1299 } 1300 1301 /* Get sysclk frequency (in MHz). */ 1302 if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0) 1303 goto fail11; 1304 1305 /* 1306 * The timer quantum is 1536 sysclk cycles, documented for the 1307 * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units. 1308 */ 1309 encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */ 1310 if (encp->enc_bug35388_workaround) { 1311 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 1312 ERF_DD_EVQ_IND_TIMER_VAL_WIDTH) / 1000; 1313 } else { 1314 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 1315 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; 1316 } 1317 1318 /* Check capabilities of running datapath firmware */ 1319 if ((rc = ef10_get_datapath_caps(enp)) != 0) 1320 goto fail12; 1321 1322 /* Alignment for receive packet DMA buffers */ 1323 encp->enc_rx_buf_align_start = 1; 1324 encp->enc_rx_buf_align_end = 64; /* RX DMA end padding */ 1325 1326 /* Alignment for WPTR updates */ 1327 encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN; 1328 1329 /* 1330 * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use 1331 * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available 1332 * resources (allocated to this PCIe function), which is zero until 1333 * after we have allocated VIs. 1334 */ 1335 encp->enc_evq_limit = 1024; 1336 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET; 1337 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET; 1338 1339 encp->enc_buftbl_limit = 0xFFFFFFFF; 1340 1341 encp->enc_piobuf_limit = HUNT_PIOBUF_NBUFS; 1342 encp->enc_piobuf_size = HUNT_PIOBUF_SIZE; 1343 encp->enc_piobuf_min_alloc_size = HUNT_MIN_PIO_ALLOC_SIZE; 1344 1345 /* 1346 * Get the current privilege mask. Note that this may be modified 1347 * dynamically, so this value is informational only. DO NOT use 1348 * the privilege mask to check for sufficient privileges, as that 1349 * can result in time-of-check/time-of-use bugs. 1350 */ 1351 if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0) 1352 goto fail13; 1353 encp->enc_privilege_mask = mask; 1354 1355 /* Get interrupt vector limits */ 1356 if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) { 1357 if (EFX_PCI_FUNCTION_IS_PF(encp)) 1358 goto fail14; 1359 1360 /* Ignore error (cannot query vector limits from a VF). */ 1361 base = 0; 1362 nvec = 1024; 1363 } 1364 encp->enc_intr_vec_base = base; 1365 encp->enc_intr_limit = nvec; 1366 1367 /* 1368 * Maximum number of bytes into the frame the TCP header can start for 1369 * firmware assisted TSO to work. 1370 */ 1371 encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT; 1372 1373 return (0); 1374 1375fail14: 1376 EFSYS_PROBE(fail14); 1377fail13: 1378 EFSYS_PROBE(fail13); 1379fail12: 1380 EFSYS_PROBE(fail12); 1381fail11: 1382 EFSYS_PROBE(fail11); 1383fail10: 1384 EFSYS_PROBE(fail10); 1385fail9: 1386 EFSYS_PROBE(fail9); 1387fail8: 1388 EFSYS_PROBE(fail8); 1389fail7: 1390 EFSYS_PROBE(fail7); 1391fail6: 1392 EFSYS_PROBE(fail6); 1393fail5: 1394 EFSYS_PROBE(fail5); 1395fail4: 1396 EFSYS_PROBE(fail4); 1397fail3: 1398 EFSYS_PROBE(fail3); 1399fail2: 1400 EFSYS_PROBE(fail2); 1401fail1: 1402 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1403 1404 return (rc); 1405} 1406 1407 1408 __checkReturn efx_rc_t 1409ef10_nic_probe( 1410 __in efx_nic_t *enp) 1411{ 1412 efx_nic_ops_t *enop = enp->en_enop; 1413 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1414 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1415 efx_rc_t rc; 1416 1417 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1418 enp->en_family == EFX_FAMILY_MEDFORD); 1419 1420 /* Read and clear any assertion state */ 1421 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1422 goto fail1; 1423 1424 /* Exit the assertion handler */ 1425 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1426 if (rc != EACCES) 1427 goto fail2; 1428 1429 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 1430 goto fail3; 1431 1432 if ((rc = enop->eno_board_cfg(enp)) != 0) 1433 if (rc != EACCES) 1434 goto fail4; 1435 1436 /* 1437 * Set default driver config limits (based on board config). 1438 * 1439 * FIXME: For now allocate a fixed number of VIs which is likely to be 1440 * sufficient and small enough to allow multiple functions on the same 1441 * port. 1442 */ 1443 edcp->edc_min_vi_count = edcp->edc_max_vi_count = 1444 MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit)); 1445 1446 /* The client driver must configure and enable PIO buffer support */ 1447 edcp->edc_max_piobuf_count = 0; 1448 edcp->edc_pio_alloc_size = 0; 1449 1450#if EFSYS_OPT_MAC_STATS 1451 /* Wipe the MAC statistics */ 1452 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 1453 goto fail5; 1454#endif 1455 1456#if EFSYS_OPT_LOOPBACK 1457 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 1458 goto fail6; 1459#endif 1460 1461#if EFSYS_OPT_MON_STATS 1462 if ((rc = mcdi_mon_cfg_build(enp)) != 0) { 1463 /* Unprivileged functions do not have access to sensors */ 1464 if (rc != EACCES) 1465 goto fail7; 1466 } 1467#endif 1468 1469 encp->enc_features = enp->en_features; 1470 1471 return (0); 1472 1473#if EFSYS_OPT_MON_STATS 1474fail7: 1475 EFSYS_PROBE(fail7); 1476#endif 1477#if EFSYS_OPT_LOOPBACK 1478fail6: 1479 EFSYS_PROBE(fail6); 1480#endif 1481#if EFSYS_OPT_MAC_STATS 1482fail5: 1483 EFSYS_PROBE(fail5); 1484#endif 1485fail4: 1486 EFSYS_PROBE(fail4); 1487fail3: 1488 EFSYS_PROBE(fail3); 1489fail2: 1490 EFSYS_PROBE(fail2); 1491fail1: 1492 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1493 1494 return (rc); 1495} 1496 1497 __checkReturn efx_rc_t 1498ef10_nic_set_drv_limits( 1499 __inout efx_nic_t *enp, 1500 __in efx_drv_limits_t *edlp) 1501{ 1502 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1503 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1504 uint32_t min_evq_count, max_evq_count; 1505 uint32_t min_rxq_count, max_rxq_count; 1506 uint32_t min_txq_count, max_txq_count; 1507 efx_rc_t rc; 1508 1509 if (edlp == NULL) { 1510 rc = EINVAL; 1511 goto fail1; 1512 } 1513 1514 /* Get minimum required and maximum usable VI limits */ 1515 min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit); 1516 min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit); 1517 min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit); 1518 1519 edcp->edc_min_vi_count = 1520 MAX(min_evq_count, MAX(min_rxq_count, min_txq_count)); 1521 1522 max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit); 1523 max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit); 1524 max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit); 1525 1526 edcp->edc_max_vi_count = 1527 MAX(max_evq_count, MAX(max_rxq_count, max_txq_count)); 1528 1529 /* 1530 * Check limits for sub-allocated piobuf blocks. 1531 * PIO is optional, so don't fail if the limits are incorrect. 1532 */ 1533 if ((encp->enc_piobuf_size == 0) || 1534 (encp->enc_piobuf_limit == 0) || 1535 (edlp->edl_min_pio_alloc_size == 0) || 1536 (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) { 1537 /* Disable PIO */ 1538 edcp->edc_max_piobuf_count = 0; 1539 edcp->edc_pio_alloc_size = 0; 1540 } else { 1541 uint32_t blk_size, blk_count, blks_per_piobuf; 1542 1543 blk_size = 1544 MAX(edlp->edl_min_pio_alloc_size, 1545 encp->enc_piobuf_min_alloc_size); 1546 1547 blks_per_piobuf = encp->enc_piobuf_size / blk_size; 1548 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32); 1549 1550 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf); 1551 1552 /* A zero max pio alloc count means unlimited */ 1553 if ((edlp->edl_max_pio_alloc_count > 0) && 1554 (edlp->edl_max_pio_alloc_count < blk_count)) { 1555 blk_count = edlp->edl_max_pio_alloc_count; 1556 } 1557 1558 edcp->edc_pio_alloc_size = blk_size; 1559 edcp->edc_max_piobuf_count = 1560 (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf; 1561 } 1562 1563 return (0); 1564 1565fail1: 1566 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1567 1568 return (rc); 1569} 1570 1571 1572 __checkReturn efx_rc_t 1573ef10_nic_reset( 1574 __in efx_nic_t *enp) 1575{ 1576 efx_mcdi_req_t req; 1577 uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN, 1578 MC_CMD_ENTITY_RESET_OUT_LEN)]; 1579 efx_rc_t rc; 1580 1581 /* ef10_nic_reset() is called to recover from BADASSERT failures. */ 1582 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1583 goto fail1; 1584 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1585 goto fail2; 1586 1587 (void) memset(payload, 0, sizeof (payload)); 1588 req.emr_cmd = MC_CMD_ENTITY_RESET; 1589 req.emr_in_buf = payload; 1590 req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN; 1591 req.emr_out_buf = payload; 1592 req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN; 1593 1594 MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG, 1595 ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1); 1596 1597 efx_mcdi_execute(enp, &req); 1598 1599 if (req.emr_rc != 0) { 1600 rc = req.emr_rc; 1601 goto fail3; 1602 } 1603 1604 /* Clear RX/TX DMA queue errors */ 1605 enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR); 1606 1607 return (0); 1608 1609fail3: 1610 EFSYS_PROBE(fail3); 1611fail2: 1612 EFSYS_PROBE(fail2); 1613fail1: 1614 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1615 1616 return (rc); 1617} 1618 1619 __checkReturn efx_rc_t 1620ef10_nic_init( 1621 __in efx_nic_t *enp) 1622{ 1623 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1624 uint32_t min_vi_count, max_vi_count; 1625 uint32_t vi_count, vi_base, vi_shift; 1626 uint32_t i; 1627 uint32_t retry; 1628 uint32_t delay_us; 1629 efx_rc_t rc; 1630 1631 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1632 enp->en_family == EFX_FAMILY_MEDFORD); 1633 1634 /* Enable reporting of some events (e.g. link change) */ 1635 if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 1636 goto fail1; 1637 1638 /* Allocate (optional) on-chip PIO buffers */ 1639 ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count); 1640 1641 /* 1642 * For best performance, PIO writes should use a write-combined 1643 * (WC) memory mapping. Using a separate WC mapping for the PIO 1644 * aperture of each VI would be a burden to drivers (and not 1645 * possible if the host page size is >4Kbyte). 1646 * 1647 * To avoid this we use a single uncached (UC) mapping for VI 1648 * register access, and a single WC mapping for extra VIs used 1649 * for PIO writes. 1650 * 1651 * Each piobuf must be linked to a VI in the WC mapping, and to 1652 * each VI that is using a sub-allocated block from the piobuf. 1653 */ 1654 min_vi_count = edcp->edc_min_vi_count; 1655 max_vi_count = 1656 edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count; 1657 1658 /* Ensure that the previously attached driver's VIs are freed */ 1659 if ((rc = efx_mcdi_free_vis(enp)) != 0) 1660 goto fail2; 1661 1662 /* 1663 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this 1664 * fails then retrying the request for fewer VI resources may succeed. 1665 */ 1666 vi_count = 0; 1667 if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count, 1668 &vi_base, &vi_count, &vi_shift)) != 0) 1669 goto fail3; 1670 1671 EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count); 1672 1673 if (vi_count < min_vi_count) { 1674 rc = ENOMEM; 1675 goto fail4; 1676 } 1677 1678 enp->en_arch.ef10.ena_vi_base = vi_base; 1679 enp->en_arch.ef10.ena_vi_count = vi_count; 1680 enp->en_arch.ef10.ena_vi_shift = vi_shift; 1681 1682 if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) { 1683 /* Not enough extra VIs to map piobufs */ 1684 ef10_nic_free_piobufs(enp); 1685 } 1686 1687 enp->en_arch.ef10.ena_pio_write_vi_base = 1688 vi_count - enp->en_arch.ef10.ena_piobuf_count; 1689 1690 /* Save UC memory mapping details */ 1691 enp->en_arch.ef10.ena_uc_mem_map_offset = 0; 1692 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1693 enp->en_arch.ef10.ena_uc_mem_map_size = 1694 (ER_DZ_TX_PIOBUF_STEP * 1695 enp->en_arch.ef10.ena_pio_write_vi_base); 1696 } else { 1697 enp->en_arch.ef10.ena_uc_mem_map_size = 1698 (ER_DZ_TX_PIOBUF_STEP * 1699 enp->en_arch.ef10.ena_vi_count); 1700 } 1701 1702 /* Save WC memory mapping details */ 1703 enp->en_arch.ef10.ena_wc_mem_map_offset = 1704 enp->en_arch.ef10.ena_uc_mem_map_offset + 1705 enp->en_arch.ef10.ena_uc_mem_map_size; 1706 1707 enp->en_arch.ef10.ena_wc_mem_map_size = 1708 (ER_DZ_TX_PIOBUF_STEP * 1709 enp->en_arch.ef10.ena_piobuf_count); 1710 1711 /* Link piobufs to extra VIs in WC mapping */ 1712 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1713 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1714 rc = efx_mcdi_link_piobuf(enp, 1715 enp->en_arch.ef10.ena_pio_write_vi_base + i, 1716 enp->en_arch.ef10.ena_piobuf_handle[i]); 1717 if (rc != 0) 1718 break; 1719 } 1720 } 1721 1722 /* 1723 * Allocate a vAdaptor attached to our upstream vPort/pPort. 1724 * 1725 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF 1726 * driver has yet to bring up the EVB port. See bug 56147. In this case, 1727 * retry the request several times after waiting a while. The wait time 1728 * between retries starts small (10ms) and exponentially increases. 1729 * Total wait time is a little over two seconds. Retry logic in the 1730 * client driver may mean this whole loop is repeated if it continues to 1731 * fail. 1732 */ 1733 retry = 0; 1734 delay_us = 10000; 1735 while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) { 1736 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) || 1737 (rc != ENOENT)) { 1738 /* 1739 * Do not retry alloc for PF, or for other errors on 1740 * a VF. 1741 */ 1742 goto fail5; 1743 } 1744 1745 /* VF startup before PF is ready. Retry allocation. */ 1746 if (retry > 5) { 1747 /* Too many attempts */ 1748 rc = EINVAL; 1749 goto fail6; 1750 } 1751 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry); 1752 EFSYS_SLEEP(delay_us); 1753 retry++; 1754 if (delay_us < 500000) 1755 delay_us <<= 2; 1756 } 1757 1758 enp->en_vport_id = EVB_PORT_ID_ASSIGNED; 1759 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2; 1760 1761 return (0); 1762 1763fail6: 1764 EFSYS_PROBE(fail6); 1765fail5: 1766 EFSYS_PROBE(fail5); 1767fail4: 1768 EFSYS_PROBE(fail4); 1769fail3: 1770 EFSYS_PROBE(fail3); 1771fail2: 1772 EFSYS_PROBE(fail2); 1773 1774 ef10_nic_free_piobufs(enp); 1775 1776fail1: 1777 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1778 1779 return (rc); 1780} 1781 1782 __checkReturn efx_rc_t 1783ef10_nic_get_vi_pool( 1784 __in efx_nic_t *enp, 1785 __out uint32_t *vi_countp) 1786{ 1787 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1788 enp->en_family == EFX_FAMILY_MEDFORD); 1789 1790 /* 1791 * Report VIs that the client driver can use. 1792 * Do not include VIs used for PIO buffer writes. 1793 */ 1794 *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base; 1795 1796 return (0); 1797} 1798 1799 __checkReturn efx_rc_t 1800ef10_nic_get_bar_region( 1801 __in efx_nic_t *enp, 1802 __in efx_nic_region_t region, 1803 __out uint32_t *offsetp, 1804 __out size_t *sizep) 1805{ 1806 efx_rc_t rc; 1807 1808 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1809 enp->en_family == EFX_FAMILY_MEDFORD); 1810 1811 /* 1812 * TODO: Specify host memory mapping alignment and granularity 1813 * in efx_drv_limits_t so that they can be taken into account 1814 * when allocating extra VIs for PIO writes. 1815 */ 1816 switch (region) { 1817 case EFX_REGION_VI: 1818 /* UC mapped memory BAR region for VI registers */ 1819 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset; 1820 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size; 1821 break; 1822 1823 case EFX_REGION_PIO_WRITE_VI: 1824 /* WC mapped memory BAR region for piobuf writes */ 1825 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset; 1826 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size; 1827 break; 1828 1829 default: 1830 rc = EINVAL; 1831 goto fail1; 1832 } 1833 1834 return (0); 1835 1836fail1: 1837 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1838 1839 return (rc); 1840} 1841 1842 void 1843ef10_nic_fini( 1844 __in efx_nic_t *enp) 1845{ 1846 uint32_t i; 1847 efx_rc_t rc; 1848 1849 (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id); 1850 enp->en_vport_id = 0; 1851 1852 /* Unlink piobufs from extra VIs in WC mapping */ 1853 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1854 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1855 rc = efx_mcdi_unlink_piobuf(enp, 1856 enp->en_arch.ef10.ena_pio_write_vi_base + i); 1857 if (rc != 0) 1858 break; 1859 } 1860 } 1861 1862 ef10_nic_free_piobufs(enp); 1863 1864 (void) efx_mcdi_free_vis(enp); 1865 enp->en_arch.ef10.ena_vi_count = 0; 1866} 1867 1868 void 1869ef10_nic_unprobe( 1870 __in efx_nic_t *enp) 1871{ 1872#if EFSYS_OPT_MON_STATS 1873 mcdi_mon_cfg_free(enp); 1874#endif /* EFSYS_OPT_MON_STATS */ 1875 (void) efx_mcdi_drv_attach(enp, B_FALSE); 1876} 1877 1878#if EFSYS_OPT_DIAG 1879 1880 __checkReturn efx_rc_t 1881ef10_nic_register_test( 1882 __in efx_nic_t *enp) 1883{ 1884 efx_rc_t rc; 1885 1886 /* FIXME */ 1887 _NOTE(ARGUNUSED(enp)) 1888 if (B_FALSE) { 1889 rc = ENOTSUP; 1890 goto fail1; 1891 } 1892 /* FIXME */ 1893 1894 return (0); 1895 1896fail1: 1897 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1898 1899 return (rc); 1900} 1901 1902#endif /* EFSYS_OPT_DIAG */ 1903 1904 1905 1906#endif /* EFSYS_OPT_HUNTINGTON */ 1907