crypto: qat - free irqs only if allocated
authorMaksim Lukoshkov <maksim.lukoshkov@intel.com>
Wed, 1 Sep 2021 17:36:07 +0000 (18:36 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 17 Sep 2021 03:05:12 +0000 (11:05 +0800)
Change the irq allocation logic so that it is possible to free only the
allocated irqs in case of error.
A new flag is introduced for every PF/VF interrupt. This flag is set to
"true" only when the interrupt is requested.
During clean up, devm_free_irq() is only called if this flag is set.

Signed-off-by: Maksim Lukoshkov <maksim.lukoshkov@intel.com>
Co-developed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
Signed-off-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/qat/qat_common/adf_accel_devices.h
drivers/crypto/qat/qat_common/adf_isr.c
drivers/crypto/qat/qat_common/adf_vf_isr.c

index 87de40d..e391ca0 100644 (file)
@@ -44,8 +44,13 @@ struct adf_bar {
        resource_size_t size;
 } __packed;
 
+struct adf_irq {
+       bool enabled;
+       char name[ADF_MAX_MSIX_VECTOR_NAME];
+};
+
 struct adf_accel_msix {
-       char **names;
+       struct adf_irq *irqs;
        u32 num_entries;
 } __packed;
 
@@ -250,7 +255,8 @@ struct adf_accel_dev {
                        struct adf_accel_vf_info *vf_info;
                } pf;
                struct {
-                       char *irq_name;
+                       bool irq_enabled;
+                       char irq_name[ADF_MAX_MSIX_VECTOR_NAME];
                        struct tasklet_struct pf2vf_bh_tasklet;
                        struct mutex vf2pf_lock; /* protect CSR access */
                        struct completion iov_msg_completion;
index 26b546d..861a936 100644 (file)
@@ -130,6 +130,7 @@ static int adf_request_irqs(struct adf_accel_dev *accel_dev)
 {
        struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       struct adf_irq *irqs = pci_dev_info->msix_entries.irqs;
        struct adf_etr_data *etr_data = accel_dev->transport;
        int clust_irq = hw_data->num_banks;
        int ret, irq, i = 0;
@@ -141,7 +142,7 @@ static int adf_request_irqs(struct adf_accel_dev *accel_dev)
                        struct adf_etr_bank_data *bank = &etr_data->banks[i];
                        unsigned int cpu, cpus = num_online_cpus();
 
-                       name = *(pci_dev_info->msix_entries.names + i);
+                       name = irqs[i].name;
                        snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
                                 "qat%d-bundle%d", accel_dev->accel_id, i);
                        irq = pci_irq_vector(pci_dev_info->pci_dev, i);
@@ -163,11 +164,12 @@ static int adf_request_irqs(struct adf_accel_dev *accel_dev)
                        cpu = ((accel_dev->accel_id * hw_data->num_banks) +
                               i) % cpus;
                        irq_set_affinity_hint(irq, get_cpu_mask(cpu));
+                       irqs[i].enabled = true;
                }
        }
 
        /* Request msix irq for AE */
-       name = *(pci_dev_info->msix_entries.names + i);
+       name = irqs[i].name;
        snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
                 "qat%d-ae-cluster", accel_dev->accel_id);
        irq = pci_irq_vector(pci_dev_info->pci_dev, clust_irq);
@@ -183,6 +185,7 @@ static int adf_request_irqs(struct adf_accel_dev *accel_dev)
                        "Failed to allocate IRQ %d for %s\n", irq, name);
                return ret;
        }
+       irqs[i].enabled = true;
        return ret;
 }
 
