Skip to content

Commit e0ef26f

Browse files
bcreeley13Jeff Kirsher
authored andcommitted
iavf: fix speed reporting over virtchnl
Link speeds are communicated over virtchnl using an enum virtchnl_link_speed. Currently, the highest link speed is 40Gbps which leaves us unable to reflect some speeds that an ice VF is capable of. This causes link speed to be misreported on the iavf driver. Allow for communicating link speeds using Mbps so that the proper speed can be reported for an ice VF. Moving away from the enum allows us to communicate future speed changes without requiring a new enum to be added. In order to support communicating link speeds over virtchnl in Mbps the following functionality was added: - Added u32 link_speed_mbps in the iavf_adapter structure. - Added the macro ADV_LINK_SUPPORT(_a) to determine if the VF driver supports communicating link speeds in Mbps. - Added the function iavf_get_vpe_link_status() to fill the correct link_status in the event_data union based on the ADV_LINK_SUPPORT(_a) macro. - Added the function iavf_set_adapter_link_speed_from_vpe() to determine whether or not to fill the u32 link_speed_mbps or enum virtchnl_link_speed link_speed field in the iavf_adapter structure based on the ADV_LINK_SUPPORT(_a) macro. - Do not free vf_res in iavf_init_get_resources() as vf_res will be accessed in iavf_get_link_ksettings(); memset to 0 instead. This memory is subsequently freed in iavf_remove(). Fixes: 7c71086 ("ice: Add handlers for VF netdevice operations") Signed-off-by: Brett Creeley <[email protected]> Signed-off-by: Sergey Nemov <[email protected]> Signed-off-by: Paul Greenwalt <[email protected]> Signed-off-by: Tony Nguyen <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 9798278 commit e0ef26f

File tree

4 files changed

+120
-21
lines changed

4 files changed

+120
-21
lines changed

drivers/net/ethernet/intel/iavf/iavf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ struct iavf_vsi {
8787
#define IAVF_HLUT_ARRAY_SIZE ((IAVF_VFQF_HLUT_MAX_INDEX + 1) * 4)
8888
#define IAVF_MBPS_DIVISOR 125000 /* divisor to convert to Mbps */
8989

90+
#define IAVF_VIRTCHNL_VF_RESOURCE_SIZE (sizeof(struct virtchnl_vf_resource) + \
91+
(IAVF_MAX_VF_VSI * \
92+
sizeof(struct virtchnl_vsi_resource)))
93+
9094
/* MAX_MSIX_Q_VECTORS of these are allocated,
9195
* but we only use one per queue-specific vector.
9296
*/
@@ -306,6 +310,14 @@ struct iavf_adapter {
306310
bool netdev_registered;
307311
bool link_up;
308312
enum virtchnl_link_speed link_speed;
313+
/* This is only populated if the VIRTCHNL_VF_CAP_ADV_LINK_SPEED is set
314+
* in vf_res->vf_cap_flags. Use ADV_LINK_SUPPORT macro to determine if
315+
* this field is valid. This field should be used going forward and the
316+
* enum virtchnl_link_speed above should be considered the legacy way of
317+
* storing/communicating link speeds.
318+
*/
319+
u32 link_speed_mbps;
320+
309321
enum virtchnl_ops current_op;
310322
#define CLIENT_ALLOWED(_a) ((_a)->vf_res ? \
311323
(_a)->vf_res->vf_cap_flags & \
@@ -322,6 +334,8 @@ struct iavf_adapter {
322334
VIRTCHNL_VF_OFFLOAD_RSS_PF)))
323335
#define VLAN_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \
324336
VIRTCHNL_VF_OFFLOAD_VLAN)
337+
#define ADV_LINK_SUPPORT(_a) ((_a)->vf_res->vf_cap_flags & \
338+
VIRTCHNL_VF_CAP_ADV_LINK_SPEED)
325339
struct virtchnl_vf_resource *vf_res; /* incl. all VSIs */
326340
struct virtchnl_vsi_resource *vsi_res; /* our LAN VSI */
327341
struct virtchnl_version_info pf_version;

