Skip to content

Commit ea25622

Browse files
Luo bindavem330
authored andcommitted
hinic: add support to set and get pause params
add support to set pause params with ethtool -A and get pause params with ethtool -a. Also remove set_link_ksettings ops for VF and enable pause by default. Signed-off-by: Luo bin <luobin9@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 491f14d commit ea25622

File tree

7 files changed

+217
-11
lines changed

7 files changed

+217
-11
lines changed

drivers/net/ethernet/huawei/hinic/hinic_ethtool.c

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,64 @@ static int hinic_set_ringparam(struct net_device *netdev,
613613

614614
return 0;
615615
}
616+
617+
static void hinic_get_pauseparam(struct net_device *netdev,
618+
struct ethtool_pauseparam *pause)
619+
{
620+
struct hinic_dev *nic_dev = netdev_priv(netdev);
621+
struct hinic_pause_config pause_info = {0};
622+
struct hinic_nic_cfg *nic_cfg;
623+
int err;
624+
625+
nic_cfg = &nic_dev->hwdev->func_to_io.nic_cfg;
626+
627+
err = hinic_get_hw_pause_info(nic_dev->hwdev, &pause_info);
628+
if (!err) {
629+
pause->autoneg = pause_info.auto_neg;
630+
if (nic_cfg->pause_set || !pause_info.auto_neg) {
631+
pause->rx_pause = nic_cfg->rx_pause;
632+
pause->tx_pause = nic_cfg->tx_pause;
633+
} else {
634+
pause->rx_pause = pause_info.rx_pause;
635+
pause->tx_pause = pause_info.tx_pause;
636+
}
637+
}
638+
}
639+
640+
static int hinic_set_pauseparam(struct net_device *netdev,
641+
struct ethtool_pauseparam *pause)
642+
{
643+
struct hinic_dev *nic_dev = netdev_priv(netdev);
644+
struct hinic_pause_config pause_info = {0};
645+
struct hinic_port_cap port_cap = {0};
646+
int err;
647+
648+
err = hinic_port_get_cap(nic_dev, &port_cap);
649+
if (err)
650+
return -EIO;
651+
652+
if (pause->autoneg != port_cap.autoneg_state)
653+
return -EOPNOTSUPP;
654+
655+
pause_info.auto_neg = pause->autoneg;
656+
pause_info.rx_pause = pause->rx_pause;
657+
pause_info.tx_pause = pause->tx_pause;
658+
659+
mutex_lock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
660+
err = hinic_set_hw_pause_info(nic_dev->hwdev, &pause_info);
661+
if (err) {
662+
mutex_unlock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
663+
return err;
664+
}
665+
nic_dev->hwdev->func_to_io.nic_cfg.pause_set = true;
666+
nic_dev->hwdev->func_to_io.nic_cfg.auto_neg = pause->autoneg;
667+
nic_dev->hwdev->func_to_io.nic_cfg.rx_pause = pause->rx_pause;
668+
nic_dev->hwdev->func_to_io.nic_cfg.tx_pause = pause->tx_pause;
669+
mutex_unlock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
670+
671+
return 0;
672+
}
673+
616674
static void hinic_get_channels(struct net_device *netdev,
617675
struct ethtool_channels *channels)
618676
{
@@ -1241,6 +1299,27 @@ static const struct ethtool_ops hinic_ethtool_ops = {
12411299
.get_link = ethtool_op_get_link,
12421300
.get_ringparam = hinic_get_ringparam,
12431301
.set_ringparam = hinic_set_ringparam,
1302+
.get_pauseparam = hinic_get_pauseparam,
1303+
.set_pauseparam = hinic_set_pauseparam,
1304+
.get_channels = hinic_get_channels,
1305+
.set_channels = hinic_set_channels,
1306+
.get_rxnfc = hinic_get_rxnfc,
1307+
.set_rxnfc = hinic_set_rxnfc,
1308+
.get_rxfh_key_size = hinic_get_rxfh_key_size,
1309+
.get_rxfh_indir_size = hinic_get_rxfh_indir_size,
1310+
.get_rxfh = hinic_get_rxfh,
1311+
.set_rxfh = hinic_set_rxfh,
1312+
.get_sset_count = hinic_get_sset_count,
1313+
.get_ethtool_stats = hinic_get_ethtool_stats,
1314+
.get_strings = hinic_get_strings,
1315+
};
1316+
1317+
static const struct ethtool_ops hinicvf_ethtool_ops = {
1318+
.get_link_ksettings = hinic_get_link_ksettings,
1319+
.get_drvinfo = hinic_get_drvinfo,
1320+
.get_link = ethtool_op_get_link,
1321+
.get_ringparam = hinic_get_ringparam,
1322+
.set_ringparam = hinic_set_ringparam,
12441323
.get_channels = hinic_get_channels,
12451324
.set_channels = hinic_set_channels,
12461325
.get_rxnfc = hinic_get_rxnfc,
@@ -1256,5 +1335,10 @@ static const struct ethtool_ops hinic_ethtool_ops = {
12561335

12571336
void hinic_set_ethtool_ops(struct net_device *netdev)
12581337
{
1259-
netdev->ethtool_ops = &hinic_ethtool_ops;
1338+
struct hinic_dev *nic_dev = netdev_priv(netdev);
1339+
1340+
if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
1341+
netdev->ethtool_ops = &hinic_ethtool_ops;
1342+
else
1343+
netdev->ethtool_ops = &hinicvf_ethtool_ops;
12601344
}

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,8 @@ struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
777777
goto err_dev_cap;
778778
}
779779

780+
mutex_init(&hwdev->func_to_io.nic_cfg.cfg_mutex);
781+
780782
err = hinic_vf_func_init(hwdev);
781783
if (err) {
782784
dev_err(&pdev->dev, "Failed to init nic mbox\n");

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ enum hinic_port_cmd {
4848
HINIC_PORT_CMD_ADD_VLAN = 3,
4949
HINIC_PORT_CMD_DEL_VLAN = 4,
5050

51+
HINIC_PORT_CMD_SET_PFC = 5,
52+
5153
HINIC_PORT_CMD_SET_MAC = 9,
5254
HINIC_PORT_CMD_GET_MAC = 10,
5355
HINIC_PORT_CMD_DEL_MAC = 11,

drivers/net/ethernet/huawei/hinic/hinic_hw_io.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ struct hinic_free_db_area {
4747
struct semaphore idx_lock;
4848
};
4949

50+
struct hinic_nic_cfg {
51+
/* lock for getting nic cfg */
52+
struct mutex cfg_mutex;
53+
bool pause_set;
54+
u32 auto_neg;
55+
u32 rx_pause;
56+
u32 tx_pause;
57+
};
58+
5059
struct hinic_func_to_io {
5160
struct hinic_hwif *hwif;
5261
struct hinic_hwdev *hwdev;
@@ -78,6 +87,7 @@ struct hinic_func_to_io {
7887
u16 max_vfs;
7988
struct vf_data_storage *vf_infos;
8089
u8 link_status;
90+
struct hinic_nic_cfg nic_cfg;
8191
};
8292

8393
struct hinic_wq_page_size {

drivers/net/ethernet/huawei/hinic/hinic_main.c

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,26 @@ static void netdev_features_init(struct net_device *netdev)
887887
netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
888888
}
889889

890+
static void hinic_refresh_nic_cfg(struct hinic_dev *nic_dev)
891+
{
892+
struct hinic_nic_cfg *nic_cfg = &nic_dev->hwdev->func_to_io.nic_cfg;
893+
struct hinic_pause_config pause_info = {0};
894+
struct hinic_port_cap port_cap = {0};
895+
896+
if (hinic_port_get_cap(nic_dev, &port_cap))
897+
return;
898+
899+
mutex_lock(&nic_cfg->cfg_mutex);
900+
if (nic_cfg->pause_set || !port_cap.autoneg_state) {
901+
nic_cfg->auto_neg = port_cap.autoneg_state;
902+
pause_info.auto_neg = nic_cfg->auto_neg;
903+
pause_info.rx_pause = nic_cfg->rx_pause;
904+
pause_info.tx_pause = nic_cfg->tx_pause;
905+
hinic_set_hw_pause_info(nic_dev->hwdev, &pause_info);
906+
}
907+
mutex_unlock(&nic_cfg->cfg_mutex);
908+
}
909+
890910
/**
891911
* link_status_event_handler - link event handler
892912
* @handle: nic device for the handler
@@ -918,6 +938,9 @@ static void link_status_event_handler(void *handle, void *buf_in, u16 in_size,
918938

919939
up(&nic_dev->mgmt_lock);
920940

941+
if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
942+
hinic_refresh_nic_cfg(nic_dev);
943+
921944
netif_info(nic_dev, drv, nic_dev->netdev, "HINIC_Link is UP\n");
922945
} else {
923946
down(&nic_dev->mgmt_lock);
@@ -948,28 +971,54 @@ static int set_features(struct hinic_dev *nic_dev,
948971
{
949972
netdev_features_t changed = force_change ? ~0 : pre_features ^ features;
950973
u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
974+
netdev_features_t failed_features = 0;
975+
int ret = 0;
951976
int err = 0;
952977

953-
if (changed & NETIF_F_TSO)
954-
err = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
978+
if (changed & NETIF_F_TSO) {
979+
ret = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
955980
HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);
981+
if (ret) {
982+
err = ret;
983+
failed_features |= NETIF_F_TSO;
984+
}
985+
}
956986

957-
if (changed & NETIF_F_RXCSUM)
958-
err = hinic_set_rx_csum_offload(nic_dev, csum_en);
987+
if (changed & NETIF_F_RXCSUM) {
988+
ret = hinic_set_rx_csum_offload(nic_dev, csum_en);
989+
if (ret) {
990+
err = ret;
991+
failed_features |= NETIF_F_RXCSUM;
992+
}
993+
}
959994

960995
if (changed & NETIF_F_LRO) {
961-
err = hinic_set_rx_lro_state(nic_dev,
996+
ret = hinic_set_rx_lro_state(nic_dev,
962997
!!(features & NETIF_F_LRO),
963998
HINIC_LRO_RX_TIMER_DEFAULT,
964999
HINIC_LRO_MAX_WQE_NUM_DEFAULT);
1000+
if (ret) {
1001+
err = ret;
1002+
failed_features |= NETIF_F_LRO;
1003+
}
9651004
}
9661005

967-
if (changed & NETIF_F_HW_VLAN_CTAG_RX)
968-
err = hinic_set_rx_vlan_offload(nic_dev,
1006+
if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
1007+
ret = hinic_set_rx_vlan_offload(nic_dev,
9691008
!!(features &
9701009
NETIF_F_HW_VLAN_CTAG_RX));
1010+
if (ret) {
1011+
err = ret;
1012+
failed_features |= NETIF_F_HW_VLAN_CTAG_RX;
1013+
}
1014+
}
9711015

972-
return err;
1016+
if (err) {
1017+
nic_dev->netdev->features = features ^ failed_features;
1018+
return -EIO;
1019+
}
1020+
1021+
return 0;
9731022
}
9741023

9751024
/**
@@ -1008,8 +1057,6 @@ static int nic_dev_init(struct pci_dev *pdev)
10081057
goto err_alloc_etherdev;
10091058
}
10101059

1011-
hinic_set_ethtool_ops(netdev);
1012-
10131060
if (!HINIC_IS_VF(hwdev->hwif))
10141061
netdev->netdev_ops = &hinic_netdev_ops;
10151062
else
@@ -1032,6 +1079,8 @@ static int nic_dev_init(struct pci_dev *pdev)
10321079
nic_dev->sriov_info.pdev = pdev;
10331080
nic_dev->max_qps = num_qps;
10341081

1082+
hinic_set_ethtool_ops(netdev);
1083+
10351084
sema_init(&nic_dev->mgmt_lock, 1);
10361085

10371086
tx_stats = &nic_dev->tx_stats;
@@ -1100,6 +1149,11 @@ static int nic_dev_init(struct pci_dev *pdev)
11001149
if (err)
11011150
goto err_set_features;
11021151

1152+
/* enable pause and disable pfc by default */
1153+
err = hinic_dcb_set_pfc(nic_dev->hwdev, 0, 0);
1154+
if (err)
1155+
goto err_set_pfc;
1156+
11031157
SET_NETDEV_DEV(netdev, &pdev->dev);
11041158

11051159
err = register_netdev(netdev);
@@ -1111,6 +1165,7 @@ static int nic_dev_init(struct pci_dev *pdev)
11111165
return 0;
11121166

11131167
err_reg_netdev:
1168+
err_set_pfc:
11141169
err_set_features:
11151170
hinic_hwdev_cb_unregister(nic_dev->hwdev,
11161171
HINIC_MGMT_MSG_CMD_LINK_STATUS);

drivers/net/ethernet/huawei/hinic/hinic_port.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,7 @@ int hinic_get_link_mode(struct hinic_hwdev *hwdev,
10821082
if (!hwdev || !link_mode)
10831083
return -EINVAL;
10841084

1085+
link_mode->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
10851086
out_size = sizeof(*link_mode);
10861087

10871088
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
@@ -1172,6 +1173,8 @@ int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,
11721173
u16 out_size = sizeof(*pause_info);
11731174
int err;
11741175

1176+
pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1177+
11751178
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,
11761179
pause_info, sizeof(*pause_info),
11771180
pause_info, &out_size);
@@ -1190,6 +1193,8 @@ int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
11901193
u16 out_size = sizeof(*pause_info);
11911194
int err;
11921195

1196+
pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1197+
11931198
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
11941199
pause_info, sizeof(*pause_info),
11951200
pause_info, &out_size);
@@ -1201,3 +1206,38 @@ int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
12011206

12021207
return 0;
12031208
}
1209+
1210+
int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap)
1211+
{
1212+
struct hinic_nic_cfg *nic_cfg = &hwdev->func_to_io.nic_cfg;
1213+
struct hinic_set_pfc pfc = {0};
1214+
u16 out_size = sizeof(pfc);
1215+
int err;
1216+
1217+
if (HINIC_IS_VF(hwdev->hwif))
1218+
return 0;
1219+
1220+
mutex_lock(&nic_cfg->cfg_mutex);
1221+
1222+
pfc.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1223+
pfc.pfc_bitmap = pfc_bitmap;
1224+
pfc.pfc_en = pfc_en;
1225+
1226+
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PFC,
1227+
&pfc, sizeof(pfc), &pfc, &out_size);
1228+
if (err || pfc.status || !out_size) {
1229+
dev_err(&hwdev->hwif->pdev->dev, "Failed to %s pfc, err: %d, status: 0x%x, out size: 0x%x\n",
1230+
pfc_en ? "enable" : "disable", err, pfc.status,
1231+
out_size);
1232+
mutex_unlock(&nic_cfg->cfg_mutex);
1233+
return -EIO;
1234+
}
1235+
1236+
/* pause settings is opposite from pfc */
1237+
nic_cfg->rx_pause = pfc_en ? 0 : 1;
1238+
nic_cfg->tx_pause = pfc_en ? 0 : 1;
1239+
1240+
mutex_unlock(&nic_cfg->cfg_mutex);
1241+
1242+
return 0;
1243+
}

drivers/net/ethernet/huawei/hinic/hinic_port.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,17 @@ struct hinic_pause_config {
641641
u32 tx_pause;
642642
};
643643

644+
struct hinic_set_pfc {
645+
u8 status;
646+
u8 version;
647+
u8 rsvd0[6];
648+
649+
u16 func_id;
650+
u8 pfc_en;
651+
u8 pfc_bitmap;
652+
u8 rsvd1[4];
653+
};
654+
644655
int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
645656
u16 vlan_id);
646657

@@ -736,6 +747,8 @@ int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,
736747
int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
737748
struct hinic_pause_config *pause_info);
738749

750+
int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap);
751+
739752
int hinic_open(struct net_device *netdev);
740753

741754
int hinic_close(struct net_device *netdev);

0 commit comments

Comments
 (0)