Skip to content

Commit 22f48e2

Browse files
IronShendavem330
authored andcommitted
net: hns3: add autoneg and change speed support for fibre port
Previously, our driver only supports phydev to autoneg or change port speed. This patch adds support for fibre port, driver gets media speed capability and autoneg capability from firmware. If the media supports multiple speeds, user can change port speed with command "ethtool -s <devname> speed xxxx autoneg off duplex full". If autoneg on, the user configuration may be overwritten by the autoneg result. Signed-off-by: Jian Shen <[email protected]> Signed-off-by: Peng Li <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 88d10bd commit 22f48e2

File tree

3 files changed

+163
-11
lines changed

3 files changed

+163
-11
lines changed

drivers/net/ethernet/hisilicon/hns3/hnae3.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ struct hnae3_ae_dev {
244244
* Get negotiation status,speed and duplex
245245
* get_media_type()
246246
* Get media type of MAC
247+
* check_port_speed()
248+
* Check target speed whether is supported
247249
* adjust_link()
248250
* Adjust link status
249251
* set_loopback()
@@ -260,6 +262,8 @@ struct hnae3_ae_dev {
260262
* set auto autonegotiation of pause frame use
261263
* get_autoneg()
262264
* get auto autonegotiation of pause frame use
265+
* restart_autoneg()
266+
* restart autonegotiation
263267
* get_coalesce_usecs()
264268
* get usecs to delay a TX interrupt after a packet is sent
265269
* get_rx_max_coalesced_frames()
@@ -355,6 +359,7 @@ struct hnae3_ae_ops {
355359

356360
void (*get_media_type)(struct hnae3_handle *handle, u8 *media_type,
357361
u8 *module_type);
362+
int (*check_port_speed)(struct hnae3_handle *handle, u32 speed);
358363
void (*adjust_link)(struct hnae3_handle *handle, int speed, int duplex);
359364
int (*set_loopback)(struct hnae3_handle *handle,
360365
enum hnae3_loop loop_mode, bool en);
@@ -370,6 +375,7 @@ struct hnae3_ae_ops {
370375

371376
int (*set_autoneg)(struct hnae3_handle *handle, bool enable);
372377
int (*get_autoneg)(struct hnae3_handle *handle);
378+
int (*restart_autoneg)(struct hnae3_handle *handle);
373379

374380
void (*get_coalesce_usecs)(struct hnae3_handle *handle,
375381
u32 *tx_usecs, u32 *rx_usecs);

drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -659,18 +659,79 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
659659
return 0;
660660
}
661661

662+
static int hns3_check_ksettings_param(struct net_device *netdev,
663+
const struct ethtool_link_ksettings *cmd)
664+
{
665+
struct hnae3_handle *handle = hns3_get_handle(netdev);
666+
const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
667+
u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN;
668+
u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
669+
u8 autoneg;
670+
u32 speed;
671+
u8 duplex;
672+
int ret;
673+
674+
if (ops->get_ksettings_an_result) {
675+
ops->get_ksettings_an_result(handle, &autoneg, &speed, &duplex);
676+
if (cmd->base.autoneg == autoneg && cmd->base.speed == speed &&
677+
cmd->base.duplex == duplex)
678+
return 0;
679+
}
680+
681+
if (ops->get_media_type)
682+
ops->get_media_type(handle, &media_type, &module_type);
683+
684+
if (cmd->base.duplex != DUPLEX_FULL &&
685+
media_type != HNAE3_MEDIA_TYPE_COPPER) {
686+
netdev_err(netdev,
687+
"only copper port supports half duplex!");
688+
return -EINVAL;
689+
}
690+
691+
if (ops->check_port_speed) {
692+
ret = ops->check_port_speed(handle, cmd->base.speed);
693+
if (ret) {
694+
netdev_err(netdev, "unsupported speed\n");
695+
return ret;
696+
}
697+
}
698+
699+
return 0;
700+
}
701+
662702
static int hns3_set_link_ksettings(struct net_device *netdev,
663703
const struct ethtool_link_ksettings *cmd)
664704
{
665-
/* Chip doesn't support this mode. */
705+
struct hnae3_handle *handle = hns3_get_handle(netdev);
706+
const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
707+
int ret = 0;
708+
709+
/* Chip don't support this mode. */
666710
if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF)
667711
return -EINVAL;
668712

669713
/* Only support ksettings_set for netdev with phy attached for now */
670714
if (netdev->phydev)
671715
return phy_ethtool_ksettings_set(netdev->phydev, cmd);
672716

673-
return -EOPNOTSUPP;
717+
if (handle->pdev->revision == 0x20)
718+
return -EOPNOTSUPP;
719+
720+
ret = hns3_check_ksettings_param(netdev, cmd);
721+
if (ret)
722+
return ret;
723+
724+
if (ops->set_autoneg) {
725+
ret = ops->set_autoneg(handle, cmd->base.autoneg);
726+
if (ret)
727+
return ret;
728+
}
729+
730+
if (ops->cfg_mac_speed_dup_h)
731+
ret = ops->cfg_mac_speed_dup_h(handle, cmd->base.speed,
732+
cmd->base.duplex);
733+
734+
return ret;
674735
}
675736

676737
static u32 hns3_get_rss_key_size(struct net_device *netdev)
@@ -875,19 +936,36 @@ static int hns3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
875936

876937
static int hns3_nway_reset(struct net_device *netdev)
877938
{
939+
struct hnae3_handle *handle = hns3_get_handle(netdev);
940+
const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
878941
struct phy_device *phy = netdev->phydev;
942+
int autoneg;
879943

880944
if (!netif_running(netdev))
881945
return 0;
882946

883-
/* Only support nway_reset for netdev with phy attached for now */
884-
if (!phy)
947+
if (hns3_nic_resetting(netdev)) {
948+
netdev_err(netdev, "dev resetting!");
949+
return -EBUSY;
950+
}
951+
952+
if (!ops->get_autoneg || !ops->restart_autoneg)
885953
return -EOPNOTSUPP;
886954

887-
if (phy->autoneg != AUTONEG_ENABLE)
955+
autoneg = ops->get_autoneg(handle);
956+
if (autoneg != AUTONEG_ENABLE) {
957+
netdev_err(netdev,
958+
"Autoneg is off, don't support to restart it\n");
888959
return -EINVAL;
960+
}
961+
962+
if (phy)
963+
return genphy_restart_aneg(phy);
964+
965+
if (handle->pdev->revision == 0x20)
966+
return -EOPNOTSUPP;
889967

890-
return genphy_restart_aneg(phy);
968+
return ops->restart_autoneg(handle);
891969
}
892970

893971
static void hns3_get_channels(struct net_device *netdev,

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,48 @@ static int hclge_parse_speed(int speed_cmd, int *speed)
845845
return 0;
846846
}
847847

848+
static int hclge_check_port_speed(struct hnae3_handle *handle, u32 speed)
849+
{
850+
struct hclge_vport *vport = hclge_get_vport(handle);
851+
struct hclge_dev *hdev = vport->back;
852+
u32 speed_ability = hdev->hw.mac.speed_ability;
853+
u32 speed_bit = 0;
854+
855+
switch (speed) {
856+
case HCLGE_MAC_SPEED_10M:
857+
speed_bit = HCLGE_SUPPORT_10M_BIT;
858+
break;
859+
case HCLGE_MAC_SPEED_100M:
860+
speed_bit = HCLGE_SUPPORT_100M_BIT;
861+
break;
862+
case HCLGE_MAC_SPEED_1G:
863+
speed_bit = HCLGE_SUPPORT_1G_BIT;
864+
break;
865+
case HCLGE_MAC_SPEED_10G:
866+
speed_bit = HCLGE_SUPPORT_10G_BIT;
867+
break;
868+
case HCLGE_MAC_SPEED_25G:
869+
speed_bit = HCLGE_SUPPORT_25G_BIT;
870+
break;
871+
case HCLGE_MAC_SPEED_40G:
872+
speed_bit = HCLGE_SUPPORT_40G_BIT;
873+
break;
874+
case HCLGE_MAC_SPEED_50G:
875+
speed_bit = HCLGE_SUPPORT_50G_BIT;
876+
break;
877+
case HCLGE_MAC_SPEED_100G:
878+
speed_bit = HCLGE_SUPPORT_100G_BIT;
879+
break;
880+
default:
881+
return -EINVAL;
882+
}
883+
884+
if (speed_bit & speed_ability)
885+
return 0;
886+
887+
return -EINVAL;
888+
}
889+
848890
static void hclge_convert_setting_sr(struct hclge_mac *mac, u8 speed_ability)
849891
{
850892
if (speed_ability & HCLGE_SUPPORT_10G_BIT)
@@ -2198,6 +2240,16 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable)
21982240
struct hclge_vport *vport = hclge_get_vport(handle);
21992241
struct hclge_dev *hdev = vport->back;
22002242

2243+
if (!hdev->hw.mac.support_autoneg) {
2244+
if (enable) {
2245+
dev_err(&hdev->pdev->dev,
2246+
"autoneg is not supported by current port\n");
2247+
return -EOPNOTSUPP;
2248+
} else {
2249+
return 0;
2250+
}
2251+
}
2252+
22012253
return hclge_set_autoneg_en(hdev, enable);
22022254
}
22032255

@@ -2213,6 +2265,20 @@ static int hclge_get_autoneg(struct hnae3_handle *handle)
22132265
return hdev->hw.mac.autoneg;
22142266
}
22152267

