diff options
author | David S. Miller <davem@davemloft.net> | 2018-08-14 09:54:24 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-08-14 09:54:24 -0700 |
commit | ac272a3e9c0838a2cbc76327e29788dc2af49abe (patch) | |
tree | 7fe838f9eef3a3b0a3c1aea32c3af296d914d112 | |
parent | 1bbf3aed25e0fc256e825da1f5c45d7b4daa828e (diff) | |
parent | 3e85af6a6812d2d4778c3b19f17384c2a9f73200 (diff) | |
download | linux-ac272a3e9c0838a2cbc76327e29788dc2af49abe.tar.bz2 |
Merge branch 'hns3-next'
Salil Mehta says:
====================
Misc bug fixes & small enhancements for HNS3 Driver
This patch-set presents some bug fixes and minor enhancements to
HNS3 Ethernet driver.
Rework Summary:
(*) Patch V1->V2
1. Fixed David S Miller's comments
2. Dropped patch 0005 "net: hns3: Fix for vf vlan delete failed problem" for now.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
7 files changed, 165 insertions, 28 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a64d69c87f13..3554dca7a680 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1673,6 +1673,9 @@ static struct pci_driver hns3_driver = { /* set default feature to hns3 */ static void hns3_set_default_feature(struct net_device *netdev) { + struct hnae3_handle *h = hns3_get_handle(netdev); + struct pci_dev *pdev = h->pdev; + netdev->priv_flags |= IFF_UNICAST_FLT; netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | @@ -1706,6 +1709,9 @@ static void hns3_set_default_feature(struct net_device *netdev) NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; + + if (pdev->revision != 0x20) + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; } static int hns3_alloc_buffer(struct hns3_enet_ring *ring, @@ -2969,13 +2975,33 @@ static void hns3_init_ring_hw(struct hns3_enet_ring *ring) hns3_write_dev(q, HNS3_RING_TX_RING_BASEADDR_H_REG, (u32)((dma >> 31) >> 1)); - hns3_write_dev(q, HNS3_RING_TX_RING_BD_LEN_REG, - hns3_buf_size2type(ring->buf_size)); hns3_write_dev(q, HNS3_RING_TX_RING_BD_NUM_REG, ring->desc_num / 8 - 1); } } +static void hns3_init_tx_ring_tc(struct hns3_nic_priv *priv) +{ + struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo; + int i; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + struct hnae3_tc_info *tc_info = &kinfo->tc_info[i]; + int j; + + if (!tc_info->enable) + continue; + + for (j = 0; j < tc_info->tqp_count; j++) { + struct hnae3_queue *q; + + q = priv->ring_data[tc_info->tqp_offset + j].ring->tqp; + hns3_write_dev(q, HNS3_RING_TX_RING_TC_REG, + tc_info->tc); + } + } +} + int hns3_init_all_ring(struct hns3_nic_priv *priv) { struct hnae3_handle *h = priv->ae_handle; @@ -3387,6 +3413,8 @@ int hns3_nic_reset_all_ring(struct hnae3_handle *h) rx_ring->next_to_use = 0; } + hns3_init_tx_ring_tc(priv); + return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index e4b4a8f2ceaa..a02a96aee2a2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -37,7 +37,7 @@ enum hns3_nic_state { #define HNS3_RING_TX_RING_BASEADDR_L_REG 0x00040 #define HNS3_RING_TX_RING_BASEADDR_H_REG 0x00044 #define HNS3_RING_TX_RING_BD_NUM_REG 0x00048 -#define HNS3_RING_TX_RING_BD_LEN_REG 0x0004C +#define HNS3_RING_TX_RING_TC_REG 0x00050 #define HNS3_RING_TX_RING_TAIL_REG 0x00058 #define HNS3_RING_TX_RING_HEAD_REG 0x0005C #define HNS3_RING_TX_RING_FBDNUM_REG 0x00060 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 80ba95d76260..f70ee6910ee2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -53,7 +53,7 @@ static const struct hns3_stats hns3_rxq_stats[] = { #define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT) -#define HNS3_SELF_TEST_TPYE_NUM 1 +#define HNS3_SELF_TEST_TYPE_NUM 2 #define HNS3_NIC_LB_TEST_PKT_NUM 1 #define HNS3_NIC_LB_TEST_RING_ID 0 #define HNS3_NIC_LB_TEST_PACKET_SIZE 128 @@ -78,6 +78,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) return -EOPNOTSUPP; switch (loop) { + case HNAE3_MAC_INTER_LOOP_SERDES: case HNAE3_MAC_INTER_LOOP_MAC: ret = h->ae_algo->ops->set_loopback(h, loop, en); break; @@ -287,7 +288,7 @@ static void hns3_self_test(struct net_device *ndev, { struct hns3_nic_priv *priv = netdev_priv(ndev); struct hnae3_handle *h = priv->ae_handle; - int st_param[HNS3_SELF_TEST_TPYE_NUM][2]; + int st_param[HNS3_SELF_TEST_TYPE_NUM][2]; bool if_running = netif_running(ndev); #if IS_ENABLED(CONFIG_VLAN_8021Q) bool dis_vlan_filter; @@ -303,6 +304,10 @@ static void hns3_self_test(struct net_device *ndev, st_param[HNAE3_MAC_INTER_LOOP_MAC][1] = h->flags & HNAE3_SUPPORT_MAC_LOOPBACK; + st_param[HNAE3_MAC_INTER_LOOP_SERDES][0] = HNAE3_MAC_INTER_LOOP_SERDES; + st_param[HNAE3_MAC_INTER_LOOP_SERDES][1] = + h->flags & HNAE3_SUPPORT_SERDES_LOOPBACK; + if (if_running) dev_close(ndev); @@ -316,7 +321,7 @@ static void hns3_self_test(struct net_device *ndev, set_bit(HNS3_NIC_STATE_TESTING, &priv->state); - for (i = 0; i < HNS3_SELF_TEST_TPYE_NUM; i++) { + for (i = 0; i < HNS3_SELF_TEST_TYPE_NUM; i++) { enum hnae3_loop loop_type = (enum hnae3_loop)st_param[i][0]; if (!st_param[i][1]) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index cd0a4f228470..821d4c2f84bd 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -94,6 +94,7 @@ enum hclge_opcode_type { HCLGE_OPC_QUERY_LINK_STATUS = 0x0307, HCLGE_OPC_CONFIG_MAX_FRM_SIZE = 0x0308, HCLGE_OPC_CONFIG_SPEED_DUP = 0x0309, + HCLGE_OPC_SERDES_LOOPBACK = 0x0315, /* PFC/Pause commands */ HCLGE_OPC_CFG_MAC_PAUSE_EN = 0x0701, @@ -775,6 +776,17 @@ struct hclge_reset_cmd { u8 fun_reset_vfid; u8 rsv[22]; }; + +#define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0) +#define HCLGE_CMD_SERDES_DONE_B BIT(0) +#define HCLGE_CMD_SERDES_SUCCESS_B BIT(1) +struct hclge_serdes_lb_cmd { + u8 mask; + u8 enable; + u8 result; + u8 rsv[21]; +}; + #define HCLGE_DEFAULT_TX_BUF 0x4000 /* 16k bytes */ #define HCLGE_TOTAL_PKT_BUF 0x108000 /* 1.03125M bytes */ #define HCLGE_DEFAULT_DV 0xA000 /* 40k byte */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index fc813b7f20e8..8577dfc799ad 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -787,9 +787,10 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) hdev->hw.mac.speed == HCLGE_MAC_SPEED_1G) { count += 1; handle->flags |= HNAE3_SUPPORT_MAC_LOOPBACK; - } else { - count = -EOPNOTSUPP; } + + count++; + handle->flags |= HNAE3_SUPPORT_SERDES_LOOPBACK; } else if (stringset == ETH_SS_STATS) { count = ARRAY_SIZE(g_mac_stats_string) + ARRAY_SIZE(g_all_32bit_stats_string) + @@ -1266,35 +1267,37 @@ static int hclge_map_tqps_to_func(struct hclge_dev *hdev, u16 func_id, return ret; } -static int hclge_assign_tqp(struct hclge_vport *vport, - struct hnae3_queue **tqp, u16 num_tqps) +static int hclge_assign_tqp(struct hclge_vport *vport) { + struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hclge_dev *hdev = vport->back; int i, alloced; for (i = 0, alloced = 0; i < hdev->num_tqps && - alloced < num_tqps; i++) { + alloced < kinfo->num_tqps; i++) { if (!hdev->htqp[i].alloced) { hdev->htqp[i].q.handle = &vport->nic; hdev->htqp[i].q.tqp_index = alloced; - tqp[alloced] = &hdev->htqp[i].q; + hdev->htqp[i].q.desc_num = kinfo->num_desc; + kinfo->tqp[alloced] = &hdev->htqp[i].q; hdev->htqp[i].alloced = true; alloced++; } } - vport->alloc_tqps = num_tqps; + vport->alloc_tqps = kinfo->num_tqps; return 0; } -static int hclge_knic_setup(struct hclge_vport *vport, u16 num_tqps) +static int hclge_knic_setup(struct hclge_vport *vport, + u16 num_tqps, u16 num_desc) { struct hnae3_handle *nic = &vport->nic; struct hnae3_knic_private_info *kinfo = &nic->kinfo; struct hclge_dev *hdev = vport->back; int i, ret; - kinfo->num_desc = hdev->num_desc; + kinfo->num_desc = num_desc; kinfo->rx_buf_len = hdev->rx_buf_len; kinfo->num_tc = min_t(u16, num_tqps, hdev->tm_info.num_tc); kinfo->rss_size @@ -1321,7 +1324,7 @@ static int hclge_knic_setup(struct hclge_vport *vport, u16 num_tqps) if (!kinfo->tqp) return -ENOMEM; - ret = hclge_assign_tqp(vport, kinfo->tqp, kinfo->num_tqps); + ret = hclge_assign_tqp(vport); if (ret) dev_err(&hdev->pdev->dev, "fail to assign TQPs %d.\n", ret); @@ -1387,7 +1390,7 @@ static int hclge_vport_setup(struct hclge_vport *vport, u16 num_tqps) nic->numa_node_mask = hdev->numa_node_mask; if (hdev->ae_dev->dev_type == HNAE3_DEV_KNIC) { - ret = hclge_knic_setup(vport, num_tqps); + ret = hclge_knic_setup(vport, num_tqps, hdev->num_desc); if (ret) { dev_err(&hdev->pdev->dev, "knic setup failed %d\n", ret); @@ -3670,6 +3673,55 @@ static int hclge_set_mac_loopback(struct hclge_dev *hdev, bool en) return ret; } +static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en) +{ +#define HCLGE_SERDES_RETRY_MS 10 +#define HCLGE_SERDES_RETRY_NUM 100 + struct hclge_serdes_lb_cmd *req; + struct hclge_desc desc; + int ret, i = 0; + + req = (struct hclge_serdes_lb_cmd *)&desc.data[0]; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, false); + + if (en) { + req->enable = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; + req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; + } else { + req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; + } + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "serdes loopback set fail, ret = %d\n", ret); + return ret; + } + + do { + msleep(HCLGE_SERDES_RETRY_MS); + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, + true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "serdes loopback get, ret = %d\n", ret); + return ret; + } + } while (++i < HCLGE_SERDES_RETRY_NUM && + !(req->result & HCLGE_CMD_SERDES_DONE_B)); + + if (!(req->result & HCLGE_CMD_SERDES_DONE_B)) { + dev_err(&hdev->pdev->dev, "serdes loopback set timeout\n"); + return -EBUSY; + } else if (!(req->result & HCLGE_CMD_SERDES_SUCCESS_B)) { + dev_err(&hdev->pdev->dev, "serdes loopback set failed in fw\n"); + return -EIO; + } + + return 0; +} + static int hclge_set_loopback(struct hnae3_handle *handle, enum hnae3_loop loop_mode, bool en) { @@ -3681,6 +3733,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle, case HNAE3_MAC_INTER_LOOP_MAC: ret = hclge_set_mac_loopback(hdev, en); break; + case HNAE3_MAC_INTER_LOOP_SERDES: + ret = hclge_set_serdes_loopback(hdev, en); + break; default: ret = -ENOTSUPP; dev_err(&hdev->pdev->dev, @@ -3729,7 +3784,7 @@ static int hclge_ae_start(struct hnae3_handle *handle) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - int i, ret; + int i; for (i = 0; i < vport->alloc_tqps; i++) hclge_tqp_enable(hdev, i, 0, true); @@ -3743,9 +3798,7 @@ static int hclge_ae_start(struct hnae3_handle *handle) /* reset tqp stats */ hclge_reset_tqp_stats(handle); - ret = hclge_mac_start_phy(hdev); - if (ret) - return ret; + hclge_mac_start_phy(hdev); return 0; } @@ -3877,7 +3930,7 @@ static bool hclge_is_all_function_id_zero(struct hclge_desc *desc) #define HCLGE_FUNC_NUMBER_PER_DESC 6 int i, j; - for (i = 0; i < HCLGE_DESC_NUMBER; i++) + for (i = 1; i < HCLGE_DESC_NUMBER; i++) for (j = 0; j < HCLGE_FUNC_NUMBER_PER_DESC; j++) if (desc[i].data[j]) return false; @@ -5364,6 +5417,16 @@ static void hclge_get_mdix_mode(struct hnae3_handle *handle, *tp_mdix = ETH_TP_MDI; } +static int hclge_init_instance_hw(struct hclge_dev *hdev) +{ + return hclge_mac_connect_phy(hdev); +} + +static void hclge_uninit_instance_hw(struct hclge_dev *hdev) +{ + hclge_mac_disconnect_phy(hdev); +} + static int hclge_init_client_instance(struct hnae3_client *client, struct hnae3_ae_dev *ae_dev) { @@ -5383,6 +5446,13 @@ static int hclge_init_client_instance(struct hnae3_client *client, if (ret) return ret; + ret = hclge_init_instance_hw(hdev); + if (ret) { + client->ops->uninit_instance(&vport->nic, + 0); + return ret; + } + if (hdev->roce_client && hnae3_dev_roce_supported(hdev)) { struct hnae3_client *rc = hdev->roce_client; @@ -5445,6 +5515,7 @@ static void hclge_uninit_client_instance(struct hnae3_client *client, if (client->type == HNAE3_CLIENT_ROCE) return; if (client->ops->uninit_instance) { + hclge_uninit_instance_hw(hdev); client->ops->uninit_instance(&vport->nic, 0); hdev->nic_client = NULL; vport->nic.client = NULL; @@ -5867,7 +5938,7 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num) /* Free old tqps, and reallocate with new tqp number when nic setup */ hclge_release_tqp(vport); - ret = hclge_knic_setup(vport, new_tqps_num); + ret = hclge_knic_setup(vport, new_tqps_num, kinfo->num_desc); if (ret) { dev_err(&hdev->pdev->dev, "setup nic fail, ret =%d\n", ret); return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index 2065ee2fd358..398971a062f4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -193,7 +193,7 @@ static void hclge_mac_adjust_link(struct net_device *netdev) netdev_err(netdev, "failed to configure flow control.\n"); } -int hclge_mac_start_phy(struct hclge_dev *hdev) +int hclge_mac_connect_phy(struct hclge_dev *hdev) { struct net_device *netdev = hdev->vport[0].nic.netdev; struct phy_device *phydev = hdev->hw.mac.phydev; @@ -202,6 +202,8 @@ int hclge_mac_start_phy(struct hclge_dev *hdev) if (!phydev) return 0; + phydev->supported &= ~SUPPORTED_FIBRE; + ret = phy_connect_direct(netdev, phydev, hclge_mac_adjust_link, PHY_INTERFACE_MODE_SGMII); @@ -213,11 +215,29 @@ int hclge_mac_start_phy(struct hclge_dev *hdev) phydev->supported &= HCLGE_PHY_SUPPORTED_FEATURES; phydev->advertising = phydev->supported; - phy_start(phydev); - return 0; } +void hclge_mac_disconnect_phy(struct hclge_dev *hdev) +{ + struct phy_device *phydev = hdev->hw.mac.phydev; + + if (!phydev) + return; + + phy_disconnect(phydev); +} + +void hclge_mac_start_phy(struct hclge_dev *hdev) +{ + struct phy_device *phydev = hdev->hw.mac.phydev; + + if (!phydev) + return; + + phy_start(phydev); +} + void hclge_mac_stop_phy(struct hclge_dev *hdev) { struct net_device *netdev = hdev->vport[0].nic.netdev; @@ -227,5 +247,4 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev) return; phy_stop(phydev); - phy_disconnect(phydev); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h index bb3ce35e0d66..5fbf7dddb5d9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h @@ -5,7 +5,9 @@ #define __HCLGE_MDIO_H int hclge_mac_mdio_config(struct hclge_dev *hdev); -int hclge_mac_start_phy(struct hclge_dev *hdev); +int hclge_mac_connect_phy(struct hclge_dev *hdev); +void hclge_mac_disconnect_phy(struct hclge_dev *hdev); +void hclge_mac_start_phy(struct hclge_dev *hdev); void hclge_mac_stop_phy(struct hclge_dev *hdev); #endif |