Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f373b15 authored by Fuyun Liang's avatar Fuyun Liang Committed by David S. Miller
Browse files

net: hns3: Fix speed/duplex information loss problem when executing ethtool ethx cmd of VF



Our VF has not implemented the ops for get_port_type. So when we executing
ethtool ethx cmd of VF, hns3_get_link_ksettings will return directly. And
we can not query anything.

To support get_link_ksettings for VF, this patch replaces get_port_type
with get_media_type. If the media type is HNAE3_MEDIA_TYPE_NONE,
hns3_get_link_ksettings will return link information of VF.

Fixes: 12f46bc1 ("net: hns3: Refine hns3_get_link_ksettings()")
Signed-off-by: default avatarFuyun Liang <liangfuyun1@huawei.com>
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarSalil Mehta <salil.mehta@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c136b884
Loading
Loading
Loading
Loading
+39 −27
Original line number Diff line number Diff line
@@ -545,32 +545,17 @@ static int hns3_set_pauseparam(struct net_device *netdev,
	return -EOPNOTSUPP;
}

static int hns3_get_link_ksettings(struct net_device *netdev,
static void hns3_get_ksettings(struct hnae3_handle *h,
			       struct ethtool_link_ksettings *cmd)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);
	const struct hnae3_ae_ops *ops;
	u8 link_stat;

	if (!h->ae_algo || !h->ae_algo->ops)
		return -EOPNOTSUPP;

	ops = h->ae_algo->ops;
	if (ops->get_port_type)
		ops->get_port_type(h, &cmd->base.port);
	else
		return -EOPNOTSUPP;
	const struct hnae3_ae_ops *ops = h->ae_algo->ops;

	switch (cmd->base.port) {
	case PORT_FIBRE:
	/* 1.auto_neg & speed & duplex from cmd */
	if (ops->get_ksettings_an_result)
		ops->get_ksettings_an_result(h,
					     &cmd->base.autoneg,
					     &cmd->base.speed,
					     &cmd->base.duplex);
		else
			return -EOPNOTSUPP;

	/* 2.get link mode*/
	if (ops->get_link_mode)
@@ -582,18 +567,45 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
	if (ops->get_mdix_mode)
		ops->get_mdix_mode(h, &cmd->base.eth_tp_mdix_ctrl,
				   &cmd->base.eth_tp_mdix);
}

static int hns3_get_link_ksettings(struct net_device *netdev,
				   struct ethtool_link_ksettings *cmd)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);
	const struct hnae3_ae_ops *ops;
	u8 media_type;
	u8 link_stat;

	if (!h->ae_algo || !h->ae_algo->ops)
		return -EOPNOTSUPP;

	ops = h->ae_algo->ops;
	if (ops->get_media_type)
		ops->get_media_type(h, &media_type);
	else
		return -EOPNOTSUPP;

	switch (media_type) {
	case HNAE3_MEDIA_TYPE_NONE:
		cmd->base.port = PORT_NONE;
		hns3_get_ksettings(h, cmd);
		break;
	case HNAE3_MEDIA_TYPE_FIBER:
		cmd->base.port = PORT_FIBRE;
		hns3_get_ksettings(h, cmd);
		break;
	case PORT_TP:
	case HNAE3_MEDIA_TYPE_COPPER:
		if (!netdev->phydev)
			return -EOPNOTSUPP;

		cmd->base.port = PORT_TP;
		phy_ethtool_ksettings_get(netdev->phydev, cmd);

		break;
	default:
		netdev_warn(netdev,
			    "Unknown port type, neither Fibre/Copper detected");

		netdev_warn(netdev, "Unknown media type");
		return 0;
	}