diff options
author | Edward Cree <ecree@solarflare.com> | 2020-03-12 19:21:39 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-14 20:57:25 -0700 |
commit | 085793f038be88af8aa840f2dff3505e99ba9034 (patch) | |
tree | c5b38c84b640eff4eb213642dde1bfe0905ed09a /drivers/net | |
parent | fa83820e5c58d200f41d08003ecb5f61cad3113b (diff) |
sfc: support configuring vf spoofchk on EF10 VFs
Corresponds to the MAC_SPOOFING_TX privilege in the hardware.
Some firmware versions on some cards don't support the feature, so check
the TX_MAC_SECURITY capability and fail EOPNOTSUPP if trying to enable
spoofchk on a NIC that doesn't support it.
Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/sfc/ef10_sriov.c | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 14393767ef9f..4580b30caae1 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -685,10 +685,70 @@ reset_nic: return rc ? rc : rc2; } -int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf_i, - bool spoofchk) +static int efx_ef10_sriov_set_privilege_mask(struct efx_nic *efx, int vf_i, + u32 mask, u32 value) { - return spoofchk ? -EOPNOTSUPP : 0; + MCDI_DECLARE_BUF(pm_outbuf, MC_CMD_PRIVILEGE_MASK_OUT_LEN); + MCDI_DECLARE_BUF(pm_inbuf, MC_CMD_PRIVILEGE_MASK_IN_LEN); + struct efx_ef10_nic_data *nic_data = efx->nic_data; + u32 old_mask, new_mask; + size_t outlen; + int rc; + + EFX_WARN_ON_PARANOID((value & ~mask) != 0); + + /* Get privilege mask */ + MCDI_POPULATE_DWORD_2(pm_inbuf, PRIVILEGE_MASK_IN_FUNCTION, + PRIVILEGE_MASK_IN_FUNCTION_PF, nic_data->pf_index, + PRIVILEGE_MASK_IN_FUNCTION_VF, vf_i); + + rc = efx_mcdi_rpc(efx, MC_CMD_PRIVILEGE_MASK, + pm_inbuf, sizeof(pm_inbuf), + pm_outbuf, sizeof(pm_outbuf), &outlen); + + if (rc != 0) + return rc; + if (outlen != MC_CMD_PRIVILEGE_MASK_OUT_LEN) + return -EIO; + + old_mask = MCDI_DWORD(pm_outbuf, PRIVILEGE_MASK_OUT_OLD_MASK); + + new_mask = old_mask & ~mask; + new_mask |= value; + + if (new_mask == old_mask) + return 0; + + new_mask |= MC_CMD_PRIVILEGE_MASK_IN_DO_CHANGE; + + /* Set privilege mask */ + MCDI_SET_DWORD(pm_inbuf, PRIVILEGE_MASK_IN_NEW_MASK, new_mask); + + rc = efx_mcdi_rpc(efx, MC_CMD_PRIVILEGE_MASK, + pm_inbuf, sizeof(pm_inbuf), + pm_outbuf, sizeof(pm_outbuf), &outlen); + + if (rc != 0) + return rc; + if (outlen != MC_CMD_PRIVILEGE_MASK_OUT_LEN) + return -EIO; + + return 0; +} + +int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf_i, bool spoofchk) +{ + struct efx_ef10_nic_data *nic_data = efx->nic_data; + + /* Can't enable spoofchk if firmware doesn't support it. */ + if (!(nic_data->datapath_caps & + BIT(MC_CMD_GET_CAPABILITIES_OUT_TX_MAC_SECURITY_FILTERING_LBN)) && + spoofchk) + return -EOPNOTSUPP; + + return efx_ef10_sriov_set_privilege_mask(efx, vf_i, + MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING_TX, + spoofchk ? 0 : MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING_TX); } int efx_ef10_sriov_set_vf_link_state(struct efx_nic *efx, int vf_i, |