drivers/net/ethernet/intel/iavf/iavf_ethtool.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,18 @@ static int iavf_get_link_ksettings(struct net_device *netdev,
278278
ethtool_link_ksettings_zero_link_mode(cmd, supported);
279279
cmd->base.autoneg = AUTONEG_DISABLE;
280280
cmd->base.port = PORT_NONE;
281-
/* Set speed and duplex */
281+
cmd->base.duplex = DUPLEX_FULL;
282+
283+
if (ADV_LINK_SUPPORT(adapter)) {
284+
if (adapter->link_speed_mbps &&
285+
adapter->link_speed_mbps < U32_MAX)
286+
cmd->base.speed = adapter->link_speed_mbps;
287+
else
288+
cmd->base.speed = SPEED_UNKNOWN;
289+
290+
return 0;
291+
}
292+
282293
switch (adapter->link_speed) {
283294
case IAVF_LINK_SPEED_40GB:
284295
cmd->base.speed = SPEED_40000;
@@ -306,7 +317,6 @@ static int iavf_get_link_ksettings(struct net_device *netdev,
306317
default:
307318
break;
308319
}
309-
cmd->base.duplex = DUPLEX_FULL;
310320

311321
return 0;
312322
}

drivers/net/ethernet/intel/iavf/iavf_main.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,17 +1756,17 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter)
17561756
struct net_device *netdev = adapter->netdev;
17571757
struct pci_dev *pdev = adapter->pdev;
17581758
struct iavf_hw *hw = &adapter->hw;
1759-
int err = 0, bufsz;
1759+
int err;
17601760