@@ -190,60 +193,51 @@ static void adf_free_irqs(struct adf_accel_dev *accel_dev)
 {
        struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       struct adf_irq *irqs = pci_dev_info->msix_entries.irqs;
        struct adf_etr_data *etr_data = accel_dev->transport;
        int clust_irq = hw_data->num_banks;
        int irq, i = 0;
 
        if (pci_dev_info->msix_entries.num_entries > 1) {
                for (i = 0; i < hw_data->num_banks; i++) {
-                       irq = pci_irq_vector(pci_dev_info->pci_dev, i);
-                       irq_set_affinity_hint(irq, NULL);
-                       free_irq(irq, &etr_data->banks[i]);
+                       if (irqs[i].enabled) {
+                               irq = pci_irq_vector(pci_dev_info->pci_dev, i);
+                               irq_set_affinity_hint(irq, NULL);
+                               free_irq(irq, &etr_data->banks[i]);
+                       }
                }
        }
 
-       irq = pci_irq_vector(pci_dev_info->pci_dev, clust_irq);
-       free_irq(irq, accel_dev);
+       if (irqs[i].enabled) {
+               irq = pci_irq_vector(pci_dev_info->pci_dev, clust_irq);
+               free_irq(irq, accel_dev);
+       }
 }
 
 static int adf_isr_alloc_msix_vectors_data(struct adf_accel_dev *accel_dev)
 {
-       int i;
-       char **names;
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
        u32 msix_num_entries = 1;
+       struct adf_irq *irqs;
 
        /* If SR-IOV is disabled (vf_info is NULL), add entries for each bank */
        if (!accel_dev->pf.vf_info)
                msix_num_entries += hw_data->num_banks;
 
-       names = kcalloc(msix_num_entries, sizeof(char *), GFP_KERNEL);
-       if (!names)
+       irqs = kzalloc_node(msix_num_entries * sizeof(*irqs),
+                           GFP_KERNEL, dev_to_node(&GET_DEV(accel_dev)));
+       if (!irqs)
                return -ENOMEM;
 
-       for (i = 0; i < msix_num_entries; i++) {
-               *(names + i) = kzalloc(ADF_MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
-               if (!(*(names + i)))
-                       goto err;
-       }
        accel_dev->accel_pci_dev.msix_entries.num_entries = msix_num_entries;
-       accel_dev->accel_pci_dev.msix_entries.names = names;
+       accel_dev->accel_pci_dev.msix_entries.irqs = irqs;
        return 0;
-err:
-       for (i = 0; i < msix_num_entries; i++)
-               kfree(*(names + i));
-       kfree(names);
-       return -ENOMEM;
 }
 
 static void adf_isr_free_msix_vectors_data(struct adf_accel_dev *accel_dev)
 {
-       char **names = accel_dev->accel_pci_dev.msix_entries.names;
-       int i;
-
-       for (i = 0; i < accel_dev->accel_pci_dev.msix_entries.num_entries; i++)
-               kfree(*(names + i));
-       kfree(names);
+       kfree(accel_dev->accel_pci_dev.msix_entries.irqs);
+       accel_dev->accel_pci_dev.msix_entries.irqs = NULL;
 }
 
 static int adf_setup_bh(struct adf_accel_dev *accel_dev)
index 695c505..07f8168 100644 (file)
@@ -61,10 +61,6 @@ static int adf_enable_msi(struct adf_accel_dev *accel_dev)
                return stat;
        }
 
-       accel_dev->vf.irq_name = kzalloc(ADF_MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
-       if (!accel_dev->vf.irq_name)
-               return -ENOMEM;
-
        return 0;
 }
 
@@ -72,7 +68,6 @@ static void adf_disable_msi(struct adf_accel_dev *accel_dev)
 {
        struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
 
-       kfree(accel_dev->vf.irq_name);
        pci_free_irq_vectors(pdev);
 }
 
@@ -240,6 +235,7 @@ static int adf_request_msi_irq(struct adf_accel_dev *accel_dev)
        }
        cpu = accel_dev->accel_id % num_online_cpus();
        irq_set_affinity_hint(pdev->irq, get_cpu_mask(cpu));
+       accel_dev->vf.irq_enabled = true;
 
        return ret;
 }
@@ -271,8 +267,10 @@ void adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev)
 {
        struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
 
-       irq_set_affinity_hint(pdev->irq, NULL);
-       free_irq(pdev->irq, (void *)accel_dev);
+       if (accel_dev->vf.irq_enabled) {
+               irq_set_affinity_hint(pdev->irq, NULL);
+               free_irq(pdev->irq, accel_dev);
+       }
        adf_cleanup_bh(accel_dev);
        adf_cleanup_pf2vf_bh(accel_dev);
        adf_disable_msi(accel_dev);