ASoC: Intel: Skylake: Fix memory leak in nhlt init
authorJeeja KP <jeeja.kp@intel.com>
Thu, 5 May 2016 05:49:19 +0000 (11:19 +0530)
committerMark Brown <broonie@kernel.org>
Thu, 5 May 2016 15:46:54 +0000 (16:46 +0100)
During skl_nhlt_init(), acpi obj pointer is allocated and never
freed and remap address is not unmapped.

To fix this we should release the ACPI obj and also unmap the
nhlt address during cleanup of driver.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/skylake/skl-nhlt.c
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.h

index 14d1916ea9f843af75622cd50c93dcf5d426fd68..7d73648e5f9ab22570f67b5153fb74fd36d1985c 100644 (file)
@@ -25,11 +25,12 @@ static u8 OSC_UUID[16] = {0x6E, 0x88, 0x9F, 0xA6, 0xEB, 0x6C, 0x94, 0x45,
 
 #define DSDT_NHLT_PATH "\\_SB.PCI0.HDAS"
 
-void *skl_nhlt_init(struct device *dev)
+struct nhlt_acpi_table *skl_nhlt_init(struct device *dev)
 {
        acpi_handle handle;
        union acpi_object *obj;
        struct nhlt_resource_desc  *nhlt_ptr = NULL;
+       struct nhlt_acpi_table *nhlt_table = NULL;
 
        if (ACPI_FAILURE(acpi_get_handle(NULL, DSDT_NHLT_PATH, &handle))) {
                dev_err(dev, "Requested NHLT device not found\n");
@@ -39,18 +40,20 @@ void *skl_nhlt_init(struct device *dev)
        obj = acpi_evaluate_dsm(handle, OSC_UUID, 1, 1, NULL);
        if (obj && obj->type == ACPI_TYPE_BUFFER) {
                nhlt_ptr = (struct nhlt_resource_desc  *)obj->buffer.pointer;
-
-               return memremap(nhlt_ptr->min_addr, nhlt_ptr->length,
+               nhlt_table = (struct nhlt_acpi_table *)
+                               memremap(nhlt_ptr->min_addr, nhlt_ptr->length,
                                MEMREMAP_WB);
+               ACPI_FREE(obj);
+               return nhlt_table;
        }
 
        dev_err(dev, "device specific method to extract NHLT blob failed\n");
        return NULL;
 }
 
-void skl_nhlt_free(void *addr)
+void skl_nhlt_free(struct nhlt_acpi_table *nhlt)
 {
-       memunmap(addr);
+       memunmap((void *) nhlt);
 }
 
 static struct nhlt_specific_cfg *skl_get_specific_cfg(
@@ -120,7 +123,7 @@ struct nhlt_specific_cfg
        struct hdac_bus *bus = ebus_to_hbus(&skl->ebus);
        struct device *dev = bus->dev;
        struct nhlt_specific_cfg *sp_config;
-       struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
+       struct nhlt_acpi_table *nhlt = skl->nhlt;
        u16 bps = (s_fmt == 16) ? 16 : 32;
        u8 j;
 
index 3982f5536f2d82b55837c4358e0b2754ac95e2c4..83e985c0c0c9fe7369db75f92e0c70786d42b3e3 100644 (file)
@@ -643,7 +643,7 @@ static int skl_probe(struct pci_dev *pci,
                err = skl_machine_device_register(skl,
                                  (void *)pci_id->driver_data);
                if (err < 0)
-                       goto out_free;
+                       goto out_nhlt_free;
 
                err = skl_init_dsp(skl);
                if (err < 0) {
@@ -693,6 +693,8 @@ out_dsp_free:
        skl_free_dsp(skl);
 out_mach_free:
        skl_machine_device_unregister(skl);
+out_nhlt_free:
+       skl_nhlt_free(skl->nhlt);
 out_free:
        skl->init_failed = 1;
        skl_free(ebus);
@@ -743,6 +745,7 @@ static void skl_remove(struct pci_dev *pci)
        skl_free_dsp(skl);
        skl_machine_device_unregister(skl);
        skl_dmic_device_unregister(skl);
+       skl_nhlt_free(skl->nhlt);
        skl_free(ebus);
        dev_set_drvdata(&pci->dev, NULL);
 }
index 39e16fa7a92b1a6921d8032ed279e88319061a4e..4b4b3876aea9a9ab6a70e2bce86d822c5c30168b 100644 (file)
@@ -66,7 +66,7 @@ struct skl {
        struct platform_device *dmic_dev;
        struct platform_device *i2s_dev;
 
-       void *nhlt; /* nhlt ptr */
+       struct nhlt_acpi_table *nhlt; /* nhlt ptr */
        struct skl_sst *skl_sst; /* sst skl ctx */
 
        struct skl_dsp_resource resource;
@@ -103,8 +103,8 @@ struct skl_dsp_ops {
 int skl_platform_unregister(struct device *dev);
 int skl_platform_register(struct device *dev);
 
-void *skl_nhlt_init(struct device *dev);
-void skl_nhlt_free(void *addr);
+struct nhlt_acpi_table *skl_nhlt_init(struct device *dev);
+void skl_nhlt_free(struct nhlt_acpi_table *addr);
 struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
                        u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn);