diff options
Diffstat (limited to 'drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c')
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 105 |
1 files changed, 88 insertions, 17 deletions
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; |