Commit 61387774 authored by Peng Li's avatar Peng Li Committed by David S. Miller

net: hns3: add support for set_pauseparam

This patch adds set_pauseparam support for ethtool cmd.
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarFuyun Liang <liangfuyun1@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 27b5bf49
...@@ -559,6 +559,18 @@ static void hns3_get_pauseparam(struct net_device *netdev, ...@@ -559,6 +559,18 @@ static void hns3_get_pauseparam(struct net_device *netdev,
&param->rx_pause, &param->tx_pause); &param->rx_pause, &param->tx_pause);
} }
static int hns3_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *param)
{
struct hnae3_handle *h = hns3_get_handle(netdev);
if (h->ae_algo->ops->set_pauseparam)
return h->ae_algo->ops->set_pauseparam(h, param->autoneg,
param->rx_pause,
param->tx_pause);
return -EOPNOTSUPP;
}
static int hns3_get_link_ksettings(struct net_device *netdev, static int hns3_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd) struct ethtool_link_ksettings *cmd)
{ {
...@@ -880,6 +892,7 @@ static const struct ethtool_ops hns3_ethtool_ops = { ...@@ -880,6 +892,7 @@ static const struct ethtool_ops hns3_ethtool_ops = {
.get_ringparam = hns3_get_ringparam, .get_ringparam = hns3_get_ringparam,
.set_ringparam = hns3_set_ringparam, .set_ringparam = hns3_set_ringparam,
.get_pauseparam = hns3_get_pauseparam, .get_pauseparam = hns3_get_pauseparam,
.set_pauseparam = hns3_set_pauseparam,
.get_strings = hns3_get_strings, .get_strings = hns3_get_strings,
.get_ethtool_stats = hns3_get_stats, .get_ethtool_stats = hns3_get_stats,
.get_sset_count = hns3_get_sset_count, .get_sset_count = hns3_get_sset_count,
......
...@@ -4660,6 +4660,53 @@ static u32 hclge_get_fw_version(struct hnae3_handle *handle) ...@@ -4660,6 +4660,53 @@ static u32 hclge_get_fw_version(struct hnae3_handle *handle)
return hdev->fw_version; return hdev->fw_version;
} }
static void hclge_set_flowctrl_adv(struct hclge_dev *hdev, u32 rx_en, u32 tx_en)
{
struct phy_device *phydev = hdev->hw.mac.phydev;
if (!phydev)
return;
phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
if (rx_en)
phydev->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
if (tx_en)
phydev->advertising ^= ADVERTISED_Asym_Pause;
}
static int hclge_cfg_pauseparam(struct hclge_dev *hdev, u32 rx_en, u32 tx_en)
{
enum hclge_fc_mode fc_mode;
int ret;
if (rx_en && tx_en)
fc_mode = HCLGE_FC_FULL;
else if (rx_en && !tx_en)
fc_mode = HCLGE_FC_RX_PAUSE;
else if (!rx_en && tx_en)
fc_mode = HCLGE_FC_TX_PAUSE;
else
fc_mode = HCLGE_FC_NONE;
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) {
hdev->fc_mode_last_time = fc_mode;
return 0;
}
ret = hclge_mac_pause_en_cfg(hdev, tx_en, rx_en);
if (ret) {
dev_err(&hdev->pdev->dev, "configure pauseparam error, ret = %d.\n",
ret);
return ret;
}
hdev->tm_info.fc_mode = fc_mode;
return 0;
}
static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg, static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg,
u32 *rx_en, u32 *tx_en) u32 *rx_en, u32 *tx_en)
{ {
...@@ -4689,6 +4736,41 @@ static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg, ...@@ -4689,6 +4736,41 @@ static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg,
} }
} }
static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
u32 rx_en, u32 tx_en)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct phy_device *phydev = hdev->hw.mac.phydev;
u32 fc_autoneg;
/* Only support flow control negotiation for netdev with
* phy attached for now.
*/
if (!phydev)
return -EOPNOTSUPP;
fc_autoneg = hclge_get_autoneg(handle);
if (auto_neg != fc_autoneg) {
dev_info(&hdev->pdev->dev,
"To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
return -EOPNOTSUPP;
}
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) {
dev_info(&hdev->pdev->dev,
"Priority flow control enabled. Cannot set link flow control.\n");
return -EOPNOTSUPP;
}
hclge_set_flowctrl_adv(hdev, rx_en, tx_en);
if (!fc_autoneg)
return hclge_cfg_pauseparam(hdev, rx_en, tx_en);
return phy_start_aneg(phydev);
}
static void hclge_get_ksettings_an_result(struct hnae3_handle *handle, static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
u8 *auto_neg, u32 *speed, u8 *duplex) u8 *auto_neg, u32 *speed, u8 *duplex)
{ {
...@@ -5344,6 +5426,7 @@ static const struct hnae3_ae_ops hclge_ops = { ...@@ -5344,6 +5426,7 @@ static const struct hnae3_ae_ops hclge_ops = {
.set_autoneg = hclge_set_autoneg, .set_autoneg = hclge_set_autoneg,
.get_autoneg = hclge_get_autoneg, .get_autoneg = hclge_get_autoneg,
.get_pauseparam = hclge_get_pauseparam, .get_pauseparam = hclge_get_pauseparam,
.set_pauseparam = hclge_set_pauseparam,
.set_mtu = hclge_set_mtu, .set_mtu = hclge_set_mtu,
.reset_queue = hclge_reset_tqp, .reset_queue = hclge_reset_tqp,
.get_stats = hclge_get_stats, .get_stats = hclge_get_stats,
......
...@@ -112,7 +112,7 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level, ...@@ -112,7 +112,7 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
return 0; return 0;
} }
static int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx) int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
{ {
struct hclge_desc desc; struct hclge_desc desc;
......
...@@ -118,4 +118,5 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc); ...@@ -118,4 +118,5 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
int hclge_tm_dwrr_cfg(struct hclge_dev *hdev); int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
int hclge_tm_map_cfg(struct hclge_dev *hdev); int hclge_tm_map_cfg(struct hclge_dev *hdev);
int hclge_tm_init_hw(struct hclge_dev *hdev); int hclge_tm_init_hw(struct hclge_dev *hdev);
int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment