mirror of https://gitee.com/openkylin/linux.git
ice: Add handlers for VF netdevice operations
This patch implements handlers for the following NDO operations: .ndo_set_vf_spoofchk .ndo_set_vf_mac .ndo_get_vf_config .ndo_set_vf_trust .ndo_set_vf_vlan .ndo_set_vf_link_state Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
007676b4ac
commit
7c710869d6
|
@ -474,4 +474,16 @@ static inline struct ice_rx_ptype_decoded ice_decode_rx_desc_ptype(u16 ptype)
|
||||||
{
|
{
|
||||||
return ice_ptype_lkup[ptype];
|
return ice_ptype_lkup[ptype];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ICE_LINK_SPEED_UNKNOWN 0
|
||||||
|
#define ICE_LINK_SPEED_10MBPS 10
|
||||||
|
#define ICE_LINK_SPEED_100MBPS 100
|
||||||
|
#define ICE_LINK_SPEED_1000MBPS 1000
|
||||||
|
#define ICE_LINK_SPEED_2500MBPS 2500
|
||||||
|
#define ICE_LINK_SPEED_5000MBPS 5000
|
||||||
|
#define ICE_LINK_SPEED_10000MBPS 10000
|
||||||
|
#define ICE_LINK_SPEED_20000MBPS 20000
|
||||||
|
#define ICE_LINK_SPEED_25000MBPS 25000
|
||||||
|
#define ICE_LINK_SPEED_40000MBPS 40000
|
||||||
|
|
||||||
#endif /* _ICE_LAN_TX_RX_H_ */
|
#endif /* _ICE_LAN_TX_RX_H_ */
|
||||||
|
|
|
@ -3884,6 +3884,12 @@ static const struct net_device_ops ice_netdev_ops = {
|
||||||
.ndo_validate_addr = eth_validate_addr,
|
.ndo_validate_addr = eth_validate_addr,
|
||||||
.ndo_change_mtu = ice_change_mtu,
|
.ndo_change_mtu = ice_change_mtu,
|
||||||
.ndo_get_stats64 = ice_get_stats64,
|
.ndo_get_stats64 = ice_get_stats64,
|
||||||
|
.ndo_set_vf_spoofchk = ice_set_vf_spoofchk,
|
||||||
|
.ndo_set_vf_mac = ice_set_vf_mac,
|
||||||
|
.ndo_get_vf_config = ice_get_vf_cfg,
|
||||||
|
.ndo_set_vf_trust = ice_set_vf_trust,
|
||||||
|
.ndo_set_vf_vlan = ice_set_vf_port_vlan,
|
||||||
|
.ndo_set_vf_link_state = ice_set_vf_link_state,
|
||||||
.ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
|
.ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
|
||||||
.ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
|
.ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
|
||||||
.ndo_set_features = ice_set_features,
|
.ndo_set_features = ice_set_features,
|
||||||
|
|
|
@ -39,3 +39,89 @@ ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
|
||||||
|
|
||||||
return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd);
|
return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_conv_link_speed_to_virtchnl
|
||||||
|
* @adv_link_support: determines the format of the returned link speed
|
||||||
|
* @link_speed: variable containing the link_speed to be converted
|
||||||
|
*
|
||||||
|
* Convert link speed supported by HW to link speed supported by virtchnl.
|
||||||
|
* If adv_link_support is true, then return link speed in Mbps. Else return
|
||||||
|
* link speed as a VIRTCHNL_LINK_SPEED_* casted to a u32. Note that the caller
|
||||||
|
* needs to cast back to an enum virtchnl_link_speed in the case where
|
||||||
|
* adv_link_support is false, but when adv_link_support is true the caller can
|
||||||
|
* expect the speed in Mbps.
|
||||||
|
*/
|
||||||
|
u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
|
||||||
|
{
|
||||||
|
u32 speed;
|
||||||
|
|
||||||
|
if (adv_link_support)
|
||||||
|
switch (link_speed) {
|
||||||
|
case ICE_AQ_LINK_SPEED_10MB:
|
||||||
|
speed = ICE_LINK_SPEED_10MBPS;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_100MB:
|
||||||
|
speed = ICE_LINK_SPEED_100MBPS;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_1000MB:
|
||||||
|
speed = ICE_LINK_SPEED_1000MBPS;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_2500MB:
|
||||||
|
speed = ICE_LINK_SPEED_2500MBPS;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_5GB:
|
||||||
|
speed = ICE_LINK_SPEED_5000MBPS;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_10GB:
|
||||||
|
speed = ICE_LINK_SPEED_10000MBPS;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_20GB:
|
||||||
|
speed = ICE_LINK_SPEED_20000MBPS;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_25GB:
|
||||||
|
speed = ICE_LINK_SPEED_25000MBPS;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_40GB:
|
||||||
|
speed = ICE_LINK_SPEED_40000MBPS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
speed = ICE_LINK_SPEED_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Virtchnl speeds are not defined for every speed supported in
|
||||||
|
* the hardware. To maintain compatibility with older AVF
|
||||||
|
* drivers, while reporting the speed the new speed values are
|
||||||
|
* resolved to the closest known virtchnl speeds
|
||||||
|
*/
|
||||||
|
switch (link_speed) {
|
||||||
|
case ICE_AQ_LINK_SPEED_10MB:
|
||||||
|
case ICE_AQ_LINK_SPEED_100MB:
|
||||||
|
speed = (u32)VIRTCHNL_LINK_SPEED_100MB;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_1000MB:
|
||||||
|
case ICE_AQ_LINK_SPEED_2500MB:
|
||||||
|
case ICE_AQ_LINK_SPEED_5GB:
|
||||||
|
speed = (u32)VIRTCHNL_LINK_SPEED_1GB;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_10GB:
|
||||||
|
speed = (u32)VIRTCHNL_LINK_SPEED_10GB;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_20GB:
|
||||||
|
speed = (u32)VIRTCHNL_LINK_SPEED_20GB;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_25GB:
|
||||||
|
speed = (u32)VIRTCHNL_LINK_SPEED_25GB;
|
||||||
|
break;
|
||||||
|
case ICE_AQ_LINK_SPEED_40GB:
|
||||||
|
/* fall through */
|
||||||
|
speed = (u32)VIRTCHNL_LINK_SPEED_40GB;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
speed = (u32)VIRTCHNL_LINK_SPEED_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ enum ice_status
|
||||||
ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
|
ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
|
||||||
u8 *msg, u16 msglen, struct ice_sq_cd *cd);
|
u8 *msg, u16 msglen, struct ice_sq_cd *cd);
|
||||||
|
|
||||||
|
u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed);
|
||||||
#else /* CONFIG_PCI_IOV */
|
#else /* CONFIG_PCI_IOV */
|
||||||
static inline enum ice_status
|
static inline enum ice_status
|
||||||
ice_aq_send_msg_to_vf(struct ice_hw __always_unused *hw,
|
ice_aq_send_msg_to_vf(struct ice_hw __always_unused *hw,
|
||||||
|
@ -21,5 +22,13 @@ ice_aq_send_msg_to_vf(struct ice_hw __always_unused *hw,
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32
|
||||||
|
ice_conv_link_speed_to_virtchnl(bool __always_unused adv_link_support,
|
||||||
|
u16 __always_unused link_speed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_PCI_IOV */
|
#endif /* CONFIG_PCI_IOV */
|
||||||
#endif /* _ICE_SRIOV_H_ */
|
#endif /* _ICE_SRIOV_H_ */
|
||||||
|
|
|
@ -34,6 +34,51 @@ ice_vc_vf_broadcast(struct ice_pf *pf, enum virtchnl_ops v_opcode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_pfe_link - Set the link speed/status of the virtchnl_pf_event
|
||||||
|
* @vf: pointer to the VF structure
|
||||||
|
* @pfe: pointer to the virtchnl_pf_event to set link speed/status for
|
||||||
|
* @ice_link_speed: link speed specified by ICE_AQ_LINK_SPEED_*
|
||||||
|
* @link_up: whether or not to set the link up/down
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ice_set_pfe_link(struct ice_vf *vf, struct virtchnl_pf_event *pfe,
|
||||||
|
int ice_link_speed, bool link_up)
|
||||||
|
{
|
||||||
|
if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) {
|
||||||
|
pfe->event_data.link_event_adv.link_status = link_up;
|
||||||
|
/* Speed in Mbps */
|
||||||
|
pfe->event_data.link_event_adv.link_speed =
|
||||||
|
ice_conv_link_speed_to_virtchnl(true, ice_link_speed);
|
||||||
|
} else {
|
||||||
|
pfe->event_data.link_event.link_status = link_up;
|
||||||
|
/* Legacy method for virtchnl link speeds */
|
||||||
|
pfe->event_data.link_event.link_speed =
|
||||||
|
(enum virtchnl_link_speed)
|
||||||
|
ice_conv_link_speed_to_virtchnl(false, ice_link_speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_pfe_link_forced - Force the virtchnl_pf_event link speed/status
|
||||||
|
* @vf: pointer to the VF structure
|
||||||
|
* @pfe: pointer to the virtchnl_pf_event to set link speed/status for
|
||||||
|
* @link_up: whether or not to set the link up/down
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ice_set_pfe_link_forced(struct ice_vf *vf, struct virtchnl_pf_event *pfe,
|
||||||
|
bool link_up)
|
||||||
|
{
|
||||||
|
u16 link_speed;
|
||||||
|
|
||||||
|
if (link_up)
|
||||||
|
link_speed = ICE_AQ_LINK_SPEED_40GB;
|
||||||
|
else
|
||||||
|
link_speed = ICE_AQ_LINK_SPEED_UNKNOWN;
|
||||||
|
|
||||||
|
ice_set_pfe_link(vf, pfe, link_speed, link_up);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_get_vf_vector - get VF interrupt vector register offset
|
* ice_get_vf_vector - get VF interrupt vector register offset
|
||||||
* @vf_msix: number of MSIx vector per VF on a PF
|
* @vf_msix: number of MSIx vector per VF on a PF
|
||||||
|
@ -291,6 +336,24 @@ static int ice_vsi_set_pvid(struct ice_vsi *vsi, u16 vid)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vsi_kill_pvid - Remove port VLAN id from the VSI
|
||||||
|
* @vsi: the VSI being changed
|
||||||
|
*/
|
||||||
|
static int ice_vsi_kill_pvid(struct ice_vsi *vsi)
|
||||||
|
{
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
|
||||||
|
if (ice_vsi_manage_vlan_stripping(vsi, false)) {
|
||||||
|
dev_err(&pf->pdev->dev, "Error removing Port VLAN on VSI %i\n",
|
||||||
|
vsi->vsi_num);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
vsi->info.pvid = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_vf_vsi_setup - Set up a VF VSI
|
* ice_vf_vsi_setup - Set up a VF VSI
|
||||||
* @pf: board private structure
|
* @pf: board private structure
|
||||||
|
@ -814,6 +877,29 @@ void ice_vc_notify_reset(struct ice_pf *pf)
|
||||||
(u8 *)&pfe, sizeof(struct virtchnl_pf_event));
|
(u8 *)&pfe, sizeof(struct virtchnl_pf_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vc_notify_vf_reset - Notify VF of a reset event
|
||||||
|
* @vf: pointer to the VF structure
|
||||||
|
*/
|
||||||
|
static void ice_vc_notify_vf_reset(struct ice_vf *vf)
|
||||||
|
{
|
||||||
|
struct virtchnl_pf_event pfe;
|
||||||
|
|
||||||
|
/* validate the request */
|
||||||
|
if (!vf || vf->vf_id >= vf->pf->num_alloc_vfs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* verify if the VF is in either init or active before proceeding */
|
||||||
|
if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states) &&
|
||||||
|
!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pfe.event = VIRTCHNL_EVENT_RESET_IMPENDING;
|
||||||
|
pfe.severity = PF_EVENT_SEVERITY_CERTAIN_DOOM;
|
||||||
|
ice_aq_send_msg_to_vf(&vf->pf->hw, vf->vf_id, VIRTCHNL_OP_EVENT, 0,
|
||||||
|
(u8 *)&pfe, sizeof(pfe), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_alloc_vfs - Allocate and set up VFs resources
|
* ice_alloc_vfs - Allocate and set up VFs resources
|
||||||
* @pf: pointer to the PF structure
|
* @pf: pointer to the PF structure
|
||||||
|
@ -1008,3 +1094,355 @@ void ice_process_vflr_event(struct ice_pf *pf)
|
||||||
ice_reset_vf(vf, true);
|
ice_reset_vf(vf, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vc_dis_vf - Disable a given VF via SW reset
|
||||||
|
* @vf: pointer to the VF info
|
||||||
|
*
|
||||||
|
* Disable the VF through a SW reset
|
||||||
|
*/
|
||||||
|
static void ice_vc_dis_vf(struct ice_vf *vf)
|
||||||
|
{
|
||||||
|
ice_vc_notify_vf_reset(vf);
|
||||||
|
ice_reset_vf(vf, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_vf_port_vlan
|
||||||
|
* @netdev: network interface device structure
|
||||||
|
* @vf_id: VF identifier
|
||||||
|
* @vlan_id: VLAN id being set
|
||||||
|
* @qos: priority setting
|
||||||
|
* @vlan_proto: VLAN protocol
|
||||||
|
*
|
||||||
|
* program VF Port VLAN id and/or qos
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
|
||||||
|
__be16 vlan_proto)
|
||||||
|
{
|
||||||
|
u16 vlanprio = vlan_id | (qos << ICE_VLAN_PRIORITY_S);
|
||||||
|
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||||
|
struct ice_pf *pf = np->vsi->back;
|
||||||
|
struct ice_vsi *vsi;
|
||||||
|
struct ice_vf *vf;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* validate the request */
|
||||||
|
if (vf_id >= pf->num_alloc_vfs) {
|
||||||
|
dev_err(&pf->pdev->dev, "invalid VF id: %d\n", vf_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vlan_id > ICE_MAX_VLANID || qos > 7) {
|
||||||
|
dev_err(&pf->pdev->dev, "Invalid VF Parameters\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vlan_proto != htons(ETH_P_8021Q)) {
|
||||||
|
dev_err(&pf->pdev->dev, "VF VLAN protocol is not supported\n");
|
||||||
|
return -EPROTONOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
vf = &pf->vf[vf_id];
|
||||||
|
vsi = pf->vsi[vf->lan_vsi_idx];
|
||||||
|
if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states)) {
|
||||||
|
dev_err(&pf->pdev->dev, "VF %d in reset. Try again.\n", vf_id);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (le16_to_cpu(vsi->info.pvid) == vlanprio) {
|
||||||
|
/* duplicate request, so just return success */
|
||||||
|
dev_info(&pf->pdev->dev,
|
||||||
|
"Duplicate pvid %d request\n", vlanprio);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If pvid, then remove all filters on the old VLAN */
|
||||||
|
if (vsi->info.pvid)
|
||||||
|
ice_vsi_kill_vlan(vsi, (le16_to_cpu(vsi->info.pvid) &
|
||||||
|
VLAN_VID_MASK));
|
||||||
|
|
||||||
|
if (vlan_id || qos) {
|
||||||
|
ret = ice_vsi_set_pvid(vsi, vlanprio);
|
||||||
|
if (ret)
|
||||||
|
goto error_set_pvid;
|
||||||
|
} else {
|
||||||
|
ice_vsi_kill_pvid(vsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vlan_id) {
|
||||||
|
dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
|
||||||
|
vlan_id, qos, vf_id);
|
||||||
|
|
||||||
|
/* add new VLAN filter for each MAC */
|
||||||
|
ret = ice_vsi_add_vlan(vsi, vlan_id);
|
||||||
|
if (ret)
|
||||||
|
goto error_set_pvid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The Port VLAN needs to be saved across resets the same as the
|
||||||
|
* default LAN MAC address.
|
||||||
|
*/
|
||||||
|
vf->port_vlan_id = le16_to_cpu(vsi->info.pvid);
|
||||||
|
|
||||||
|
error_set_pvid:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_get_vf_cfg
|
||||||
|
* @netdev: network interface device structure
|
||||||
|
* @vf_id: VF identifier
|
||||||
|
* @ivi: VF configuration structure
|
||||||
|
*
|
||||||
|
* return VF configuration
|
||||||
|
*/
|
||||||
|
int ice_get_vf_cfg(struct net_device *netdev, int vf_id,
|
||||||
|
struct ifla_vf_info *ivi)
|
||||||
|
{
|
||||||
|
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||||
|
struct ice_vsi *vsi = np->vsi;
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
struct ice_vf *vf;
|
||||||
|
|
||||||
|
/* validate the request */
|
||||||
|
if (vf_id >= pf->num_alloc_vfs) {
|
||||||
|
netdev_err(netdev, "invalid VF id: %d\n", vf_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vf = &pf->vf[vf_id];
|
||||||
|
vsi = pf->vsi[vf->lan_vsi_idx];
|
||||||
|
|
||||||
|
if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states)) {
|
||||||
|
netdev_err(netdev, "VF %d in reset. Try again.\n", vf_id);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
ivi->vf = vf_id;
|
||||||
|
ether_addr_copy(ivi->mac, vf->dflt_lan_addr.addr);
|
||||||
|
|
||||||
|
/* VF configuration for VLAN and applicable QoS */
|
||||||
|
ivi->vlan = le16_to_cpu(vsi->info.pvid) & ICE_VLAN_M;
|
||||||
|
ivi->qos = (le16_to_cpu(vsi->info.pvid) & ICE_PRIORITY_M) >>
|
||||||
|
ICE_VLAN_PRIORITY_S;
|
||||||
|
|
||||||
|
ivi->trusted = vf->trusted;
|
||||||
|
ivi->spoofchk = vf->spoofchk;
|
||||||
|
if (!vf->link_forced)
|
||||||
|
ivi->linkstate = IFLA_VF_LINK_STATE_AUTO;
|
||||||
|
else if (vf->link_up)
|
||||||
|
ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE;
|
||||||
|
else
|
||||||
|
ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE;
|
||||||
|
ivi->max_tx_rate = vf->tx_rate;
|
||||||
|
ivi->min_tx_rate = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_vf_spoofchk
|
||||||
|
* @netdev: network interface device structure
|
||||||
|
* @vf_id: VF identifier
|
||||||
|
* @ena: flag to enable or disable feature
|
||||||
|
*
|
||||||
|
* Enable or disable VF spoof checking
|
||||||
|
*/
|
||||||
|
int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
|
||||||
|
{
|
||||||
|
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||||
|
struct ice_vsi_ctx ctx = { 0 };
|
||||||
|
struct ice_vsi *vsi = np->vsi;
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
struct ice_vf *vf;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* validate the request */
|
||||||
|
if (vf_id >= pf->num_alloc_vfs) {
|
||||||
|
netdev_err(netdev, "invalid VF id: %d\n", vf_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vf = &pf->vf[vf_id];
|
||||||
|
if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states)) {
|
||||||
|
netdev_err(netdev, "VF %d in reset. Try again.\n", vf_id);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ena == vf->spoofchk) {
|
||||||
|
dev_dbg(&pf->pdev->dev, "VF spoofchk already %s\n",
|
||||||
|
ena ? "ON" : "OFF");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
|
||||||
|
|
||||||
|
if (ena) {
|
||||||
|
ctx.info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF;
|
||||||
|
ctx.info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_M;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = ice_update_vsi(&pf->hw, vsi->idx, &ctx, NULL);
|
||||||
|
if (status) {
|
||||||
|
dev_dbg(&pf->pdev->dev,
|
||||||
|
"Error %d, failed to update VSI* parameters\n", status);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
vf->spoofchk = ena;
|
||||||
|
vsi->info.sec_flags = ctx.info.sec_flags;
|
||||||
|
vsi->info.sw_flags2 = ctx.info.sw_flags2;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_vf_mac
|
||||||
|
* @netdev: network interface device structure
|
||||||
|
* @vf_id: VF identifier
|
||||||
|
* @mac: mac address
|
||||||
|
*
|
||||||
|
* program VF mac address
|
||||||
|
*/
|
||||||
|
int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
|
||||||
|
{
|
||||||
|
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||||
|
struct ice_vsi *vsi = np->vsi;
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
struct ice_vf *vf;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* validate the request */
|
||||||
|
if (vf_id >= pf->num_alloc_vfs) {
|
||||||
|
netdev_err(netdev, "invalid VF id: %d\n", vf_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vf = &pf->vf[vf_id];
|
||||||
|
if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states)) {
|
||||||
|
netdev_err(netdev, "VF %d in reset. Try again.\n", vf_id);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_zero_ether_addr(mac) || is_multicast_ether_addr(mac)) {
|
||||||
|
netdev_err(netdev, "%pM not a valid unicast address\n", mac);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy mac into dflt_lan_addr and trigger a VF reset. The reset
|
||||||
|
* flow will use the updated dflt_lan_addr and add a MAC filter
|
||||||
|
* using ice_add_mac. Also set pf_set_mac to indicate that the PF has
|
||||||
|
* set the MAC address for this VF.
|
||||||
|
*/
|
||||||
|
ether_addr_copy(vf->dflt_lan_addr.addr, mac);
|
||||||
|
vf->pf_set_mac = true;
|
||||||
|
netdev_info(netdev,
|
||||||
|
"mac on VF %d set to %pM\n. VF driver will be reinitialized\n",
|
||||||
|
vf_id, mac);
|
||||||
|
|
||||||
|
ice_vc_dis_vf(vf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_vf_trust
|
||||||
|
* @netdev: network interface device structure
|
||||||
|
* @vf_id: VF identifier
|
||||||
|
* @trusted: Boolean value to enable/disable trusted VF
|
||||||
|
*
|
||||||
|
* Enable or disable a given VF as trusted
|
||||||
|
*/
|
||||||
|
int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
|
||||||
|
{
|
||||||
|
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||||
|
struct ice_vsi *vsi = np->vsi;
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
struct ice_vf *vf;
|
||||||
|
|
||||||
|
/* validate the request */
|
||||||
|
if (vf_id >= pf->num_alloc_vfs) {
|
||||||
|
dev_err(&pf->pdev->dev, "invalid VF id: %d\n", vf_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vf = &pf->vf[vf_id];
|
||||||
|
if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states)) {
|
||||||
|
dev_err(&pf->pdev->dev, "VF %d in reset. Try again.\n", vf_id);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if already trusted */
|
||||||
|
if (trusted == vf->trusted)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
vf->trusted = trusted;
|
||||||
|
ice_vc_dis_vf(vf);
|
||||||
|
dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
|
||||||
|
vf_id, trusted ? "" : "un");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_vf_link_state
|
||||||
|
* @netdev: network interface device structure
|
||||||
|
* @vf_id: VF identifier
|
||||||
|
* @link_state: required link state
|
||||||
|
*
|
||||||
|
* Set VF's link state, irrespective of physical link state status
|
||||||
|
*/
|
||||||
|
int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state)
|
||||||
|
{
|
||||||
|
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||||
|
struct ice_pf *pf = np->vsi->back;
|
||||||
|
struct virtchnl_pf_event pfe = { 0 };
|
||||||
|
struct ice_link_status *ls;
|
||||||
|
struct ice_vf *vf;
|
||||||
|
struct ice_hw *hw;
|
||||||
|
|
||||||
|
if (vf_id >= pf->num_alloc_vfs) {
|
||||||
|
dev_err(&pf->pdev->dev, "Invalid VF Identifier %d\n", vf_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vf = &pf->vf[vf_id];
|
||||||
|
hw = &pf->hw;
|
||||||
|
ls = &pf->hw.port_info->phy.link_info;
|
||||||
|
|
||||||
|
if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states)) {
|
||||||
|
dev_err(&pf->pdev->dev, "vf %d in reset. Try again.\n", vf_id);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
|
||||||
|
pfe.severity = PF_EVENT_SEVERITY_INFO;
|
||||||
|
|
||||||
|
switch (link_state) {
|
||||||
|
case IFLA_VF_LINK_STATE_AUTO:
|
||||||
|
vf->link_forced = false;
|
||||||
|
vf->link_up = ls->link_info & ICE_AQ_LINK_UP;
|
||||||
|
break;
|
||||||
|
case IFLA_VF_LINK_STATE_ENABLE:
|
||||||
|
vf->link_forced = true;
|
||||||
|
vf->link_up = true;
|
||||||
|
break;
|
||||||
|
case IFLA_VF_LINK_STATE_DISABLE:
|
||||||
|
vf->link_forced = true;
|
||||||
|
vf->link_up = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vf->link_forced)
|
||||||
|
ice_set_pfe_link_forced(vf, &pfe, vf->link_up);
|
||||||
|
else
|
||||||
|
ice_set_pfe_link(vf, &pfe, ls->link_speed, vf->link_up);
|
||||||
|
|
||||||
|
/* Notify the VF of its new link state */
|
||||||
|
ice_aq_send_msg_to_vf(hw, vf->vf_id, VIRTCHNL_OP_EVENT, 0, (u8 *)&pfe,
|
||||||
|
sizeof(pfe), NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
#define _ICE_VIRTCHNL_PF_H_
|
#define _ICE_VIRTCHNL_PF_H_
|
||||||
#include "ice.h"
|
#include "ice.h"
|
||||||
|
|
||||||
|
#define ICE_MAX_VLANID 4095
|
||||||
|
#define ICE_VLAN_PRIORITY_S 12
|
||||||
|
#define ICE_VLAN_M 0xFFF
|
||||||
|
#define ICE_PRIORITY_M 0x7000
|
||||||
|
|
||||||
/* Static VF transaction/status register def */
|
/* Static VF transaction/status register def */
|
||||||
#define VF_DEVICE_STATUS 0xAA
|
#define VF_DEVICE_STATUS 0xAA
|
||||||
#define VF_TRANS_PENDING_M 0x20
|
#define VF_TRANS_PENDING_M 0x20
|
||||||
|
@ -36,15 +41,20 @@ struct ice_vf {
|
||||||
struct ice_pf *pf;
|
struct ice_pf *pf;
|
||||||
|
|
||||||
s16 vf_id; /* VF id in the PF space */
|
s16 vf_id; /* VF id in the PF space */
|
||||||
|
u32 driver_caps; /* reported by VF driver */
|
||||||
int first_vector_idx; /* first vector index of this VF */
|
int first_vector_idx; /* first vector index of this VF */
|
||||||
struct ice_sw *vf_sw_id; /* switch id the VF VSIs connect to */
|
struct ice_sw *vf_sw_id; /* switch id the VF VSIs connect to */
|
||||||
struct virtchnl_ether_addr dflt_lan_addr;
|
struct virtchnl_ether_addr dflt_lan_addr;
|
||||||
u16 port_vlan_id;
|
u16 port_vlan_id;
|
||||||
|
u8 pf_set_mac; /* VF MAC address set by VMM admin */
|
||||||
u8 trusted;
|
u8 trusted;
|
||||||
u16 lan_vsi_idx; /* index into PF struct */
|
u16 lan_vsi_idx; /* index into PF struct */
|
||||||
u16 lan_vsi_num; /* ID as used by firmware */
|
u16 lan_vsi_num; /* ID as used by firmware */
|
||||||
unsigned long vf_caps; /* vf's adv. capabilities */
|
unsigned long vf_caps; /* vf's adv. capabilities */
|
||||||
DECLARE_BITMAP(vf_states, ICE_VF_STATES_NBITS); /* VF runtime states */
|
DECLARE_BITMAP(vf_states, ICE_VF_STATES_NBITS); /* VF runtime states */
|
||||||
|
unsigned int tx_rate; /* Tx bandwidth limit in Mbps */
|
||||||
|
u8 link_forced;
|
||||||
|
u8 link_up; /* only valid if VF link is forced */
|
||||||
u8 spoofchk;
|
u8 spoofchk;
|
||||||
u16 num_mac;
|
u16 num_mac;
|
||||||
u16 num_vlan;
|
u16 num_vlan;
|
||||||
|
@ -53,14 +63,29 @@ struct ice_vf {
|
||||||
#ifdef CONFIG_PCI_IOV
|
#ifdef CONFIG_PCI_IOV
|
||||||
void ice_process_vflr_event(struct ice_pf *pf);
|
void ice_process_vflr_event(struct ice_pf *pf);
|
||||||
int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
|
int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
|
||||||
|
int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
|
||||||
|
int ice_get_vf_cfg(struct net_device *netdev, int vf_id,
|
||||||
|
struct ifla_vf_info *ivi);
|
||||||
|
|
||||||
void ice_free_vfs(struct ice_pf *pf);
|
void ice_free_vfs(struct ice_pf *pf);
|
||||||
void ice_vc_notify_reset(struct ice_pf *pf);
|
void ice_vc_notify_reset(struct ice_pf *pf);
|
||||||
bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr);
|
bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr);
|
||||||
|
|
||||||
|
int ice_set_vf_port_vlan(struct net_device *netdev, int vf_id,
|
||||||
|
u16 vlan_id, u8 qos, __be16 vlan_proto);
|
||||||
|
|
||||||
|
int ice_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,
|
||||||
|
int max_tx_rate);
|
||||||
|
|
||||||
|
int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted);
|
||||||
|
|
||||||
|
int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state);
|
||||||
|
|
||||||
|
int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena);
|
||||||
#else /* CONFIG_PCI_IOV */
|
#else /* CONFIG_PCI_IOV */
|
||||||
#define ice_process_vflr_event(pf) do {} while (0)
|
#define ice_process_vflr_event(pf) do {} while (0)
|
||||||
#define ice_free_vfs(pf) do {} while (0)
|
#define ice_free_vfs(pf) do {} while (0)
|
||||||
#define ice_vc_notify_reset(pf) do {} while (0)
|
#define ice_vc_notify_reset(pf) do {} while (0)
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
ice_reset_all_vfs(struct ice_pf __always_unused *pf,
|
ice_reset_all_vfs(struct ice_pf __always_unused *pf,
|
||||||
bool __always_unused is_vflr)
|
bool __always_unused is_vflr)
|
||||||
|
@ -74,5 +99,57 @@ ice_sriov_configure(struct pci_dev __always_unused *pdev,
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ice_set_vf_mac(struct net_device __always_unused *netdev,
|
||||||
|
int __always_unused vf_id, u8 __always_unused *mac)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ice_get_vf_cfg(struct net_device __always_unused *netdev,
|
||||||
|
int __always_unused vf_id,
|
||||||
|
struct ifla_vf_info __always_unused *ivi)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ice_set_vf_trust(struct net_device __always_unused *netdev,
|
||||||
|
int __always_unused vf_id, bool __always_unused trusted)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ice_set_vf_port_vlan(struct net_device __always_unused *netdev,
|
||||||
|
int __always_unused vf_id, u16 __always_unused vid,
|
||||||
|
u8 __always_unused qos, __be16 __always_unused v_proto)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ice_set_vf_spoofchk(struct net_device __always_unused *netdev,
|
||||||
|
int __always_unused vf_id, bool __always_unused ena)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ice_set_vf_link_state(struct net_device __always_unused *netdev,
|
||||||
|
int __always_unused vf_id, int __always_unused link_state)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ice_set_vf_bw(struct net_device __always_unused *netdev,
|
||||||
|
int __always_unused vf_id, int __always_unused min_tx_rate,
|
||||||
|
int __always_unused max_tx_rate)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
#endif /* CONFIG_PCI_IOV */
|
#endif /* CONFIG_PCI_IOV */
|
||||||
#endif /* _ICE_VIRTCHNL_PF_H_ */
|
#endif /* _ICE_VIRTCHNL_PF_H_ */
|
||||||
|
|
Loading…
Reference in New Issue