2268+
static int hclge_restart_autoneg(struct hnae3_handle *handle)
2269+
{
2270+
struct hclge_vport *vport = hclge_get_vport(handle);
2271+
struct hclge_dev *hdev = vport->back;
2272+
int ret;
2273+
2274+
dev_dbg(&hdev->pdev->dev, "restart autoneg\n");
2275+
2276+
ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
2277+
if (ret)
2278+
return ret;
2279+
return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
2280+
}
2281+
22162282
static int hclge_mac_init(struct hclge_dev *hdev)
22172283
{
22182284
struct hclge_mac *mac = &hdev->hw.mac;
@@ -7613,13 +7679,13 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
76137679
if (!fc_autoneg)
76147680
return hclge_cfg_pauseparam(hdev, rx_en, tx_en);
76157681

7616-
/* Only support flow control negotiation for netdev with
7617-
* phy attached for now.
7618-
*/
7619-
if (!phydev)
7682+
if (phydev)
7683+
return phy_start_aneg(phydev);
7684+
7685+
if (hdev->pdev->revision == 0x20)
76207686
return -EOPNOTSUPP;
76217687

7622-
return phy_start_aneg(phydev);
7688+
return hclge_restart_autoneg(handle);
76237689
}
76247690

76257691
static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
@@ -8686,6 +8752,7 @@ static const struct hnae3_ae_ops hclge_ops = {
86868752
.get_ksettings_an_result = hclge_get_ksettings_an_result,
86878753
.cfg_mac_speed_dup_h = hclge_cfg_mac_speed_dup_h,
86888754
.get_media_type = hclge_get_media_type,
8755+
.check_port_speed = hclge_check_port_speed,
86898756
.get_rss_key_size = hclge_get_rss_key_size,
86908757
.get_rss_indir_size = hclge_get_rss_indir_size,
86918758
.get_rss = hclge_get_rss,
@@ -8702,6 +8769,7 @@ static const struct hnae3_ae_ops hclge_ops = {
87028769
.rm_mc_addr = hclge_rm_mc_addr,
87038770
.set_autoneg = hclge_set_autoneg,
87048771
.get_autoneg = hclge_get_autoneg,
8772+
.restart_autoneg = hclge_restart_autoneg,
87058773
.get_pauseparam = hclge_get_pauseparam,
87068774
.set_pauseparam = hclge_set_pauseparam,
87078775
.set_mtu = hclge_set_mtu,

0 commit comments

Comments
 (0)