From a714d679eaa6340e4297af169daaa78c6963e65b Mon Sep 17 00:00:00 2001 From: Yufeng Mo Date: Thu, 8 Aug 2019 21:53:41 +0800 Subject: [PATCH] net: hns3: add the function of setting VF status independently driver inclusion category: bugfix bugzilla: NA CVE: NA This patch adds the function of setting VF status independently. The options are auto, enable, and disable. Even if the PF is down, the communication between VFs will be normal if the VFs are set to enable. The commands are as follows: 'ip link set vf state ' set the vf status 'ip link show' view the setting status Feature or Bugfix:Bugfix Signed-off-by: Yufeng Mo Reviewed-by: lipeng Reviewed-by: Yunsheng Lin Reviewed-by: Yang Yingliang Signed-off-by: Yang Yingliang --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 4 +++ .../net/ethernet/hisilicon/hns3/hns3_enet.c | 24 +++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 36 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.h | 2 ++ .../hisilicon/hns3/hns3pf/hclge_mbx.c | 25 +++++++++++-- 5 files changed, 88 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 8fc488e6db01..3c65633b0971 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -533,6 +533,10 @@ struct hnae3_ae_ops { int (*priv_ops)(struct hnae3_handle *handle, int opcode, void *data, int length); #endif + int (*get_vf_config)(struct hnae3_handle *handle, int vf, + struct ifla_vf_info *ivf); + int (*set_vf_link_state)(struct hnae3_handle *handle, int vf, + int link_state); }; struct hnae3_dcb_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 109919747bdf..0cb10c793dff 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1881,6 +1881,28 @@ static int hns3_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, } #endif +static int hns3_nic_get_vf_config(struct net_device *ndev, int vf, + struct ifla_vf_info *ivf) +{ + struct hnae3_handle *h = hns3_get_handle(ndev); + + if (!h->ae_algo->ops->get_vf_config) + return -EOPNOTSUPP; + + return h->ae_algo->ops->get_vf_config(h, vf, ivf); +} + +static int hns3_nic_set_vf_link_state(struct net_device *ndev, int vf, + int link_state) +{ + struct hnae3_handle *h = hns3_get_handle(ndev); + + if (!h->ae_algo->ops->set_vf_link_state) + return -EOPNOTSUPP; + + return h->ae_algo->ops->set_vf_link_state(h, vf, link_state); +} + struct net_device_ops hns3_nic_netdev_ops = { .ndo_open = hns3_nic_net_open, .ndo_stop = hns3_nic_net_stop, @@ -1901,6 +1923,8 @@ struct net_device_ops hns3_nic_netdev_ops = { #ifdef CONFIG_RFS_ACCEL .ndo_rx_flow_steer = hns3_rx_flow_steer, #endif + .ndo_get_vf_config = hns3_nic_get_vf_config, + .ndo_set_vf_link_state = hns3_nic_set_vf_link_state, }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 0e3ebb701b24..29df4c784c0b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1612,6 +1612,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev) for (i = 0; i < num_vport; i++) { vport->back = hdev; vport->vport_id = i; + vport->link_state = IFLA_VF_LINK_STATE_AUTO; vport->mps = HCLGE_MAC_DEFAULT_FRAME; vport->port_base_vlan_cfg.state = HNAE3_PORT_BASE_VLAN_DISABLE; vport->rxvlan_cfg.rx_vlan_offload_en = true; @@ -2830,6 +2831,39 @@ static int hclge_get_status(struct hnae3_handle *handle) return hdev->hw.mac.link; } +static int hclge_get_vf_config(struct hnae3_handle *handle, int vf, + struct ifla_vf_info *ivf) +{ +#define HCLGE_VF_VPORT_START_NUM 1 + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + + if (vf < 0 || vf >= hdev->num_alloc_vport - HCLGE_VF_VPORT_START_NUM) + return -EINVAL; + + /* vf start from 1 in vport */ + vf += HCLGE_VF_VPORT_START_NUM; + ivf->vf = vf; + ivf->linkstate = hdev->vport[vf].link_state; + ether_addr_copy(ivf->mac, hdev->vport[vf].mac); + + return 0; +} + +static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf, + int link_state) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + + if (vf <= 0 || vf >= hdev->num_alloc_vport) + return -EINVAL; + + hdev->vport[vf].link_state = link_state; + + return 0; +} + static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) { u32 rst_src_reg; @@ -10185,6 +10219,8 @@ struct hnae3_ae_ops hclge_ops = { .restore_vlan_table = hclge_restore_vlan_table, .reset_done = hclge_reset_done, .handle_imp_error = hclge_handle_imp_error, + .get_vf_config = hclge_get_vf_config, + .set_vf_link_state = hclge_set_vf_link_state, }; struct hnae3_ae_algo ae_algo = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 335dc26322ab..01956f346a54 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -969,6 +969,8 @@ struct hclge_vport { unsigned long state; unsigned long last_active_jiffies; + int link_state; + u8 mac[ETH_ALEN]; int mps; /* Max packet size */ struct list_head uc_mac_list; /* Store VF unicast table */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index ce6ac9a38d5e..48441f1e9ad3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -260,17 +260,22 @@ static int hclge_set_vf_uc_mac_addr(struct hclge_vport *vport, false, HCLGE_MAC_ADDR_UC); hclge_add_vport_mac_table(vport, mac_addr, HCLGE_MAC_ADDR_UC); + ether_addr_copy(vport->mac, mac_addr); } } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_ADD) { status = hclge_add_uc_addr_common(vport, mac_addr); - if (!status) + if (!status) { hclge_add_vport_mac_table(vport, mac_addr, HCLGE_MAC_ADDR_UC); + ether_addr_copy(vport->mac, mac_addr); + } } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_REMOVE) { status = hclge_rm_uc_addr_common(vport, mac_addr); - if (!status) + if (!status) { hclge_rm_vport_mac_table(vport, mac_addr, false, HCLGE_MAC_ADDR_UC); + eth_zero_addr(vport->mac); + } } else { dev_err(&hdev->pdev->dev, "failed to set unicast mac addr, unknown subcode %d\n", @@ -455,6 +460,8 @@ static int hclge_get_vf_media_type(struct hclge_vport *vport, static int hclge_get_link_info(struct hclge_vport *vport, struct hclge_mbx_vf_to_pf_cmd *mbx_req) { +#define HCLGE_VF_LINK_STATE_UP 1U +#define HCLGE_VF_LINK_STATE_DOWN 0U struct hclge_dev *hdev = vport->back; u16 link_status; u8 msg_data[8]; @@ -462,7 +469,19 @@ static int hclge_get_link_info(struct hclge_vport *vport, u16 duplex; /* mac.link can only be 0 or 1 */ - link_status = (u16)hdev->hw.mac.link; + switch (vport->link_state) { + case IFLA_VF_LINK_STATE_ENABLE: + link_status = HCLGE_VF_LINK_STATE_UP; + break; + case IFLA_VF_LINK_STATE_DISABLE: + link_status = HCLGE_VF_LINK_STATE_DOWN; + break; + case IFLA_VF_LINK_STATE_AUTO: + default: + link_status = (u16)hdev->hw.mac.link; + break; + } + duplex = hdev->hw.mac.duplex; memcpy(&msg_data[0], &link_status, sizeof(u16)); memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32)); -- GitLab