diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c index 9bb1004548ab..935a6a03b14f 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c @@ -225,11 +225,15 @@ static const struct enetc_pf_ops enetc4_pf_ops = { static int enetc4_pf_struct_init(struct enetc_si *si) { struct enetc_pf *pf = enetc_si_priv(si); + int err; pf->si = si; - pf->total_vfs = pci_sriov_get_totalvfs(si->pdev); pf->ops = &enetc4_pf_ops; + err = enetc_init_sriov_resources(pf); + if (err) + return err; + enetc4_get_port_caps(pf); enetc4_get_psi_hw_features(si); @@ -574,6 +578,7 @@ static const struct net_device_ops enetc4_ndev_ops = { .ndo_eth_ioctl = enetc_ioctl, .ndo_hwtstamp_get = enetc_hwtstamp_get, .ndo_hwtstamp_set = enetc_hwtstamp_set, + .ndo_set_vf_trust = enetc_pf_set_vf_trust, }; static struct phylink_pcs * diff --git a/drivers/net/ethernet/freescale/enetc/enetc_msg.c b/drivers/net/ethernet/freescale/enetc/enetc_msg.c index edc1277bb586..78114ab3e482 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_msg.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_msg.c @@ -7,6 +7,8 @@ ENETC_MSG_CLASS_ID_CMD_SUCCESS) #define ENETC_PF_MSG_NOTSUPP FIELD_PREP(ENETC_PF_MSG_CLASS_ID, \ ENETC_MSG_CLASS_ID_CMD_NOT_SUPPORT) +#define ENETC_PF_MSG_PERM_DENY FIELD_PREP(ENETC_PF_MSG_CLASS_ID, \ + ENETC_MSG_CLASS_ID_PERMISSION_DENY) static void enetc_msg_disable_mr_int(struct enetc_pf *pf) { @@ -61,31 +63,49 @@ static u16 enetc_msg_set_vf_primary_mac_addr(struct enetc_pf *pf, int vf_id, struct enetc_vf_state *vf_state = &pf->vf_state[vf_id]; struct enetc_msg_mac_exact_filter *msg = vf_msg; struct device *dev = &pf->si->pdev->dev; + u16 pf_msg = ENETC_PF_MSG_SUCCESS; char *addr = msg->mac[0].addr; + mutex_lock(&vf_state->lock); + + /* Untrusted VFs cannot set their MAC addresses by the mailbox + * messages. + */ + if (!(vf_state->flags & ENETC_VF_FLAG_TRUSTED)) { + pf_msg = ENETC_PF_MSG_PERM_DENY; + goto vf_state_unlock; + } + if (!is_valid_ether_addr(addr)) { dev_err_ratelimited(dev, "VF%d attempted to set invalid MAC\n", vf_id); - return (FIELD_PREP(ENETC_PF_MSG_CLASS_ID, - ENETC_MSG_CLASS_ID_MAC_FILTER) | - FIELD_PREP(ENETC_PF_MSG_CLASS_CODE, - ENETC_MF_CLASS_CODE_INVALID_MAC)); + pf_msg = FIELD_PREP(ENETC_PF_MSG_CLASS_ID, + ENETC_MSG_CLASS_ID_MAC_FILTER) | + FIELD_PREP(ENETC_PF_MSG_CLASS_CODE, + ENETC_MF_CLASS_CODE_INVALID_MAC); + goto vf_state_unlock; } - mutex_lock(&vf_state->lock); + /* PF has higher privileges. If PF has already modified the MAC + * address for VF through .ndo_set_vf_mac() interface, VF is not + * allowed to set its MAC address via mailbox messages, even if + * it is trusted. + */ if (vf_state->flags & ENETC_VF_FLAG_PF_SET_MAC) { - mutex_unlock(&vf_state->lock); dev_err_ratelimited(dev, "VF%d attempted to override PF set MAC\n", vf_id); - return FIELD_PREP(ENETC_PF_MSG_CLASS_ID, - ENETC_MSG_CLASS_ID_CMD_NOT_PERMITTED); + pf_msg = FIELD_PREP(ENETC_PF_MSG_CLASS_ID, + ENETC_MSG_CLASS_ID_CMD_NOT_PERMITTED); + goto vf_state_unlock; } enetc_set_si_hw_addr(pf, vf_id + 1, addr); + +vf_state_unlock: mutex_unlock(&vf_state->lock); - return ENETC_PF_MSG_SUCCESS; + return pf_msg; } static u16 enetc_msg_handle_mac_filter(struct enetc_pf *pf, int vf_id, diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 55c07c528f22..a7bf4bfc25b7 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -488,6 +488,7 @@ static const struct net_device_ops enetc_ndev_ops = { .ndo_set_rx_mode = enetc_pf_set_rx_mode, .ndo_vlan_rx_add_vid = enetc_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = enetc_vlan_rx_del_vid, + .ndo_set_vf_trust = enetc_pf_set_vf_trust, .ndo_set_vf_mac = enetc_pf_set_vf_mac, .ndo_set_vf_vlan = enetc_pf_set_vf_vlan, .ndo_set_vf_spoofchk = enetc_pf_set_vf_spoofchk, diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h index 56d23a8a11a0..6789f92d005e 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h @@ -9,6 +9,7 @@ enum enetc_vf_flags { ENETC_VF_FLAG_PF_SET_MAC = BIT(0), + ENETC_VF_FLAG_TRUSTED = BIT(1), }; struct enetc_vf_state { diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c index d32a195a04c9..519fc90d2647 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c @@ -586,5 +586,28 @@ int enetc_init_sriov_resources(struct enetc_pf *pf) } EXPORT_SYMBOL_GPL(enetc_init_sriov_resources); +int enetc_pf_set_vf_trust(struct net_device *ndev, int vf, bool setting) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_pf *pf = enetc_si_priv(priv->si); + struct enetc_vf_state *vf_state; + + if (vf >= pf->total_vfs) + return -EINVAL; + + vf_state = &pf->vf_state[vf]; + mutex_lock(&vf_state->lock); + + if (setting) + vf_state->flags |= ENETC_VF_FLAG_TRUSTED; + else + vf_state->flags &= ~ENETC_VF_FLAG_TRUSTED; + + mutex_unlock(&vf_state->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(enetc_pf_set_vf_trust); + MODULE_DESCRIPTION("NXP ENETC PF common functionality driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h index 8243ce0de57f..96a4dc63da57 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h @@ -22,6 +22,7 @@ void enetc_set_si_mc_promisc(struct enetc_si *si, int si_id, bool promisc); void enetc_set_si_uc_hash_filter(struct enetc_si *si, int si_id, u64 hash); void enetc_set_si_mc_hash_filter(struct enetc_si *si, int si_id, u64 hash); void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id, bool promisc); +int enetc_pf_set_vf_trust(struct net_device *ndev, int vf, bool setting); static inline u16 enetc_get_ip_revision(struct enetc_hw *hw) {