Skip to content

Commit

Permalink
mfd: Fix memleak in pcf50633_client_dev_register
Browse files Browse the repository at this point in the history
Since platform_device_add_data copies the passed data, the allocated
subdev_pdata is never freed. A simple fix would be to either free subdev_pdata
or put it onto the stack. But since the pcf50633 child devices can rely on
beeing children of the pcf50633 core device it's much more elegant to get access
to pcf50633 core structure through that link. This allows to get completly rid
of pcf5033_subdev_pdata.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Lars-Peter Clausen authored and Samuel Ortiz committed Dec 13, 2009
1 parent b18fdc4 commit 68d641e
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 28 deletions.
7 changes: 3 additions & 4 deletions drivers/input/misc/pcf50633-input.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ pcf50633_input_irq(int irq, void *data)
static int __devinit pcf50633_input_probe(struct platform_device *pdev)
{
struct pcf50633_input *input;
struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
struct input_dev *input_dev;
int ret;

Expand All @@ -71,7 +70,7 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev)
}

platform_set_drvdata(pdev, input);
input->pcf = pdata->pcf;
input->pcf = dev_to_pcf50633(pdev->dev.parent);
input->input_dev = input_dev;

input_dev->name = "PCF50633 PMU events";
Expand All @@ -85,9 +84,9 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev)
kfree(input);
return ret;
}
pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYR,
pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR,
pcf50633_input_irq, input);
pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYF,
pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF,
pcf50633_input_irq, input);

return 0;
Expand Down
5 changes: 2 additions & 3 deletions drivers/mfd/pcf50633-adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,16 @@ static void pcf50633_adc_irq(int irq, void *data)

static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
{
struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
struct pcf50633_adc *adc;

adc = kzalloc(sizeof(*adc), GFP_KERNEL);
if (!adc)
return -ENOMEM;

adc->pcf = pdata->pcf;
adc->pcf = dev_to_pcf50633(pdev->dev.parent);
platform_set_drvdata(pdev, adc);

pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ADCRDY,
pcf50633_register_irq(adc->pcf, PCF50633_IRQ_ADCRDY,
pcf50633_adc_irq, adc);

mutex_init(&adc->queue_mutex);
Expand Down
10 changes: 0 additions & 10 deletions drivers/mfd/pcf50633-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,6 @@ static void
pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
struct platform_device **pdev)
{
struct pcf50633_subdev_pdata *subdev_pdata;
int ret;

*pdev = platform_device_alloc(name, -1);
Expand All @@ -465,15 +464,6 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
return;
}

subdev_pdata = kmalloc(sizeof(*subdev_pdata), GFP_KERNEL);
if (!subdev_pdata) {
dev_err(pcf->dev, "Error allocating subdev pdata\n");
platform_device_put(*pdev);
}

subdev_pdata->pcf = pcf;
platform_device_add_data(*pdev, subdev_pdata, sizeof(*subdev_pdata));

(*pdev)->dev.parent = pcf->dev;

ret = platform_device_add(*pdev);
Expand Down
3 changes: 1 addition & 2 deletions drivers/power/pcf50633-charger.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,6 @@ static const u8 mbc_irq_handlers[] = {
static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
{
struct pcf50633_mbc *mbc;
struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
int ret;
int i;
u8 mbcs1;
Expand All @@ -313,7 +312,7 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
return -ENOMEM;

platform_set_drvdata(pdev, mbc);
mbc->pcf = pdata->pcf;
mbc->pcf = dev_to_pcf50633(pdev->dev.parent);

/* Set up IRQ handlers */
for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
Expand Down
5 changes: 1 addition & 4 deletions drivers/rtc/rtc-pcf50633.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,16 +277,13 @@ static void pcf50633_rtc_irq(int irq, void *data)

static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
{
struct pcf50633_subdev_pdata *pdata;
struct pcf50633_rtc *rtc;


rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;

pdata = pdev->dev.platform_data;
rtc->pcf = pdata->pcf;
rtc->pcf = dev_to_pcf50633(pdev->dev.parent);
platform_set_drvdata(pdev, rtc);
rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev,
&pcf50633_rtc_ops, THIS_MODULE);
Expand Down
10 changes: 5 additions & 5 deletions include/linux/mfd/pcf50633/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ struct pcf50633_platform_data {
u8 resumers[5];
};

struct pcf50633_subdev_pdata {
struct pcf50633 *pcf;
};

struct pcf50633_irq {
void (*handler) (int, void *);
void *data;
Expand Down Expand Up @@ -217,5 +213,9 @@ enum pcf50633_reg_int5 {
#define PCF50633_REG_LEDCTL 0x2a
#define PCF50633_REG_LEDDIM 0x2b

#endif
static inline struct pcf50633 *dev_to_pcf50633(struct device *dev)
{
return dev_get_drvdata(dev);
}

#endif

0 comments on commit 68d641e

Please sign in to comment.