17611761
WARN_ON(adapter->state != __IAVF_INIT_GET_RESOURCES);
17621762
/* aq msg sent, awaiting reply */
17631763
if (!adapter->vf_res) {
1764-
bufsz = sizeof(struct virtchnl_vf_resource) +
1765-
(IAVF_MAX_VF_VSI *
1766-
sizeof(struct virtchnl_vsi_resource));
1767-
adapter->vf_res = kzalloc(bufsz, GFP_KERNEL);
1768-
if (!adapter->vf_res)
1764+
adapter->vf_res = kzalloc(IAVF_VIRTCHNL_VF_RESOURCE_SIZE,
1765+
GFP_KERNEL);
1766+
if (!adapter->vf_res) {
1767+
err = -ENOMEM;
17691768
goto err;
1769+
}
17701770
}
17711771
err = iavf_get_vf_config(adapter);
17721772
if (err == IAVF_ERR_ADMIN_QUEUE_NO_WORK) {
@@ -2036,7 +2036,7 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
20362036
iavf_reset_interrupt_capability(adapter);
20372037
iavf_free_queues(adapter);
20382038
iavf_free_q_vectors(adapter);
2039-
kfree(adapter->vf_res);
2039+
memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE);
20402040
iavf_shutdown_adminq(&adapter->hw);
20412041
adapter->netdev->flags &= ~IFF_UP;
20422042
clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
@@ -2487,6 +2487,16 @@ static int iavf_validate_tx_bandwidth(struct iavf_adapter *adapter,
24872487
{
24882488
int speed = 0, ret = 0;
24892489

2490+
if (ADV_LINK_SUPPORT(adapter)) {
2491+
if (adapter->link_speed_mbps < U32_MAX) {
2492+
speed = adapter->link_speed_mbps;
2493+
goto validate_bw;
2494+
} else {
2495+
dev_err(&adapter->pdev->dev, "Unknown link speed\n");
2496+
return -EINVAL;
2497+
}
2498+
}
2499+
24902500
switch (adapter->link_speed) {
24912501
case IAVF_LINK_SPEED_40GB:
24922502
speed = 40000;
@@ -2510,6 +2520,7 @@ static int iavf_validate_tx_bandwidth(struct iavf_adapter *adapter,
25102520
break;
25112521
}
25122522

2523+
validate_bw:
25132524
if (max_tx_rate > speed) {
25142525
dev_err(&adapter->pdev->dev,
25152526
"Invalid tx rate specified\n");

drivers/net/ethernet/intel/iavf/iavf_virtchnl.c

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ int iavf_send_vf_config_msg(struct iavf_adapter *adapter)
139139
VIRTCHNL_VF_OFFLOAD_ENCAP |
140140
VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
141141
VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
142-
VIRTCHNL_VF_OFFLOAD_ADQ;
142+
VIRTCHNL_VF_OFFLOAD_ADQ |
143+
VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
143144

144145
adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
145146
adapter->aq_required &= ~IAVF_FLAG_AQ_GET_CONFIG;
@@ -891,6 +892,8 @@ void iavf_disable_vlan_stripping(struct iavf_adapter *adapter)
891892
iavf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING, NULL, 0);
892893
}
893894

895+
#define IAVF_MAX_SPEED_STRLEN 13
896+
894897
/**
895898
* iavf_print_link_message - print link up or down
896899
* @adapter: adapter structure
@@ -900,37 +903,99 @@ void iavf_disable_vlan_stripping(struct iavf_adapter *adapter)
900903
static void iavf_print_link_message(struct iavf_adapter *adapter)
901904
{
902905
struct net_device *netdev = adapter->netdev;
903-
char *speed = "Unknown ";
906+
int link_speed_mbps;
907+
char *speed;
904908

905909
if (!adapter->link_up) {
906910
netdev_info(netdev, "NIC Link is Down\n");
907911
return;
908912
}
909913

914+
speed = kcalloc(1, IAVF_MAX_SPEED_STRLEN, GFP_KERNEL);
915+
if (!speed)
916+
return;
917+
918+
if (ADV_LINK_SUPPORT(adapter)) {
919+
link_speed_mbps = adapter->link_speed_mbps;
920+
goto print_link_msg;
921+
}
922+
910923
switch (adapter->link_speed) {
911924
case IAVF_LINK_SPEED_40GB:
912-
speed = "40 G";
925+
link_speed_mbps = SPEED_40000;
913926
break;
914927
case IAVF_LINK_SPEED_25GB:
915-
speed = "25 G";
928+
link_speed_mbps = SPEED_25000;
916929
break;
917930
case IAVF_LINK_SPEED_20GB:
918-
speed = "20 G";
931+
link_speed_mbps = SPEED_20000;
919932
break;
920933
case IAVF_LINK_SPEED_10GB:
921-
speed = "10 G";
934+
link_speed_mbps = SPEED_10000;
922935
break;
923936
case IAVF_LINK_SPEED_1GB:
924-
speed = "1000 M";
937+
link_speed_mbps = SPEED_1000;
925938
break;
926939
case IAVF_LINK_SPEED_100MB:
927-
speed = "100 M";
940+
link_speed_mbps = SPEED_100;
928941
break;
929942
default:
943+
link_speed_mbps = SPEED_UNKNOWN;
930944
break;
931945
}
932946

933-
netdev_info(netdev, "NIC Link is Up %sbps Full Duplex\n", speed);
947+
print_link_msg:
948+
if (link_speed_mbps > SPEED_1000) {
949+
if (link_speed_mbps == SPEED_2500)
950+
snprintf(speed, IAVF_MAX_SPEED_STRLEN, "2.5 Gbps");
951+
else
952+
/* convert to Gbps inline */
953+
snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%d %s",
954+
link_speed_mbps / 1000, "Gbps");
955+
} else if (link_speed_mbps == SPEED_UNKNOWN) {
956+
snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%s", "Unknown Mbps");
957+
} else {
958+
snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%u %s",
959+
link_speed_mbps, "Mbps");
960+
}
961+
962+
netdev_info(netdev, "NIC Link is Up Speed is %s Full Duplex\n", speed);
963+
kfree(speed);
964+
}
965+
966+
/**
967+
* iavf_get_vpe_link_status
968+
* @adapter: adapter structure
969+
* @vpe: virtchnl_pf_event structure
970+
*
971+
* Helper function for determining the link status
972+
**/
973+
static bool
974+
iavf_get_vpe_link_status(struct iavf_adapter *adapter,
975+
struct virtchnl_pf_event *vpe)
976+
{
977+
if (ADV_LINK_SUPPORT(adapter))
978+
return vpe->event_data.link_event_adv.link_status;
979+
else
980+
return vpe->event_data.link_event.link_status;
981+
}
982+
983+
/**
984+
* iavf_set_adapter_link_speed_from_vpe
985+
* @adapter: adapter structure for which we are setting the link speed
986+
* @vpe: virtchnl_pf_event structure that contains the link speed we are setting
987+
*
988+
* Helper function for setting iavf_adapter link speed
989+
**/
990+
static void
991+
iavf_set_adapter_link_speed_from_vpe(struct iavf_adapter *adapter,
992+
struct virtchnl_pf_event *vpe)
993+
{
994+
if (ADV_LINK_SUPPORT(adapter))
995+
adapter->link_speed_mbps =
996+
vpe->event_data.link_event_adv.link_speed;
997+
else
998+
adapter->link_speed = vpe->event_data.link_event.link_speed;
934999
}
9351000

9361001
/**
@@ -1160,12 +1225,11 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
11601225
if (v_opcode == VIRTCHNL_OP_EVENT) {
11611226
struct virtchnl_pf_event *vpe =
11621227
(struct virtchnl_pf_event *)msg;
1163-
bool link_up = vpe->event_data.link_event.link_status;
1228+
bool link_up = iavf_get_vpe_link_status(adapter, vpe);
11641229

11651230
switch (vpe->event) {
11661231
case VIRTCHNL_EVENT_LINK_CHANGE:
1167-
adapter->link_speed =
1168-
vpe->event_data.link_event.link_speed;
1232+
iavf_set_adapter_link_speed_from_vpe(adapter, vpe);
11691233

11701234
/* we've already got the right link status, bail */
11711235
if (adapter->link_up == link_up)

0 commit comments

Comments
 (0)