X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fbase%2Fef10_evb.c;h=1788a2c96a0291539e1555beb7e7292e86b2d6cc;hb=45a49cc7e7a589d268e362ee275c399a6640708a;hp=03ac19ae0f090b1b91f08e5e82f76d32c40891da;hpb=4f12e20c85dce289668ef0ff61295fdebeb14b7d;p=dpdk.git diff --git a/drivers/net/sfc/base/ef10_evb.c b/drivers/net/sfc/base/ef10_evb.c index 03ac19ae0f..1788a2c96a 100644 --- a/drivers/net/sfc/base/ef10_evb.c +++ b/drivers/net/sfc/base/ef10_evb.c @@ -31,5 +31,523 @@ ef10_evb_fini( enp->en_family == EFX_FAMILY_MEDFORD2); } + __checkReturn efx_rc_t +efx_mcdi_vswitch_alloc( + __in efx_nic_t *enp, + __in efx_vport_id_t vport_id, + __in efx_vswitch_type_t vswitch_type) +{ + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VSWITCH_ALLOC_IN_LEN, + MC_CMD_VSWITCH_ALLOC_OUT_LEN); + efx_mcdi_req_t req; + efx_rc_t rc; + uint8_t ntags; + + /* Ensure EFX and MCDI use same values for vswitch types */ + EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_VLAN == + MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VLAN); + EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_VEB == + MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VEB); + EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_MUX == + MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_MUX); + + /* First try with maximum number of VLAN tags FW supports */ + ntags = 2; +retry: + req.emr_cmd = MC_CMD_VSWITCH_ALLOC; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VSWITCH_ALLOC_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VSWITCH_ALLOC_OUT_LEN; + + MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_UPSTREAM_PORT_ID, vport_id); + MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_TYPE, vswitch_type); + MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_NUM_VLAN_TAGS, ntags); + MCDI_IN_POPULATE_DWORD_1(req, VSWITCH_ALLOC_IN_FLAGS, + VSWITCH_ALLOC_IN_FLAG_AUTO_PORT, 0); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + /* + * efx_rc_t error codes in libefx are translated from MCDI + * error codes in efx_mcdi_request_errcode. As this conversion + * is not a 1:1, here we check the specific MCDI error code. + */ + if (req.emr_err_code == MC_CMD_ERR_VLAN_LIMIT) { + /* Too many VLAN tags, retry with fewer */ + EFSYS_PROBE(vlan_limit); + ntags--; + if (ntags > 0) { + /* + * Zero the buffer before reusing it + * for another request + */ + memset(payload, 0, sizeof (payload)); + goto retry; + } + goto fail1; + } + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_vswitch_free( + __in efx_nic_t *enp) +{ + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VSWITCH_FREE_IN_LEN, + MC_CMD_VSWITCH_FREE_OUT_LEN); + efx_mcdi_req_t req; + efx_rc_t rc; + + req.emr_cmd = MC_CMD_VSWITCH_FREE; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VSWITCH_FREE_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VSWITCH_FREE_OUT_LEN; + + MCDI_IN_SET_DWORD(req, VSWITCH_FREE_IN_UPSTREAM_PORT_ID, + EVB_PORT_ID_ASSIGNED); + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_vport_alloc( + __in efx_nic_t *enp, + __in efx_vport_type_t vport_type, + __in uint16_t vid, + __in boolean_t vlan_restrict, + __out efx_vport_id_t *vport_idp) +{ + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_ALLOC_IN_LEN, + MC_CMD_VPORT_ALLOC_OUT_LEN); + efx_mcdi_req_t req; + efx_rc_t rc; + + /* Ensure EFX and MCDI use same values for vport types */ + EFX_STATIC_ASSERT(EFX_VPORT_TYPE_NORMAL == + MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL); + EFX_STATIC_ASSERT(EFX_VPORT_TYPE_EXPANSION == + MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_EXPANSION); + EFX_STATIC_ASSERT(EFX_VPORT_TYPE_TEST == + MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_TEST); + + req.emr_cmd = MC_CMD_VPORT_ALLOC; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VPORT_ALLOC_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VPORT_ALLOC_OUT_LEN; + + MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_UPSTREAM_PORT_ID, + EVB_PORT_ID_ASSIGNED); + MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_TYPE, vport_type); + MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_NUM_VLAN_TAGS, + (vid != EFX_FILTER_VID_UNSPEC)); + + MCDI_IN_POPULATE_DWORD_2(req, VPORT_ALLOC_IN_FLAGS, + VPORT_ALLOC_IN_FLAG_AUTO_PORT, 0, + VPORT_ALLOC_IN_FLAG_VLAN_RESTRICT, vlan_restrict); + + if (vid != EFX_FILTER_VID_UNSPEC) + MCDI_IN_POPULATE_DWORD_1(req, VPORT_ALLOC_IN_VLAN_TAGS, + VPORT_ALLOC_IN_VLAN_TAG_0, vid); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_VPORT_ALLOC_OUT_LEN) { + rc = EMSGSIZE; + goto fail2; + } + + *vport_idp = *MCDI_OUT2(req, uint32_t, VPORT_ALLOC_OUT_VPORT_ID); + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_vport_free( + __in efx_nic_t *enp, + __in efx_vport_id_t vport_id) +{ + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_FREE_IN_LEN, + MC_CMD_VPORT_FREE_OUT_LEN); + efx_mcdi_req_t req; + efx_rc_t rc; + + req.emr_cmd = MC_CMD_VPORT_FREE; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VPORT_FREE_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VPORT_FREE_OUT_LEN; + + MCDI_IN_SET_DWORD(req, VPORT_FREE_IN_VPORT_ID, vport_id); + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_vport_mac_addr_add( + __in efx_nic_t *enp, + __in efx_vport_id_t vport_id, + __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp) +{ + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN, + MC_CMD_VPORT_ADD_MAC_ADDRESS_OUT_LEN); + efx_mcdi_req_t req; + efx_rc_t rc; + + req.emr_cmd = MC_CMD_VPORT_ADD_MAC_ADDRESS; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VPORT_ADD_MAC_ADDRESS_OUT_LEN; + + MCDI_IN_SET_DWORD(req, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, vport_id); + EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, + VPORT_ADD_MAC_ADDRESS_IN_MACADDR), addrp); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_vport_mac_addr_del( + __in efx_nic_t *enp, + __in efx_vport_id_t vport_id, + __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp) +{ + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN, + MC_CMD_VPORT_DEL_MAC_ADDRESS_OUT_LEN); + efx_mcdi_req_t req; + efx_rc_t rc; + + req.emr_cmd = MC_CMD_VPORT_DEL_MAC_ADDRESS; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VPORT_DEL_MAC_ADDRESS_OUT_LEN; + + MCDI_IN_SET_DWORD(req, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, vport_id); + EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, + VPORT_DEL_MAC_ADDRESS_IN_MACADDR), addrp); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_port_assign( + __in efx_nic_t *enp, + __in efx_vport_id_t vport_id, + __in uint32_t vf_index) +{ + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_EVB_PORT_ASSIGN_IN_LEN, + MC_CMD_EVB_PORT_ASSIGN_OUT_LEN); + efx_mcdi_req_t req; + efx_nic_cfg_t *encp = &(enp->en_nic_cfg); + efx_rc_t rc; + + req.emr_cmd = MC_CMD_EVB_PORT_ASSIGN; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_EVB_PORT_ASSIGN_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_EVB_PORT_ASSIGN_OUT_LEN; + + MCDI_IN_SET_DWORD(req, EVB_PORT_ASSIGN_IN_PORT_ID, vport_id); + MCDI_IN_POPULATE_DWORD_2(req, EVB_PORT_ASSIGN_IN_FUNCTION, + EVB_PORT_ASSIGN_IN_PF, encp->enc_pf, + EVB_PORT_ASSIGN_IN_VF, vf_index); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_vport_reconfigure( + __in efx_nic_t *enp, + __in efx_vport_id_t vport_id, + __in_opt uint16_t *vidp, + __in_bcount_opt(EFX_MAC_ADDR_LEN) uint8_t *addrp, + __out_opt boolean_t *fn_resetp) +{ + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_RECONFIGURE_IN_LEN, + MC_CMD_VPORT_RECONFIGURE_OUT_LEN); + efx_mcdi_req_t req; + efx_rc_t rc; + uint32_t reset_flag = 0; + + req.emr_cmd = MC_CMD_VPORT_RECONFIGURE; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VPORT_RECONFIGURE_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VPORT_RECONFIGURE_OUT_LEN; + + MCDI_IN_SET_DWORD(req, VPORT_RECONFIGURE_IN_VPORT_ID, vport_id); + + if (vidp != NULL) { + MCDI_IN_POPULATE_DWORD_1(req, VPORT_RECONFIGURE_IN_FLAGS, + VPORT_RECONFIGURE_IN_REPLACE_VLAN_TAGS, 1); + if (*vidp != EFX_FILTER_VID_UNSPEC) { + MCDI_IN_SET_DWORD(req, + VPORT_RECONFIGURE_IN_NUM_VLAN_TAGS, 1); + MCDI_IN_POPULATE_DWORD_1(req, + VPORT_RECONFIGURE_IN_VLAN_TAGS, + VPORT_RECONFIGURE_IN_VLAN_TAG_0, *vidp); + } + } + + if ((addrp != NULL) && (efx_is_zero_eth_addr(addrp) == B_FALSE)) { + MCDI_IN_POPULATE_DWORD_1(req, VPORT_RECONFIGURE_IN_FLAGS, + VPORT_RECONFIGURE_IN_REPLACE_MACADDRS, 1); + MCDI_IN_SET_DWORD(req, VPORT_RECONFIGURE_IN_NUM_MACADDRS, 1); + EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, + VPORT_RECONFIGURE_IN_MACADDRS), addrp); + } + + efx_mcdi_execute(enp, &req); + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_VPORT_RECONFIGURE_OUT_LEN) { + rc = EMSGSIZE; + goto fail2; + } + + reset_flag = MCDI_OUT_DWORD_FIELD(req, VPORT_RECONFIGURE_OUT_FLAGS, + VPORT_RECONFIGURE_OUT_RESET_DONE); + + if (fn_resetp != NULL) + *fn_resetp = (reset_flag != 0); + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +ef10_evb_vswitch_alloc( + __in efx_nic_t *enp, + __out efx_vswitch_id_t *vswitch_idp) +{ + efx_rc_t rc; + if (vswitch_idp == NULL) { + rc = EINVAL; + goto fail1; + } + + if ((rc = efx_mcdi_vswitch_alloc(enp, EVB_PORT_ID_ASSIGNED, + EFX_VSWITCH_TYPE_VEB)) != 0) { + goto fail2; + } + + *vswitch_idp = EFX_DEFAULT_VSWITCH_ID; + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +ef10_evb_vswitch_free( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id) +{ + _NOTE(ARGUNUSED(vswitch_id)) + + return (efx_mcdi_vswitch_free(enp)); +} + + __checkReturn efx_rc_t +ef10_evb_vport_alloc( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_type_t vport_type, + __in uint16_t vid, + __in boolean_t vlan_restrict, + __out efx_vport_id_t *vport_idp) +{ + _NOTE(ARGUNUSED(vswitch_id)) + + return (efx_mcdi_vport_alloc(enp, + vport_type, vid, + vlan_restrict, vport_idp)); +} + + __checkReturn efx_rc_t +ef10_evb_vport_free( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_id_t vport_id) +{ + _NOTE(ARGUNUSED(vswitch_id)) + + return (efx_mcdi_vport_free(enp, vport_id)); +} + + __checkReturn efx_rc_t +ef10_evb_vport_mac_addr_add( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_id_t vport_id, + __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp) +{ + _NOTE(ARGUNUSED(vswitch_id)) + EFSYS_ASSERT(addrp != NULL); + + return (efx_mcdi_vport_mac_addr_add(enp, vport_id, addrp)); +} + + __checkReturn efx_rc_t +ef10_evb_vport_mac_addr_del( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_id_t vport_id, + __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp) +{ + _NOTE(ARGUNUSED(vswitch_id)) + EFSYS_ASSERT(addrp != NULL); + + return (efx_mcdi_vport_mac_addr_del(enp, vport_id, addrp)); +} + + __checkReturn efx_rc_t +ef10_evb_vadaptor_alloc( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_id_t vport_id) +{ + _NOTE(ARGUNUSED(vswitch_id)) + + return (efx_mcdi_vadaptor_alloc(enp, vport_id)); +} + + __checkReturn efx_rc_t +ef10_evb_vadaptor_free( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_id_t vport_id) +{ + _NOTE(ARGUNUSED(vswitch_id)) + + return (efx_mcdi_vadaptor_free(enp, vport_id)); +} + + __checkReturn efx_rc_t +ef10_evb_vport_assign( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_id_t vport_id, + __in uint32_t vf_index) +{ + _NOTE(ARGUNUSED(vswitch_id)) + + return (efx_mcdi_port_assign(enp, vport_id, vf_index)); +} + + __checkReturn efx_rc_t +ef10_evb_vport_reconfigure( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_id_t vport_id, + __in_opt uint16_t *vidp, + __in_bcount_opt(EFX_MAC_ADDR_LEN) uint8_t *addrp, + __out_opt boolean_t *fn_resetp) +{ + _NOTE(ARGUNUSED(vswitch_id)) + + return (efx_mcdi_vport_reconfigure(enp, vport_id, vidp, + addrp, fn_resetp)); +} + + __checkReturn efx_rc_t +ef10_evb_vport_stats( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in efx_vport_id_t vport_id, + __in efsys_mem_t *esmp) +{ + _NOTE(ARGUNUSED(vswitch_id)) + + return (efx_mcdi_mac_stats(enp, vport_id, esmp, + EFX_STATS_UPLOAD, 0)); +} + #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ #endif /* EFSYS_OPT_EVB */