| From 5f0d17174801a3aee346c6d60b4ab2b3962c3b7d Mon Sep 17 00:00:00 2001 |
| From: Yonglong Liu <liuyonglong@huawei.com> |
| Date: Fri, 18 Oct 2019 11:42:59 +0800 |
| Subject: [PATCH] net: hns3: fix mis-counting IRQ vector numbers issue |
| |
| commit 580a05f9d4ada3bfb689140d0efec1efdb8a48da upstream. |
| |
| Currently, the num_msi_left means the vector numbers of NIC, |
| but if the PF supported RoCE, it contains the vector numbers |
| of NIC and RoCE(Not expected). |
| |
| This may cause interrupts lost in some case, because of the |
| NIC module used the vector resources which belongs to RoCE. |
| |
| This patch adds a new variable num_nic_msi to store the vector |
| numbers of NIC, and adjust the default TQP numbers and rss_size |
| according to the value of num_nic_msi. |
| |
| Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support") |
| Signed-off-by: Yonglong Liu <liuyonglong@huawei.com> |
| Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h |
| index ad21b0ef1946..b43ef9f0857d 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h |
| @@ -32,6 +32,8 @@ |
| |
| #define HNAE3_MOD_VERSION "1.0" |
| |
| +#define HNAE3_MIN_VECTOR_NUM 2 /* first one for misc, another for IO */ |
| + |
| /* Device IDs */ |
| #define HNAE3_DEV_ID_GE 0xA220 |
| #define HNAE3_DEV_ID_25GE 0xA221 |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c |
| index f2bffc05e902..8d0123f79ffe 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c |
| @@ -796,6 +796,9 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev) |
| hnae3_get_field(__le16_to_cpu(req->pf_intr_vector_number), |
| HCLGE_PF_VEC_NUM_M, HCLGE_PF_VEC_NUM_S); |
| |
| + /* nic's msix numbers is always equals to the roce's. */ |
| + hdev->num_nic_msi = hdev->num_roce_msi; |
| + |
| /* PF should have NIC vectors and Roce vectors, |
| * NIC vectors are queued before Roce vectors. |
| */ |
| @@ -805,6 +808,15 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev) |
| hdev->num_msi = |
| hnae3_get_field(__le16_to_cpu(req->pf_intr_vector_number), |
| HCLGE_PF_VEC_NUM_M, HCLGE_PF_VEC_NUM_S); |
| + |
| + hdev->num_nic_msi = hdev->num_msi; |
| + } |
| + |
| + if (hdev->num_nic_msi < HNAE3_MIN_VECTOR_NUM) { |
| + dev_err(&hdev->pdev->dev, |
| + "Just %u msi resources, not enough for pf(min:2).\n", |
| + hdev->num_nic_msi); |
| + return -EINVAL; |
| } |
| |
| return 0; |
| @@ -1385,6 +1397,10 @@ static int hclge_assign_tqp(struct hclge_vport *vport, u16 num_tqps) |
| kinfo->rss_size = min_t(u16, hdev->rss_size_max, |
| vport->alloc_tqps / hdev->tm_info.num_tc); |
| |
| + /* ensure one to one mapping between irq and queue at default */ |
| + kinfo->rss_size = min_t(u16, kinfo->rss_size, |
| + (hdev->num_nic_msi - 1) / hdev->tm_info.num_tc); |
| + |
| return 0; |
| } |
| |
| @@ -2112,7 +2128,8 @@ static int hclge_init_msi(struct hclge_dev *hdev) |
| int vectors; |
| int i; |
| |
| - vectors = pci_alloc_irq_vectors(pdev, 1, hdev->num_msi, |
| + vectors = pci_alloc_irq_vectors(pdev, HNAE3_MIN_VECTOR_NUM, |
| + hdev->num_msi, |
| PCI_IRQ_MSI | PCI_IRQ_MSIX); |
| if (vectors < 0) { |
| dev_err(&pdev->dev, |
| @@ -2127,6 +2144,7 @@ static int hclge_init_msi(struct hclge_dev *hdev) |
| |
| hdev->num_msi = vectors; |
| hdev->num_msi_left = vectors; |
| + |
| hdev->base_msi_vector = pdev->irq; |
| hdev->roce_base_vector = hdev->base_msi_vector + |
| hdev->roce_base_msix_offset; |
| @@ -3561,6 +3579,7 @@ static int hclge_get_vector(struct hnae3_handle *handle, u16 vector_num, |
| int alloc = 0; |
| int i, j; |
| |
| + vector_num = min_t(u16, hdev->num_nic_msi - 1, vector_num); |
| vector_num = min(hdev->num_msi_left, vector_num); |
| |
| for (j = 0; j < vector_num; j++) { |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h |
| index dd06b11187b0..390cbb77e778 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h |
| @@ -761,6 +761,7 @@ struct hclge_dev { |
| u32 base_msi_vector; |
| u16 *vector_status; |
| int *vector_irq; |
| + u16 num_nic_msi; /* Num of nic vectors for this PF */ |
| u16 num_roce_msi; /* Num of roce vectors for this PF */ |
| int roce_base_vector; |
| |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c |
| index 0d53062f7bb5..9fa0f85daf98 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c |
| @@ -539,8 +539,16 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) |
| kinfo->rss_size = kinfo->req_rss_size; |
| } else if (kinfo->rss_size > max_rss_size || |
| (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size)) { |
| - dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n", |
| - kinfo->rss_size, max_rss_size); |
| + /* if user not set rss, the rss_size should compare with the |
| + * valid msi numbers to ensure one to one map between tqp and |
| + * irq as default. |
| + */ |
| + if (!kinfo->req_rss_size) |
| + max_rss_size = min_t(u16, max_rss_size, |
| + (hdev->num_nic_msi - 1) / |
| + kinfo->num_tc); |
| + |
| + /* Set to the maximum specification value (max_rss_size). */ |
| kinfo->rss_size = max_rss_size; |
| } |
| |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c |
| index 3b02745605d4..48d943ae18be 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c |
| @@ -409,6 +409,13 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) |
| kinfo->tqp[i] = &hdev->htqp[i].q; |
| } |
| |
| + /* after init the max rss_size and tqps, adjust the default tqp numbers |
| + * and rss size with the actual vector numbers |
| + */ |
| + kinfo->num_tqps = min_t(u16, hdev->num_nic_msix - 1, kinfo->num_tqps); |
| + kinfo->rss_size = min_t(u16, kinfo->num_tqps / kinfo->num_tc, |
| + kinfo->rss_size); |
| + |
| return 0; |
| } |
| |
| @@ -504,6 +511,7 @@ static int hclgevf_get_vector(struct hnae3_handle *handle, u16 vector_num, |
| int alloc = 0; |
| int i, j; |
| |
| + vector_num = min_t(u16, hdev->num_nic_msix - 1, vector_num); |
| vector_num = min(hdev->num_msi_left, vector_num); |
| |
| for (j = 0; j < vector_num; j++) { |
| @@ -2146,13 +2154,14 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev) |
| int vectors; |
| int i; |
| |
| - if (hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B)) |
| + if (hnae3_dev_roce_supported(hdev)) |
| vectors = pci_alloc_irq_vectors(pdev, |
| hdev->roce_base_msix_offset + 1, |
| hdev->num_msi, |
| PCI_IRQ_MSIX); |
| else |
| - vectors = pci_alloc_irq_vectors(pdev, 1, hdev->num_msi, |
| + vectors = pci_alloc_irq_vectors(pdev, HNAE3_MIN_VECTOR_NUM, |
| + hdev->num_msi, |
| PCI_IRQ_MSI | PCI_IRQ_MSIX); |
| |
| if (vectors < 0) { |
| @@ -2168,6 +2177,7 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev) |
| |
| hdev->num_msi = vectors; |
| hdev->num_msi_left = vectors; |
| + |
| hdev->base_msi_vector = pdev->irq; |
| hdev->roce_base_vector = pdev->irq + hdev->roce_base_msix_offset; |
| |
| @@ -2419,7 +2429,7 @@ static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev) |
| |
| req = (struct hclgevf_query_res_cmd *)desc.data; |
| |
| - if (hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B)) { |
| + if (hnae3_dev_roce_supported(hdev)) { |
| hdev->roce_base_msix_offset = |
| hnae3_get_field(__le16_to_cpu(req->msixcap_localid_ba_rocee), |
| HCLGEVF_MSIX_OFT_ROCEE_M, |
| @@ -2428,6 +2438,9 @@ static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev) |
| hnae3_get_field(__le16_to_cpu(req->vf_intr_vector_number), |
| HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S); |
| |
| + /* nic's msix numbers is always equals to the roce's. */ |
| + hdev->num_nic_msix = hdev->num_roce_msix; |
| + |
| /* VF should have NIC vectors and Roce vectors, NIC vectors |
| * are queued before Roce vectors. The offset is fixed to 64. |
| */ |
| @@ -2437,6 +2450,15 @@ static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev) |
| hdev->num_msi = |
| hnae3_get_field(__le16_to_cpu(req->vf_intr_vector_number), |
| HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S); |
| + |
| + hdev->num_nic_msix = hdev->num_msi; |
| + } |
| + |
| + if (hdev->num_nic_msix < HNAE3_MIN_VECTOR_NUM) { |
| + dev_err(&hdev->pdev->dev, |
| + "Just %u msi resources, not enough for vf(min:2).\n", |
| + hdev->num_nic_msix); |
| + return -EINVAL; |
| } |
| |
| return 0; |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h |
| index cc52f54f8c08..d6798e07a8b4 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h |
| @@ -258,6 +258,7 @@ struct hclgevf_dev { |
| u16 num_msi; |
| u16 num_msi_left; |
| u16 num_msi_used; |
| + u16 num_nic_msix; /* Num of nic vectors for this VF */ |
| u16 num_roce_msix; /* Num of roce vectors for this VF */ |
| u16 roce_base_msix_offset; |
| int roce_base_vector; |
| -- |
| 2.7.4 |
| |