int bnxt_get_vf_config(struct net_device *dev, int vf_id, struct ifla_vf_info *ivi) { struct bnxt *bp = netdev_priv(dev); struct bnxt_vf_info *vf; int rc; rc = bnxt_vf_ndo_prep(bp, vf_id); if (rc) return rc; ivi->vf = vf_id; vf = &bp->pf.vf[vf_id]; memcpy(&ivi->mac, vf->mac_addr, ETH_ALEN); ivi->max_tx_rate = vf->max_tx_rate; ivi->min_tx_rate = vf->min_tx_rate; ivi->vlan = vf->vlan; ivi->qos = vf->flags & BNXT_VF_QOS; ivi->spoofchk = vf->flags & BNXT_VF_SPOOFCHK; if (!(vf->flags & BNXT_VF_LINK_FORCED)) ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; else if (vf->flags & BNXT_VF_LINK_UP) ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE; else ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE; return 0; }
int bnxt_set_vf_link_state(struct net_device *dev, int vf_id, int link) { struct bnxt *bp = netdev_priv(dev); struct bnxt_vf_info *vf; int rc; rc = bnxt_vf_ndo_prep(bp, vf_id); if (rc) return rc; vf = &bp->pf.vf[vf_id]; vf->flags &= ~(BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED); switch (link) { case IFLA_VF_LINK_STATE_AUTO: vf->flags |= BNXT_VF_LINK_UP; break; case IFLA_VF_LINK_STATE_DISABLE: vf->flags |= BNXT_VF_LINK_FORCED; break; case IFLA_VF_LINK_STATE_ENABLE: vf->flags |= BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED; break; default: netdev_err(bp->dev, "Invalid link option\n"); rc = -EINVAL; break; } /* CHIMP TODO: send msg to VF to update new link state */ return rc; }
int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos) { struct hwrm_func_cfg_input req = {0}; struct bnxt *bp = netdev_priv(dev); struct bnxt_vf_info *vf; u16 vlan_tag; int rc; rc = bnxt_vf_ndo_prep(bp, vf_id); if (rc) return rc; /* TODO: needed to implement proper handling of user priority, * currently fail the command if there is valid priority */ if (vlan_id > 4095 || qos) return -EINVAL; vf = &bp->pf.vf[vf_id]; vlan_tag = vlan_id; if (vlan_tag == vf->vlan) return 0; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); req.fid = cpu_to_le16(vf->fw_fid); req.flags = cpu_to_le32(vf->func_flags); req.dflt_vlan = cpu_to_le16(vlan_tag); req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN); rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); if (!rc) vf->vlan = vlan_tag; return rc; }
int bnxt_set_vf_mac(struct net_device *dev, int vf_id, u8 *mac) { struct hwrm_func_cfg_input req = {0}; struct bnxt *bp = netdev_priv(dev); struct bnxt_vf_info *vf; int rc; rc = bnxt_vf_ndo_prep(bp, vf_id); if (rc) return rc; /* reject bc or mc mac addr, zero mac addr means allow * VF to use its own mac addr */ if (is_multicast_ether_addr(mac)) { netdev_err(dev, "Invalid VF ethernet address\n"); return -EINVAL; } vf = &bp->pf.vf[vf_id]; memcpy(vf->mac_addr, mac, ETH_ALEN); bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); req.fid = cpu_to_le16(vf->fw_fid); req.flags = cpu_to_le32(vf->func_flags); req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR); memcpy(req.dflt_mac_addr, mac, ETH_ALEN); return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); }
int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trusted) { struct bnxt *bp = netdev_priv(dev); struct bnxt_vf_info *vf; if (bnxt_vf_ndo_prep(bp, vf_id)) return -EINVAL; vf = &bp->pf.vf[vf_id]; if (trusted) vf->flags |= BNXT_VF_TRUST; else vf->flags &= ~BNXT_VF_TRUST; return 0; }
int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting) { struct hwrm_func_cfg_input req = {0}; struct bnxt *bp = netdev_priv(dev); struct bnxt_vf_info *vf; bool old_setting = false; u32 func_flags; int rc; if (bp->hwrm_spec_code < 0x10701) return -ENOTSUPP; rc = bnxt_vf_ndo_prep(bp, vf_id); if (rc) return rc; vf = &bp->pf.vf[vf_id]; if (vf->flags & BNXT_VF_SPOOFCHK) old_setting = true; if (old_setting == setting) return 0; func_flags = vf->func_flags; if (setting) func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE; else func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE; /*TODO: if the driver supports VLAN filter on guest VLAN, * the spoof check should also include vlan anti-spoofing */ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); req.fid = cpu_to_le16(vf->fw_fid); req.flags = cpu_to_le32(func_flags); rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); if (!rc) { vf->func_flags = func_flags; if (setting) vf->flags |= BNXT_VF_SPOOFCHK; else vf->flags &= ~BNXT_VF_SPOOFCHK; } return rc; }
int bnxt_set_vf_bw(struct net_device *dev, int vf_id, int min_tx_rate, int max_tx_rate) { struct hwrm_func_cfg_input req = {0}; struct bnxt *bp = netdev_priv(dev); struct bnxt_vf_info *vf; u32 pf_link_speed; int rc; rc = bnxt_vf_ndo_prep(bp, vf_id); if (rc) return rc; vf = &bp->pf.vf[vf_id]; pf_link_speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed); if (max_tx_rate > pf_link_speed) { netdev_info(bp->dev, "max tx rate %d exceed PF link speed for VF %d\n", max_tx_rate, vf_id); return -EINVAL; } if (min_tx_rate > pf_link_speed || min_tx_rate > max_tx_rate) { netdev_info(bp->dev, "min tx rate %d is invalid for VF %d\n", min_tx_rate, vf_id); return -EINVAL; } if (min_tx_rate == vf->min_tx_rate && max_tx_rate == vf->max_tx_rate) return 0; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); req.fid = cpu_to_le16(vf->fw_fid); req.flags = cpu_to_le32(vf->func_flags); req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW); req.max_bw = cpu_to_le32(max_tx_rate); req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_MIN_BW); req.min_bw = cpu_to_le32(min_tx_rate); rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); if (!rc) { vf->min_tx_rate = min_tx_rate; vf->max_tx_rate = max_tx_rate; } return rc; }
int bnxt_get_vf_config(struct net_device *dev, int vf_id, struct ifla_vf_info *ivi) { struct bnxt *bp = netdev_priv(dev); struct bnxt_vf_info *vf; int rc; rc = bnxt_vf_ndo_prep(bp, vf_id); if (rc) return rc; ivi->vf = vf_id; vf = &bp->pf.vf[vf_id]; memcpy(&ivi->mac, vf->mac_addr, ETH_ALEN); ivi->max_tx_rate = vf->max_tx_rate; ivi->min_tx_rate = vf->min_tx_rate; ivi->vlan = vf->vlan; if (vf->flags & BNXT_VF_QOS) ivi->qos = vf->vlan >> VLAN_PRIO_SHIFT; else