}
/**
+ * i40e_vc_link_speed2mbps
+ * converts i40e_aq_link_speed to integer value of Mbps
+ * @link_speed: the speed to convert
+ *
+ * return the speed as direct value of Mbps.
+ **/
+static u32
+i40e_vc_link_speed2mbps(enum i40e_aq_link_speed link_speed)
+{
+ switch (link_speed) {
+ case I40E_LINK_SPEED_100MB:
+ return SPEED_100;
+ case I40E_LINK_SPEED_1GB:
+ return SPEED_1000;
+ case I40E_LINK_SPEED_2_5GB:
+ return SPEED_2500;
+ case I40E_LINK_SPEED_5GB:
+ return SPEED_5000;
+ case I40E_LINK_SPEED_10GB:
+ return SPEED_10000;
+ case I40E_LINK_SPEED_20GB:
+ return SPEED_20000;
+ case I40E_LINK_SPEED_25GB:
+ return SPEED_25000;
+ case I40E_LINK_SPEED_40GB:
+ return SPEED_40000;
+ case I40E_LINK_SPEED_UNKNOWN:
+ return SPEED_UNKNOWN;
+ }
+ return SPEED_UNKNOWN;
+}
+
+/**
+ * i40e_set_vf_link_state
+ * @vf: pointer to the VF structure
+ * @pfe: pointer to PF event structure
+ * @ls: pointer to link status structure
+ *
+ * set a link state on a single vf
+ **/
+static void i40e_set_vf_link_state(struct i40e_vf *vf,
+ struct virtchnl_pf_event *pfe, struct i40e_link_status *ls)
+{
+ u8 link_status = ls->link_info & I40E_AQ_LINK_UP;
+
+ if (vf->link_forced)
+ link_status = vf->link_up;
+
+ if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) {
+ pfe->event_data.link_event_adv.link_speed = link_status ?
+ i40e_vc_link_speed2mbps(ls->link_speed) : 0;
+ pfe->event_data.link_event_adv.link_status = link_status;
+ } else {
+ pfe->event_data.link_event.link_speed = link_status ?
+ i40e_virtchnl_link_speed(ls->link_speed) : 0;
+ pfe->event_data.link_event.link_status = link_status;
+ }
+}
+
+/**
* i40e_vc_notify_vf_link_state
* @vf: pointer to the VF structure
*
pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
pfe.severity = PF_EVENT_SEVERITY_INFO;
- if (vf->link_forced) {
- pfe.event_data.link_event.link_status = vf->link_up;
- pfe.event_data.link_event.link_speed =
- (vf->link_up ? i40e_virtchnl_link_speed(ls->link_speed) : 0);
- } else {
- pfe.event_data.link_event.link_status =
- ls->link_info & I40E_AQ_LINK_UP;
- pfe.event_data.link_event.link_speed =
- i40e_virtchnl_link_speed(ls->link_speed);
- }
+
+ i40e_set_vf_link_state(vf, &pfe, ls);
+
i40e_aq_send_msg_to_vf(hw, abs_vf_id, VIRTCHNL_OP_EVENT,
0, (u8 *)&pfe, sizeof(pfe), NULL);
}
VIRTCHNL_VF_OFFLOAD_VLAN;
vfres->vf_cap_flags = VIRTCHNL_VF_OFFLOAD_L2;
+ vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
vsi = pf->vsi[vf->lan_vsi_idx];
if (!vsi->info.pvid)
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_VLAN;
}
/* get link speed in MB to validate rate limit */
- switch (ls->link_speed) {
- case VIRTCHNL_LINK_SPEED_100MB:
- speed = SPEED_100;
- break;
- case VIRTCHNL_LINK_SPEED_1GB:
- speed = SPEED_1000;
- break;
- case VIRTCHNL_LINK_SPEED_10GB:
- speed = SPEED_10000;
- break;
- case VIRTCHNL_LINK_SPEED_20GB:
- speed = SPEED_20000;
- break;
- case VIRTCHNL_LINK_SPEED_25GB:
- speed = SPEED_25000;
- break;
- case VIRTCHNL_LINK_SPEED_40GB:
- speed = SPEED_40000;
- break;
- default:
+ speed = i40e_vc_link_speed2mbps(ls->link_speed);
+ if (speed == SPEED_UNKNOWN) {
dev_err(&pf->pdev->dev,
"Cannot detect link speed\n");
aq_ret = I40E_ERR_PARAM;
switch (link) {
case IFLA_VF_LINK_STATE_AUTO:
vf->link_forced = false;
- pfe.event_data.link_event.link_status =
- pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP;
- pfe.event_data.link_event.link_speed =
- (enum virtchnl_link_speed)
- pf->hw.phy.link_info.link_speed;
+ i40e_set_vf_link_state(vf, &pfe, ls);
break;
case IFLA_VF_LINK_STATE_ENABLE:
vf->link_forced = true;
vf->link_up = true;
- pfe.event_data.link_event.link_status = true;
- pfe.event_data.link_event.link_speed = i40e_virtchnl_link_speed(ls->link_speed);
+ i40e_set_vf_link_state(vf, &pfe, ls);
break;
case IFLA_VF_LINK_STATE_DISABLE:
vf->link_forced = true;
vf->link_up = false;
- pfe.event_data.link_event.link_status = false;
- pfe.event_data.link_event.link_speed = 0;
+ i40e_set_vf_link_state(vf, &pfe, ls);
break;
default:
ret = -EINVAL;