Skip to content

Commit 3bda2e5

Browse files
Guangbin Huangdavem330
authored andcommitted
net: hns3: fix pause config problem after autoneg disabled
If a TP port is configured by follow steps: 1.ethtool -s ethx autoneg off speed 100 duplex full 2.ethtool -A ethx rx on tx on 3.ethtool -s ethx autoneg on(rx&tx negotiated pause results are off) 4.ethtool -s ethx autoneg off speed 100 duplex full In step 3, driver will set rx&tx pause parameters of hardware to off as pause parameters negotiated with link partner are off. After step 4, the "ethtool -a ethx" command shows both rx and tx pause parameters are on. However, pause parameters of hardware are still off and port has no flow control function actually. To fix this problem, if autoneg is disabled, driver uses its saved parameters to restore pause of hardware. If the speed is not changed in this case, there is no link state changed for phy, it will cause the pause parameter is not taken effect, so we need to force phy to go down and up. Fixes: aacbe27 ("net: hns3: modify how pause options is displayed") Signed-off-by: Guangbin Huang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 440ffcd commit 3bda2e5

File tree

5 files changed

+57
-10
lines changed

5 files changed

+57
-10
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ struct hnae3_ae_ops {
568568
u32 *auto_neg, u32 *rx_en, u32 *tx_en);
569569
int (*set_pauseparam)(struct hnae3_handle *handle,
570570
u32 auto_neg, u32 rx_en, u32 tx_en);
571+
int (*restore_pauseparam)(struct hnae3_handle *handle);
571572

572573
int (*set_autoneg)(struct hnae3_handle *handle, bool enable);
573574
int (*get_autoneg)(struct hnae3_handle *handle);

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

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,26 @@ static int hns3_check_ksettings_param(const struct net_device *netdev,
824824
return 0;
825825
}
826826

827+
static int hns3_set_phy_link_ksettings(struct net_device *netdev,
828+
const struct ethtool_link_ksettings *cmd)
829+
{
830+
struct hnae3_handle *handle = hns3_get_handle(netdev);
831+
const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
832+
int ret;
833+
834+
if (cmd->base.speed == SPEED_1000 &&
835+
cmd->base.autoneg == AUTONEG_DISABLE)
836+
return -EINVAL;
837+
838+
if (cmd->base.autoneg == AUTONEG_DISABLE && ops->restore_pauseparam) {
839+
ret = ops->restore_pauseparam(handle);
840+
if (ret)
841+
return ret;
842+
}
843+
844+
return phy_ethtool_ksettings_set(netdev->phydev, cmd);
845+
}
846+
827847
static int hns3_set_link_ksettings(struct net_device *netdev,
828848
const struct ethtool_link_ksettings *cmd)
829849
{
@@ -842,16 +862,11 @@ static int hns3_set_link_ksettings(struct net_device *netdev,
842862
cmd->base.autoneg, cmd->base.speed, cmd->base.duplex);
843863

844864
/* Only support ksettings_set for netdev with phy attached for now */
845-
if (netdev->phydev) {
846-
if (cmd->base.speed == SPEED_1000 &&
847-
cmd->base.autoneg == AUTONEG_DISABLE)
848-
return -EINVAL;
849-
850-
return phy_ethtool_ksettings_set(netdev->phydev, cmd);
851-
} else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
852-
ops->set_phy_link_ksettings) {
865+
if (netdev->phydev)
866+
return hns3_set_phy_link_ksettings(netdev, cmd);
867+
else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
868+
ops->set_phy_link_ksettings)
853869
return ops->set_phy_link_ksettings(handle, cmd);
854-
}
855870

856871
if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
857872
return -EOPNOTSUPP;

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11021,6 +11021,35 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
1102111021
return -EOPNOTSUPP;
1102211022
}
1102311023

11024+
static int hclge_restore_pauseparam(struct hnae3_handle *handle)
11025+
{
11026+
struct hclge_vport *vport = hclge_get_vport(handle);
11027+
struct hclge_dev *hdev = vport->back;
11028+
u32 auto_neg, rx_pause, tx_pause;
11029+
int ret;
11030+
11031+
hclge_get_pauseparam(handle, &auto_neg, &rx_pause, &tx_pause);
11032+
/* when autoneg is disabled, the pause setting of phy has no effect
11033+
* unless the link goes down.
11034+
*/
11035+
ret = phy_suspend(hdev->hw.mac.phydev);
11036+
if (ret)
11037+
return ret;
11038+
11039+
phy_set_asym_pause(hdev->hw.mac.phydev, rx_pause, tx_pause);
11040+
11041+
ret = phy_resume(hdev->hw.mac.phydev);
11042+
if (ret)
11043+
return ret;
11044+
11045+
ret = hclge_mac_pause_setup_hw(hdev);
11046+
if (ret)
11047+
dev_err(&hdev->pdev->dev,
11048+
"restore pauseparam error, ret = %d.\n", ret);
11049+
11050+
return ret;
11051+
}
11052+
1102411053
static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
1102511054
u8 *auto_neg, u32 *speed, u8 *duplex)
1102611055
{
@@ -12984,6 +13013,7 @@ static const struct hnae3_ae_ops hclge_ops = {
1298413013
.halt_autoneg = hclge_halt_autoneg,
1298513014
.get_pauseparam = hclge_get_pauseparam,
1298613015
.set_pauseparam = hclge_set_pauseparam,
13016+
.restore_pauseparam = hclge_restore_pauseparam,
1298713017
.set_mtu = hclge_set_mtu,
1298813018
.reset_queue = hclge_reset_tqp,
1298913019
.get_stats = hclge_get_stats,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1435,7 +1435,7 @@ static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc)
14351435
return 0;
14361436
}
14371437

1438-
static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
1438+
int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
14391439
{
14401440
bool tx_en, rx_en;
14411441

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ int hclge_tm_get_pri_weight(struct hclge_dev *hdev, u8 pri_id, u8 *weight);
244244
int hclge_tm_get_pri_shaper(struct hclge_dev *hdev, u8 pri_id,
245245
enum hclge_opcode_type cmd,
246246
struct hclge_tm_shaper_para *para);
247+
int hclge_mac_pause_setup_hw(struct hclge_dev *hdev);
247248
int hclge_tm_get_q_to_qs_map(struct hclge_dev *hdev, u16 q_id, u16 *qset_id);
248249
int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id);
249250
int hclge_tm_get_pg_to_pri_map(struct hclge_dev *hdev, u8 pg_id,

0 commit comments

Comments
 (0)