All of lore.kernel.org
 help / color / mirror / Atom feed
* Using statically allocated memory for platform_data.
@ 2009-11-02 10:23 ` Antonio Ospite
  0 siblings, 0 replies; 26+ messages in thread
From: Antonio Ospite @ 2009-11-02 10:23 UTC (permalink / raw)
  To: linux-arm-kernel, openezx-devel, linux-kernel
  Cc: Samuel Ortiz, Daniel Ribeiro, Mike Rapoport

[-- Attachment #1: Type: text/plain, Size: 2120 bytes --]

Hi,

I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
drivers/mfd/da903x.c) there is code like this:

static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
                                     struct pcap_subdev *subdev)
{
        struct platform_device *pdev;

        pdev = platform_device_alloc(subdev->name, subdev->id);
        pdev->dev.parent = &pcap->spi->dev;
        pdev->dev.platform_data = subdev->platform_data;

        return platform_device_add(pdev);
}

Note the _direct_assignment_ of platform data; then in board init code
there are often global struct pointers passed as subdev platform data,
see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.

In these cases, whenever the subdev platform device is unregistered,
the call to platform_device_release() tries to kfree the platform data,
and being it statically allocated memory this triggers a bug from SLAB:
	kernel BUG at mm/slab.c:521!
In my case this prevented proper device poweroff.

The question: should these mfd drivers use platform_device_add_data()
which allocates dynamic memory for *a copy* of platform data? Is this
simple solution acceptable even if there will be more memory used?
Or should we setup platform_data in dynamic memory from the beginning
in board init code? (which would be way less pretty IMHO).

As a side note, I've found that SLOB is more permissive in these cases
when statically allocated memory is being freed, it reports the bug but
the kernel does not hang, and in my case poweroff is still possible.

If you need more info to come up with an opinion about that, just let me
know.

Thanks,
   Antonio

P.S. I am sending this also to LKML, but I am not subscribed to it, if
you get the message from there, please CC me on reply.

-- 
Antonio Ospite
http://ao2.it

PGP public key ID: 0x4553B001

A: Because it messes up the order in which people normally read text.
   See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 10:23 ` Antonio Ospite
  0 siblings, 0 replies; 26+ messages in thread
From: Antonio Ospite @ 2009-11-02 10:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
drivers/mfd/da903x.c) there is code like this:

static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
                                     struct pcap_subdev *subdev)
{
        struct platform_device *pdev;

        pdev = platform_device_alloc(subdev->name, subdev->id);
        pdev->dev.parent = &pcap->spi->dev;
        pdev->dev.platform_data = subdev->platform_data;

        return platform_device_add(pdev);
}

Note the _direct_assignment_ of platform data; then in board init code
there are often global struct pointers passed as subdev platform data,
see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.

In these cases, whenever the subdev platform device is unregistered,
the call to platform_device_release() tries to kfree the platform data,
and being it statically allocated memory this triggers a bug from SLAB:
	kernel BUG at mm/slab.c:521!
In my case this prevented proper device poweroff.

The question: should these mfd drivers use platform_device_add_data()
which allocates dynamic memory for *a copy* of platform data? Is this
simple solution acceptable even if there will be more memory used?
Or should we setup platform_data in dynamic memory from the beginning
in board init code? (which would be way less pretty IMHO).

As a side note, I've found that SLOB is more permissive in these cases
when statically allocated memory is being freed, it reports the bug but
the kernel does not hang, and in my case poweroff is still possible.

If you need more info to come up with an opinion about that, just let me
know.

Thanks,
   Antonio

P.S. I am sending this also to LKML, but I am not subscribed to it, if
you get the message from there, please CC me on reply.

-- 
Antonio Ospite
http://ao2.it

PGP public key ID: 0x4553B001

A: Because it messes up the order in which people normally read text.
   See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20091102/7ef9c33a/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 10:23 ` Antonio Ospite
@ 2009-11-02 10:39   ` Uwe Kleine-König
  -1 siblings, 0 replies; 26+ messages in thread
From: Uwe Kleine-König @ 2009-11-02 10:39 UTC (permalink / raw)
  To: Antonio Ospite
  Cc: linux-arm-kernel, openezx-devel, linux-kernel, Samuel Ortiz,
	Daniel Ribeiro, Mike Rapoport

Hello,

On Mon, Nov 02, 2009 at 11:23:16AM +0100, Antonio Ospite wrote:
> Hi,
> 
> I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
> drivers/mfd/da903x.c) there is code like this:
> 
> static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
>                                      struct pcap_subdev *subdev)
> {
>         struct platform_device *pdev;
> 
>         pdev = platform_device_alloc(subdev->name, subdev->id);
>         pdev->dev.parent = &pcap->spi->dev;
>         pdev->dev.platform_data = subdev->platform_data;
> 
>         return platform_device_add(pdev);
> }
> 
> Note the _direct_assignment_ of platform data; then in board init code
> there are often global struct pointers passed as subdev platform data,
> see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.
> 
> In these cases, whenever the subdev platform device is unregistered,
> the call to platform_device_release() tries to kfree the platform data,
> and being it statically allocated memory this triggers a bug from SLAB:
> 	kernel BUG at mm/slab.c:521!
> In my case this prevented proper device poweroff.
> 
> The question: should these mfd drivers use platform_device_add_data()
> which allocates dynamic memory for *a copy* of platform data? Is this
> simple solution acceptable even if there will be more memory used?
If you move the original data lives in .init there is no duplication.

Best regards
Uwe

-- 
Pengutronix e.K.                              | Uwe Kleine-König            |
Industrial Linux Solutions                    | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 10:39   ` Uwe Kleine-König
  0 siblings, 0 replies; 26+ messages in thread
From: Uwe Kleine-König @ 2009-11-02 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Mon, Nov 02, 2009 at 11:23:16AM +0100, Antonio Ospite wrote:
> Hi,
> 
> I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
> drivers/mfd/da903x.c) there is code like this:
> 
> static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
>                                      struct pcap_subdev *subdev)
> {
>         struct platform_device *pdev;
> 
>         pdev = platform_device_alloc(subdev->name, subdev->id);
>         pdev->dev.parent = &pcap->spi->dev;
>         pdev->dev.platform_data = subdev->platform_data;
> 
>         return platform_device_add(pdev);
> }
> 
> Note the _direct_assignment_ of platform data; then in board init code
> there are often global struct pointers passed as subdev platform data,
> see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.
> 
> In these cases, whenever the subdev platform device is unregistered,
> the call to platform_device_release() tries to kfree the platform data,
> and being it statically allocated memory this triggers a bug from SLAB:
> 	kernel BUG at mm/slab.c:521!
> In my case this prevented proper device poweroff.
> 
> The question: should these mfd drivers use platform_device_add_data()
> which allocates dynamic memory for *a copy* of platform data? Is this
> simple solution acceptable even if there will be more memory used?
If you move the original data lives in .init there is no duplication.

Best regards
Uwe

-- 
Pengutronix e.K.                              | Uwe Kleine-K?nig            |
Industrial Linux Solutions                    | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 10:39   ` Uwe Kleine-König
@ 2009-11-02 14:51     ` Ben Dooks
  -1 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 14:51 UTC (permalink / raw)
  To: Uwe Kleine-K?nig
  Cc: Antonio Ospite, linux-arm-kernel, openezx-devel, linux-kernel,
	Samuel Ortiz, Daniel Ribeiro, Mike Rapoport

On Mon, Nov 02, 2009 at 11:39:40AM +0100, Uwe Kleine-K?nig wrote:
> Hello,
> 
> On Mon, Nov 02, 2009 at 11:23:16AM +0100, Antonio Ospite wrote:
> > Hi,
> > 
> > I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
> > drivers/mfd/da903x.c) there is code like this:
> > 
> > static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
> >                                      struct pcap_subdev *subdev)
> > {
> >         struct platform_device *pdev;
> > 
> >         pdev = platform_device_alloc(subdev->name, subdev->id);
> >         pdev->dev.parent = &pcap->spi->dev;
> >         pdev->dev.platform_data = subdev->platform_data;
> > 
> >         return platform_device_add(pdev);
> > }
> > 
> > Note the _direct_assignment_ of platform data; then in board init code
> > there are often global struct pointers passed as subdev platform data,
> > see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.
> > 
> > In these cases, whenever the subdev platform device is unregistered,
> > the call to platform_device_release() tries to kfree the platform data,
> > and being it statically allocated memory this triggers a bug from SLAB:
> > 	kernel BUG at mm/slab.c:521!
> > In my case this prevented proper device poweroff.
> > 
> > The question: should these mfd drivers use platform_device_add_data()
> > which allocates dynamic memory for *a copy* of platform data? Is this
> > simple solution acceptable even if there will be more memory used?
> If you move the original data lives in .init there is no duplication.

they you can't modprobe devices after loading the kernel, so udev
autoload and the like become impossible.

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 14:51     ` Ben Dooks
  0 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 11:39:40AM +0100, Uwe Kleine-K?nig wrote:
> Hello,
> 
> On Mon, Nov 02, 2009 at 11:23:16AM +0100, Antonio Ospite wrote:
> > Hi,
> > 
> > I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
> > drivers/mfd/da903x.c) there is code like this:
> > 
> > static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
> >                                      struct pcap_subdev *subdev)
> > {
> >         struct platform_device *pdev;
> > 
> >         pdev = platform_device_alloc(subdev->name, subdev->id);
> >         pdev->dev.parent = &pcap->spi->dev;
> >         pdev->dev.platform_data = subdev->platform_data;
> > 
> >         return platform_device_add(pdev);
> > }
> > 
> > Note the _direct_assignment_ of platform data; then in board init code
> > there are often global struct pointers passed as subdev platform data,
> > see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.
> > 
> > In these cases, whenever the subdev platform device is unregistered,
> > the call to platform_device_release() tries to kfree the platform data,
> > and being it statically allocated memory this triggers a bug from SLAB:
> > 	kernel BUG at mm/slab.c:521!
> > In my case this prevented proper device poweroff.
> > 
> > The question: should these mfd drivers use platform_device_add_data()
> > which allocates dynamic memory for *a copy* of platform data? Is this
> > simple solution acceptable even if there will be more memory used?
> If you move the original data lives in .init there is no duplication.

they you can't modprobe devices after loading the kernel, so udev
autoload and the like become impossible.

-- 
Ben (ben at fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 10:23 ` Antonio Ospite
@ 2009-11-02 15:00   ` Ben Dooks
  -1 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 15:00 UTC (permalink / raw)
  To: Antonio Ospite
  Cc: linux-arm-kernel, openezx-devel, linux-kernel, Samuel Ortiz,
	Daniel Ribeiro, Mike Rapoport

On Mon, Nov 02, 2009 at 11:23:16AM +0100, Antonio Ospite wrote:
> Hi,
> 
> I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
> drivers/mfd/da903x.c) there is code like this:
> 
> static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
>                                      struct pcap_subdev *subdev)
> {
>         struct platform_device *pdev;
> 
>         pdev = platform_device_alloc(subdev->name, subdev->id);
>         pdev->dev.parent = &pcap->spi->dev;
>         pdev->dev.platform_data = subdev->platform_data;
> 
>         return platform_device_add(pdev);
> }
> 
> Note the _direct_assignment_ of platform data; then in board init code
> there are often global struct pointers passed as subdev platform data,
> see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.
> 
> In these cases, whenever the subdev platform device is unregistered,
> the call to platform_device_release() tries to kfree the platform data,
> and being it statically allocated memory this triggers a bug from SLAB:
> 	kernel BUG at mm/slab.c:521!
> In my case this prevented proper device poweroff.

This looks like something is freeing stuff that it did not allocate in
the first place, which is IMHO bad. The call platform_device_alloc()
is setting platform_device_release() as the default release function
but platform_device_release() releases more than platform_device_alloc()
actually created.

My view is that platform_device_alloc()'s default release shouldn't
be freeing the platform data, and that using platform_device_add_data()
or platform_device_add_resources() should change either the behvaiour 
of platform_device_release() or it should change the pointer to a new
release function.
 
> The question: should these mfd drivers use platform_device_add_data()
> which allocates dynamic memory for *a copy* of platform data? Is this
> simple solution acceptable even if there will be more memory used?
> Or should we setup platform_data in dynamic memory from the beginning
> in board init code? (which would be way less pretty IMHO).

On the s3c24xx, we copy the data when the device is registered by the
board as this allows the board's data to be specified __initdata and
still have things work with hotplug etc.

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 15:00   ` Ben Dooks
  0 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 15:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 11:23:16AM +0100, Antonio Ospite wrote:
> Hi,
> 
> I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
> drivers/mfd/da903x.c) there is code like this:
> 
> static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
>                                      struct pcap_subdev *subdev)
> {
>         struct platform_device *pdev;
> 
>         pdev = platform_device_alloc(subdev->name, subdev->id);
>         pdev->dev.parent = &pcap->spi->dev;
>         pdev->dev.platform_data = subdev->platform_data;
> 
>         return platform_device_add(pdev);
> }
> 
> Note the _direct_assignment_ of platform data; then in board init code
> there are often global struct pointers passed as subdev platform data,
> see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.
> 
> In these cases, whenever the subdev platform device is unregistered,
> the call to platform_device_release() tries to kfree the platform data,
> and being it statically allocated memory this triggers a bug from SLAB:
> 	kernel BUG at mm/slab.c:521!
> In my case this prevented proper device poweroff.

This looks like something is freeing stuff that it did not allocate in
the first place, which is IMHO bad. The call platform_device_alloc()
is setting platform_device_release() as the default release function
but platform_device_release() releases more than platform_device_alloc()
actually created.

My view is that platform_device_alloc()'s default release shouldn't
be freeing the platform data, and that using platform_device_add_data()
or platform_device_add_resources() should change either the behvaiour 
of platform_device_release() or it should change the pointer to a new
release function.
 
> The question: should these mfd drivers use platform_device_add_data()
> which allocates dynamic memory for *a copy* of platform data? Is this
> simple solution acceptable even if there will be more memory used?
> Or should we setup platform_data in dynamic memory from the beginning
> in board init code? (which would be way less pretty IMHO).

On the s3c24xx, we copy the data when the device is registered by the
board as this allows the board's data to be specified __initdata and
still have things work with hotplug etc.

-- 
Ben (ben at fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 15:00   ` Ben Dooks
@ 2009-11-02 15:05     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2009-11-02 15:05 UTC (permalink / raw)
  To: Ben Dooks
  Cc: Antonio Ospite, openezx-devel, Samuel Ortiz, linux-kernel,
	linux-arm-kernel, Mike Rapoport, Daniel Ribeiro

On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> This looks like something is freeing stuff that it did not allocate in
> the first place, which is IMHO bad. The call platform_device_alloc()
> is setting platform_device_release() as the default release function
> but platform_device_release() releases more than platform_device_alloc()
> actually created.
> 
> My view is that platform_device_alloc()'s default release shouldn't
> be freeing the platform data, and that using platform_device_add_data()
> or platform_device_add_resources() should change either the behvaiour 
> of platform_device_release() or it should change the pointer to a new
> release function.

That doesn't work - how do those other functions (adding) know what data
has also been added by other functions?  That can't work reliably.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 15:05     ` Russell King - ARM Linux
  0 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2009-11-02 15:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> This looks like something is freeing stuff that it did not allocate in
> the first place, which is IMHO bad. The call platform_device_alloc()
> is setting platform_device_release() as the default release function
> but platform_device_release() releases more than platform_device_alloc()
> actually created.
> 
> My view is that platform_device_alloc()'s default release shouldn't
> be freeing the platform data, and that using platform_device_add_data()
> or platform_device_add_resources() should change either the behvaiour 
> of platform_device_release() or it should change the pointer to a new
> release function.

That doesn't work - how do those other functions (adding) know what data
has also been added by other functions?  That can't work reliably.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 15:05     ` Russell King - ARM Linux
@ 2009-11-02 15:25       ` Ben Dooks
  -1 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 15:25 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Ben Dooks, Antonio Ospite, openezx-devel, Samuel Ortiz,
	linux-kernel, linux-arm-kernel, Mike Rapoport, Daniel Ribeiro

On Mon, Nov 02, 2009 at 03:05:25PM +0000, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> > This looks like something is freeing stuff that it did not allocate in
> > the first place, which is IMHO bad. The call platform_device_alloc()
> > is setting platform_device_release() as the default release function
> > but platform_device_release() releases more than platform_device_alloc()
> > actually created.
> > 
> > My view is that platform_device_alloc()'s default release shouldn't
> > be freeing the platform data, and that using platform_device_add_data()
> > or platform_device_add_resources() should change either the behvaiour 
> > of platform_device_release() or it should change the pointer to a new
> > release function.
> 
> That doesn't work - how do those other functions (adding) know what data
> has also been added by other functions?  That can't work reliably.

You could wrapper platform device, and each of the add functions could
update it, but that would assume the platform device had been allocated
with platform_device_alloc().

-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 15:25       ` Ben Dooks
  0 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 15:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 03:05:25PM +0000, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> > This looks like something is freeing stuff that it did not allocate in
> > the first place, which is IMHO bad. The call platform_device_alloc()
> > is setting platform_device_release() as the default release function
> > but platform_device_release() releases more than platform_device_alloc()
> > actually created.
> > 
> > My view is that platform_device_alloc()'s default release shouldn't
> > be freeing the platform data, and that using platform_device_add_data()
> > or platform_device_add_resources() should change either the behvaiour 
> > of platform_device_release() or it should change the pointer to a new
> > release function.
> 
> That doesn't work - how do those other functions (adding) know what data
> has also been added by other functions?  That can't work reliably.

You could wrapper platform device, and each of the add functions could
update it, but that would assume the platform device had been allocated
with platform_device_alloc().

-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 15:25       ` Ben Dooks
@ 2009-11-02 15:52         ` Ben Dooks
  -1 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 15:52 UTC (permalink / raw)
  To: Ben Dooks
  Cc: Russell King - ARM Linux, Antonio Ospite, openezx-devel,
	Samuel Ortiz, linux-kernel, linux-arm-kernel, Mike Rapoport,
	Daniel Ribeiro

On Mon, Nov 02, 2009 at 03:25:00PM +0000, Ben Dooks wrote:
> On Mon, Nov 02, 2009 at 03:05:25PM +0000, Russell King - ARM Linux wrote:
> > On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> > > This looks like something is freeing stuff that it did not allocate in
> > > the first place, which is IMHO bad. The call platform_device_alloc()
> > > is setting platform_device_release() as the default release function
> > > but platform_device_release() releases more than platform_device_alloc()
> > > actually created.
> > > 
> > > My view is that platform_device_alloc()'s default release shouldn't
> > > be freeing the platform data, and that using platform_device_add_data()
> > > or platform_device_add_resources() should change either the behvaiour 
> > > of platform_device_release() or it should change the pointer to a new
> > > release function.
> > 
> > That doesn't work - how do those other functions (adding) know what data
> > has also been added by other functions?  That can't work reliably.
> 
> You could wrapper platform device, and each of the add functions could
> update it, but that would assume the platform device had been allocated
> with platform_device_alloc().

Having had a look, all the current users of platform_device_add_data()
are from a platform_alloc_device() created device. 

The number of calls to platform_device_add_resources() are many, but
the ones I checked are from platform_alloc_device().

However your point being that these add calls may not be used on a
device that has been created from platform_device_alloc() is one I
overlooked.

Having a state machine that changed the release call from
platform_device_release() to say platform_device_release_resources()
or platform_device_release_all() and then platform_device_release_all()
may be another way to do it.

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 15:52         ` Ben Dooks
  0 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 15:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 03:25:00PM +0000, Ben Dooks wrote:
> On Mon, Nov 02, 2009 at 03:05:25PM +0000, Russell King - ARM Linux wrote:
> > On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> > > This looks like something is freeing stuff that it did not allocate in
> > > the first place, which is IMHO bad. The call platform_device_alloc()
> > > is setting platform_device_release() as the default release function
> > > but platform_device_release() releases more than platform_device_alloc()
> > > actually created.
> > > 
> > > My view is that platform_device_alloc()'s default release shouldn't
> > > be freeing the platform data, and that using platform_device_add_data()
> > > or platform_device_add_resources() should change either the behvaiour 
> > > of platform_device_release() or it should change the pointer to a new
> > > release function.
> > 
> > That doesn't work - how do those other functions (adding) know what data
> > has also been added by other functions?  That can't work reliably.
> 
> You could wrapper platform device, and each of the add functions could
> update it, but that would assume the platform device had been allocated
> with platform_device_alloc().

Having had a look, all the current users of platform_device_add_data()
are from a platform_alloc_device() created device. 

The number of calls to platform_device_add_resources() are many, but
the ones I checked are from platform_alloc_device().

However your point being that these add calls may not be used on a
device that has been created from platform_device_alloc() is one I
overlooked.

Having a state machine that changed the release call from
platform_device_release() to say platform_device_release_resources()
or platform_device_release_all() and then platform_device_release_all()
may be another way to do it.

-- 
Ben (ben at fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 15:52         ` Ben Dooks
@ 2009-11-02 15:56           ` Russell King - ARM Linux
  -1 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2009-11-02 15:56 UTC (permalink / raw)
  To: Ben Dooks
  Cc: Antonio Ospite, openezx-devel, Samuel Ortiz, linux-kernel,
	linux-arm-kernel, Mike Rapoport, Daniel Ribeiro

On Mon, Nov 02, 2009 at 03:52:31PM +0000, Ben Dooks wrote:
> On Mon, Nov 02, 2009 at 03:25:00PM +0000, Ben Dooks wrote:
> > On Mon, Nov 02, 2009 at 03:05:25PM +0000, Russell King - ARM Linux wrote:
> > > On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> > > > This looks like something is freeing stuff that it did not allocate in
> > > > the first place, which is IMHO bad. The call platform_device_alloc()
> > > > is setting platform_device_release() as the default release function
> > > > but platform_device_release() releases more than platform_device_alloc()
> > > > actually created.
> > > > 
> > > > My view is that platform_device_alloc()'s default release shouldn't
> > > > be freeing the platform data, and that using platform_device_add_data()
> > > > or platform_device_add_resources() should change either the behvaiour 
> > > > of platform_device_release() or it should change the pointer to a new
> > > > release function.
> > > 
> > > That doesn't work - how do those other functions (adding) know what data
> > > has also been added by other functions?  That can't work reliably.
> > 
> > You could wrapper platform device, and each of the add functions could
> > update it, but that would assume the platform device had been allocated
> > with platform_device_alloc().
> 
> Having had a look, all the current users of platform_device_add_data()
> are from a platform_alloc_device() created device. 
> 
> The number of calls to platform_device_add_resources() are many, but
> the ones I checked are from platform_alloc_device().
> 
> However your point being that these add calls may not be used on a
> device that has been created from platform_device_alloc() is one I
> overlooked.

I did not say that.  I said your idea of replacing the release function
on each _add() is impractical when you have multiple _add() functions.

> Having a state machine that changed the release call from
> platform_device_release() to say platform_device_release_resources()
> or platform_device_release_all() and then platform_device_release_all()
> may be another way to do it.

The reason we have platform_device_add_data() is that people think that
the device data needs to persist for the lifetime of the device.  I
personally disagree with that - once you unregister the device, it's
guaranteed that device drivers will have been unregistered, so who's
going to use the platform data?

So we could just fix it by killing off platform_device_add_data() and
removing the kfree of the platform data, and ensuring that data marked
with __initdata either loses that attributation or is kmalloc+copied.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 15:56           ` Russell King - ARM Linux
  0 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2009-11-02 15:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 03:52:31PM +0000, Ben Dooks wrote:
> On Mon, Nov 02, 2009 at 03:25:00PM +0000, Ben Dooks wrote:
> > On Mon, Nov 02, 2009 at 03:05:25PM +0000, Russell King - ARM Linux wrote:
> > > On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> > > > This looks like something is freeing stuff that it did not allocate in
> > > > the first place, which is IMHO bad. The call platform_device_alloc()
> > > > is setting platform_device_release() as the default release function
> > > > but platform_device_release() releases more than platform_device_alloc()
> > > > actually created.
> > > > 
> > > > My view is that platform_device_alloc()'s default release shouldn't
> > > > be freeing the platform data, and that using platform_device_add_data()
> > > > or platform_device_add_resources() should change either the behvaiour 
> > > > of platform_device_release() or it should change the pointer to a new
> > > > release function.
> > > 
> > > That doesn't work - how do those other functions (adding) know what data
> > > has also been added by other functions?  That can't work reliably.
> > 
> > You could wrapper platform device, and each of the add functions could
> > update it, but that would assume the platform device had been allocated
> > with platform_device_alloc().
> 
> Having had a look, all the current users of platform_device_add_data()
> are from a platform_alloc_device() created device. 
> 
> The number of calls to platform_device_add_resources() are many, but
> the ones I checked are from platform_alloc_device().
> 
> However your point being that these add calls may not be used on a
> device that has been created from platform_device_alloc() is one I
> overlooked.

I did not say that.  I said your idea of replacing the release function
on each _add() is impractical when you have multiple _add() functions.

> Having a state machine that changed the release call from
> platform_device_release() to say platform_device_release_resources()
> or platform_device_release_all() and then platform_device_release_all()
> may be another way to do it.

The reason we have platform_device_add_data() is that people think that
the device data needs to persist for the lifetime of the device.  I
personally disagree with that - once you unregister the device, it's
guaranteed that device drivers will have been unregistered, so who's
going to use the platform data?

So we could just fix it by killing off platform_device_add_data() and
removing the kfree of the platform data, and ensuring that data marked
with __initdata either loses that attributation or is kmalloc+copied.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 15:56           ` Russell King - ARM Linux
@ 2009-11-02 16:28             ` Ben Dooks
  -1 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 16:28 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Ben Dooks, Antonio Ospite, openezx-devel, Samuel Ortiz,
	linux-kernel, linux-arm-kernel, Mike Rapoport, Daniel Ribeiro

On Mon, Nov 02, 2009 at 03:56:25PM +0000, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2009 at 03:52:31PM +0000, Ben Dooks wrote:
> > On Mon, Nov 02, 2009 at 03:25:00PM +0000, Ben Dooks wrote:
> > > On Mon, Nov 02, 2009 at 03:05:25PM +0000, Russell King - ARM Linux wrote:
> > > > On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> > > > > This looks like something is freeing stuff that it did not allocate in
> > > > > the first place, which is IMHO bad. The call platform_device_alloc()
> > > > > is setting platform_device_release() as the default release function
> > > > > but platform_device_release() releases more than platform_device_alloc()
> > > > > actually created.
> > > > > 
> > > > > My view is that platform_device_alloc()'s default release shouldn't
> > > > > be freeing the platform data, and that using platform_device_add_data()
> > > > > or platform_device_add_resources() should change either the behvaiour 
> > > > > of platform_device_release() or it should change the pointer to a new
> > > > > release function.
> > > > 
> > > > That doesn't work - how do those other functions (adding) know what data
> > > > has also been added by other functions?  That can't work reliably.
> > > 
> > > You could wrapper platform device, and each of the add functions could
> > > update it, but that would assume the platform device had been allocated
> > > with platform_device_alloc().
> > 
> > Having had a look, all the current users of platform_device_add_data()
> > are from a platform_alloc_device() created device. 
> > 
> > The number of calls to platform_device_add_resources() are many, but
> > the ones I checked are from platform_alloc_device().
> > 
> > However your point being that these add calls may not be used on a
> > device that has been created from platform_device_alloc() is one I
> > overlooked.
> 
> I did not say that.  I said your idea of replacing the release function
> on each _add() is impractical when you have multiple _add() functions.

Sorry, that was what I read into it.

As a note, this would be my proposed fix:

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index ed156a1..302543e 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -141,16 +141,42 @@ void platform_device_put(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(platform_device_put);
 
+static inline platform_object *to_platform_object(struct device *dev)
+{
+	return container_of(dev, struct platform_object, pdev.dev);
+}
+
+static void platform_device_release_all(struct device *dev)
+{
+	struct platform_object *pa = to_platform_object(dev);
+
+	kfree(pa->pdev.dev.platform_data);
+	kfree(pa->pdev.resource);
+	kfree(pa);
+}
+
 static void platform_device_release(struct device *dev)
 {
-	struct platform_object *pa = container_of(dev, struct platform_object,
-						  pdev.dev);
+	kfree(to_platform_object(dev));
+}
+
+static void platform_device_release_pdata(struct device *dev)
+{
+	struct platform_object *pa = to_platform_object(dev);
 
 	kfree(pa->pdev.dev.platform_data);
+	kfree(pa);
+}
+
+static void platform_device_release_res(struct device *dev)
+{
+	struct platform_object *pa = to_platform_object(dev);
+
 	kfree(pa->pdev.resource);
 	kfree(pa);
 }
 
+
 /**
  * platform_device_alloc
  * @name: base name of the device we're adding
@@ -196,6 +222,11 @@ int platform_device_add_resources(struct platform_device *pdev,
 		memcpy(r, res, sizeof(struct resource) * num);
 		pdev->resource = r;
 		pdev->num_resources = num;
+
+		if (pdev->dev.release == platform_device_release)
+			pdev->dev.release = platform_device_release_res;
+		else if (pdev->dev.release ==  platform_device_release_pdata)
+			pdev->dev.release = platform_device_release_all;
 	}
 	return r ? 0 : -ENOMEM;
 }
@@ -218,6 +249,12 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
 
 	if (d) {
 		pdev->dev.platform_data = d;
+
+		if (pdev->dev.release == platform_device_release)
+			pdev->dev.release = platform_device_release_pdata;
+		else if (pdev->dev.release ==  platform_device_release_res)
+			pdev->dev.release = platform_device_release_all;
+
 		return 0;
 	}
 	return -ENOMEM;

 
> > Having a state machine that changed the release call from
> > platform_device_release() to say platform_device_release_resources()
> > or platform_device_release_all() and then platform_device_release_all()
> > may be another way to do it.
> 
> The reason we have platform_device_add_data() is that people think that
> the device data needs to persist for the lifetime of the device.  I
> personally disagree with that - once you unregister the device, it's
> guaranteed that device drivers will have been unregistered, so who's
> going to use the platform data?

That doesn't make any sense, in the current case of using the
platform_device_alloc() and those calls the data is only living
for the lifetime of the device, as the release call is tidying up
the result.

platform_device_add_data() is often being used to create platform data
from some stack based data or similar that isn't guarnateed to live
beyond the liftime of the call that is creating the platform_device
in the first place, let alone getting to the driver stage.

The default release function would be doing the right thing if the
data had been allocated on the fly by one of the subsequent calls
after platform_device_alloc(), but there is no guarantee that these
calls where used to create the data.

The problem comes when we already have the data copied somewhere, such
as from an init-time board that has already done the necessary copying
and this data is then being passed down to sub-drivers of an mfd
device, which use platform_device_alloc() to create a new device.

> So we could just fix it by killing off platform_device_add_data() and
> removing the kfree of the platform data, and ensuring that data marked
> with __initdata either loses that attributation or is kmalloc+copied.

There are a number of places where this data isn't __initdata, and
still needs to be copied, and then freed once the device has been
removed.

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 16:28             ` Ben Dooks
  0 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 03:56:25PM +0000, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2009 at 03:52:31PM +0000, Ben Dooks wrote:
> > On Mon, Nov 02, 2009 at 03:25:00PM +0000, Ben Dooks wrote:
> > > On Mon, Nov 02, 2009 at 03:05:25PM +0000, Russell King - ARM Linux wrote:
> > > > On Mon, Nov 02, 2009 at 03:00:11PM +0000, Ben Dooks wrote:
> > > > > This looks like something is freeing stuff that it did not allocate in
> > > > > the first place, which is IMHO bad. The call platform_device_alloc()
> > > > > is setting platform_device_release() as the default release function
> > > > > but platform_device_release() releases more than platform_device_alloc()
> > > > > actually created.
> > > > > 
> > > > > My view is that platform_device_alloc()'s default release shouldn't
> > > > > be freeing the platform data, and that using platform_device_add_data()
> > > > > or platform_device_add_resources() should change either the behvaiour 
> > > > > of platform_device_release() or it should change the pointer to a new
> > > > > release function.
> > > > 
> > > > That doesn't work - how do those other functions (adding) know what data
> > > > has also been added by other functions?  That can't work reliably.
> > > 
> > > You could wrapper platform device, and each of the add functions could
> > > update it, but that would assume the platform device had been allocated
> > > with platform_device_alloc().
> > 
> > Having had a look, all the current users of platform_device_add_data()
> > are from a platform_alloc_device() created device. 
> > 
> > The number of calls to platform_device_add_resources() are many, but
> > the ones I checked are from platform_alloc_device().
> > 
> > However your point being that these add calls may not be used on a
> > device that has been created from platform_device_alloc() is one I
> > overlooked.
> 
> I did not say that.  I said your idea of replacing the release function
> on each _add() is impractical when you have multiple _add() functions.

Sorry, that was what I read into it.

As a note, this would be my proposed fix:

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index ed156a1..302543e 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -141,16 +141,42 @@ void platform_device_put(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(platform_device_put);
 
+static inline platform_object *to_platform_object(struct device *dev)
+{
+	return container_of(dev, struct platform_object, pdev.dev);
+}
+
+static void platform_device_release_all(struct device *dev)
+{
+	struct platform_object *pa = to_platform_object(dev);
+
+	kfree(pa->pdev.dev.platform_data);
+	kfree(pa->pdev.resource);
+	kfree(pa);
+}
+
 static void platform_device_release(struct device *dev)
 {
-	struct platform_object *pa = container_of(dev, struct platform_object,
-						  pdev.dev);
+	kfree(to_platform_object(dev));
+}
+
+static void platform_device_release_pdata(struct device *dev)
+{
+	struct platform_object *pa = to_platform_object(dev);
 
 	kfree(pa->pdev.dev.platform_data);
+	kfree(pa);
+}
+
+static void platform_device_release_res(struct device *dev)
+{
+	struct platform_object *pa = to_platform_object(dev);
+
 	kfree(pa->pdev.resource);
 	kfree(pa);
 }
 
+
 /**
  * platform_device_alloc
  * @name: base name of the device we're adding
@@ -196,6 +222,11 @@ int platform_device_add_resources(struct platform_device *pdev,
 		memcpy(r, res, sizeof(struct resource) * num);
 		pdev->resource = r;
 		pdev->num_resources = num;
+
+		if (pdev->dev.release == platform_device_release)
+			pdev->dev.release = platform_device_release_res;
+		else if (pdev->dev.release ==  platform_device_release_pdata)
+			pdev->dev.release = platform_device_release_all;
 	}
 	return r ? 0 : -ENOMEM;
 }
@@ -218,6 +249,12 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
 
 	if (d) {
 		pdev->dev.platform_data = d;
+
+		if (pdev->dev.release == platform_device_release)
+			pdev->dev.release = platform_device_release_pdata;
+		else if (pdev->dev.release ==  platform_device_release_res)
+			pdev->dev.release = platform_device_release_all;
+
 		return 0;
 	}
 	return -ENOMEM;

 
> > Having a state machine that changed the release call from
> > platform_device_release() to say platform_device_release_resources()
> > or platform_device_release_all() and then platform_device_release_all()
> > may be another way to do it.
> 
> The reason we have platform_device_add_data() is that people think that
> the device data needs to persist for the lifetime of the device.  I
> personally disagree with that - once you unregister the device, it's
> guaranteed that device drivers will have been unregistered, so who's
> going to use the platform data?

That doesn't make any sense, in the current case of using the
platform_device_alloc() and those calls the data is only living
for the lifetime of the device, as the release call is tidying up
the result.

platform_device_add_data() is often being used to create platform data
from some stack based data or similar that isn't guarnateed to live
beyond the liftime of the call that is creating the platform_device
in the first place, let alone getting to the driver stage.

The default release function would be doing the right thing if the
data had been allocated on the fly by one of the subsequent calls
after platform_device_alloc(), but there is no guarantee that these
calls where used to create the data.

The problem comes when we already have the data copied somewhere, such
as from an init-time board that has already done the necessary copying
and this data is then being passed down to sub-drivers of an mfd
device, which use platform_device_alloc() to create a new device.

> So we could just fix it by killing off platform_device_add_data() and
> removing the kfree of the platform data, and ensuring that data marked
> with __initdata either loses that attributation or is kmalloc+copied.

There are a number of places where this data isn't __initdata, and
still needs to be copied, and then freed once the device has been
removed.

-- 
Ben (ben at fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 16:28             ` Ben Dooks
@ 2009-11-02 16:37               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2009-11-02 16:37 UTC (permalink / raw)
  To: Ben Dooks
  Cc: Antonio Ospite, openezx-devel, Samuel Ortiz, linux-kernel,
	linux-arm-kernel, Mike Rapoport, Daniel Ribeiro

On Mon, Nov 02, 2009 at 04:28:39PM +0000, Ben Dooks wrote:
> On Mon, Nov 02, 2009 at 03:56:25PM +0000, Russell King - ARM Linux wrote:
> > The reason we have platform_device_add_data() is that people think that
> > the device data needs to persist for the lifetime of the device.  I
> > personally disagree with that - once you unregister the device, it's
> > guaranteed that device drivers will have been unregistered, so who's
> > going to use the platform data?
> 
> That doesn't make any sense, in the current case of using the
> platform_device_alloc() and those calls the data is only living
> for the lifetime of the device, as the release call is tidying up
> the result.

What I'm saying is that the lifetime of the data finishes once
the _unregister() call has returned.  So:

	data = pdev->dev.platform_data;
	platform_device_unregister(pdev);
	kfree(data);

is an entirely valid way of handling the "I allocated my platform
data" problem - it doesn't need to exist to the point where the
device itself is freed.

> There are a number of places where this data isn't __initdata, and
> still needs to be copied, and then freed once the device has been
> removed.

What I'm saying is that the point where the platform data can be
freed is the point where the device is unregistered.  It is not the
point where the device is actually freed.

Whenever you have the pointer for the platform device to be unregistered,
you also have the pointer for its data available.

If we accept that the lifetime for the platform data is from the point
the device is registered to the point immediately following when the
device is unregistered, then the above solution is acceptable and
we don't need to play games with release pointers.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 16:37               ` Russell King - ARM Linux
  0 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2009-11-02 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 04:28:39PM +0000, Ben Dooks wrote:
> On Mon, Nov 02, 2009 at 03:56:25PM +0000, Russell King - ARM Linux wrote:
> > The reason we have platform_device_add_data() is that people think that
> > the device data needs to persist for the lifetime of the device.  I
> > personally disagree with that - once you unregister the device, it's
> > guaranteed that device drivers will have been unregistered, so who's
> > going to use the platform data?
> 
> That doesn't make any sense, in the current case of using the
> platform_device_alloc() and those calls the data is only living
> for the lifetime of the device, as the release call is tidying up
> the result.

What I'm saying is that the lifetime of the data finishes once
the _unregister() call has returned.  So:

	data = pdev->dev.platform_data;
	platform_device_unregister(pdev);
	kfree(data);

is an entirely valid way of handling the "I allocated my platform
data" problem - it doesn't need to exist to the point where the
device itself is freed.

> There are a number of places where this data isn't __initdata, and
> still needs to be copied, and then freed once the device has been
> removed.

What I'm saying is that the point where the platform data can be
freed is the point where the device is unregistered.  It is not the
point where the device is actually freed.

Whenever you have the pointer for the platform device to be unregistered,
you also have the pointer for its data available.

If we accept that the lifetime for the platform data is from the point
the device is registered to the point immediately following when the
device is unregistered, then the above solution is acceptable and
we don't need to play games with release pointers.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 16:37               ` Russell King - ARM Linux
@ 2009-11-02 16:47                 ` Ben Dooks
  -1 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 16:47 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Ben Dooks, Antonio Ospite, openezx-devel, Samuel Ortiz,
	linux-kernel, linux-arm-kernel, Mike Rapoport, Daniel Ribeiro

On Mon, Nov 02, 2009 at 04:37:01PM +0000, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2009 at 04:28:39PM +0000, Ben Dooks wrote:
> > On Mon, Nov 02, 2009 at 03:56:25PM +0000, Russell King - ARM Linux wrote:
> > > The reason we have platform_device_add_data() is that people think that
> > > the device data needs to persist for the lifetime of the device.  I
> > > personally disagree with that - once you unregister the device, it's
> > > guaranteed that device drivers will have been unregistered, so who's
> > > going to use the platform data?
> > 
> > That doesn't make any sense, in the current case of using the
> > platform_device_alloc() and those calls the data is only living
> > for the lifetime of the device, as the release call is tidying up
> > the result.
> 
> What I'm saying is that the lifetime of the data finishes once
> the _unregister() call has returned.  So:
> 
> 	data = pdev->dev.platform_data;
> 	platform_device_unregister(pdev);
> 	kfree(data);
> 
> is an entirely valid way of handling the "I allocated my platform
> data" problem - it doesn't need to exist to the point where the
> device itself is freed.

Unforutnately pretty much everyone now assumes that the act of
unregistering the device will get rid of the data that the allocated
by the add functions.

This would mean going around fixing a number of current drivers which
all make that assumption.

-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-02 16:47                 ` Ben Dooks
  0 siblings, 0 replies; 26+ messages in thread
From: Ben Dooks @ 2009-11-02 16:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2009 at 04:37:01PM +0000, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2009 at 04:28:39PM +0000, Ben Dooks wrote:
> > On Mon, Nov 02, 2009 at 03:56:25PM +0000, Russell King - ARM Linux wrote:
> > > The reason we have platform_device_add_data() is that people think that
> > > the device data needs to persist for the lifetime of the device.  I
> > > personally disagree with that - once you unregister the device, it's
> > > guaranteed that device drivers will have been unregistered, so who's
> > > going to use the platform data?
> > 
> > That doesn't make any sense, in the current case of using the
> > platform_device_alloc() and those calls the data is only living
> > for the lifetime of the device, as the release call is tidying up
> > the result.
> 
> What I'm saying is that the lifetime of the data finishes once
> the _unregister() call has returned.  So:
> 
> 	data = pdev->dev.platform_data;
> 	platform_device_unregister(pdev);
> 	kfree(data);
> 
> is an entirely valid way of handling the "I allocated my platform
> data" problem - it doesn't need to exist to the point where the
> device itself is freed.

Unforutnately pretty much everyone now assumes that the act of
unregistering the device will get rid of the data that the allocated
by the add functions.

This would mean going around fixing a number of current drivers which
all make that assumption.

-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 16:47                 ` Ben Dooks
@ 2009-11-03 17:31                   ` Antonio Ospite
  -1 siblings, 0 replies; 26+ messages in thread
From: Antonio Ospite @ 2009-11-03 17:31 UTC (permalink / raw)
  To: Ben Dooks
  Cc: Russell King - ARM Linux, openezx-devel, Samuel Ortiz,
	linux-kernel, linux-arm-kernel, Mike Rapoport, Daniel Ribeiro

[-- Attachment #1: Type: text/plain, Size: 2105 bytes --]

On Mon, 2 Nov 2009 16:47:44 +0000
Ben Dooks <ben-linux@fluff.org> wrote:

> On Mon, Nov 02, 2009 at 04:37:01PM +0000, Russell King - ARM Linux wrote:
> > On Mon, Nov 02, 2009 at 04:28:39PM +0000, Ben Dooks wrote:
> > > On Mon, Nov 02, 2009 at 03:56:25PM +0000, Russell King - ARM Linux wrote:
> > > > The reason we have platform_device_add_data() is that people think that
> > > > the device data needs to persist for the lifetime of the device.  I
> > > > personally disagree with that - once you unregister the device, it's
> > > > guaranteed that device drivers will have been unregistered, so who's
> > > > going to use the platform data?
> > > 
> > > That doesn't make any sense, in the current case of using the
> > > platform_device_alloc() and those calls the data is only living
> > > for the lifetime of the device, as the release call is tidying up
> > > the result.
> > 
> > What I'm saying is that the lifetime of the data finishes once
> > the _unregister() call has returned.  So:
> > 
> > 	data = pdev->dev.platform_data;
> > 	platform_device_unregister(pdev);
> > 	kfree(data);
> > 
> > is an entirely valid way of handling the "I allocated my platform
> > data" problem - it doesn't need to exist to the point where the
> > device itself is freed.
> 
> Unforutnately pretty much everyone now assumes that the act of
> unregistering the device will get rid of the data that the allocated
> by the add functions.
> 
> This would mean going around fixing a number of current drivers which
> all make that assumption.
> 

So those drivers (ezx-pcap.c, da903x.c) aren't doing anything manifestly
wrong by not calling platform_device_add_data(), and the issue will be
solved in ./drivers/base/platform.c someway eventually, right?

Thanks,
   Antonio

-- 
Antonio Ospite
http://ao2.it

PGP public key ID: 0x4553B001

A: Because it messes up the order in which people normally read text.
   See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-03 17:31                   ` Antonio Ospite
  0 siblings, 0 replies; 26+ messages in thread
From: Antonio Ospite @ 2009-11-03 17:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2 Nov 2009 16:47:44 +0000
Ben Dooks <ben-linux@fluff.org> wrote:

> On Mon, Nov 02, 2009 at 04:37:01PM +0000, Russell King - ARM Linux wrote:
> > On Mon, Nov 02, 2009 at 04:28:39PM +0000, Ben Dooks wrote:
> > > On Mon, Nov 02, 2009 at 03:56:25PM +0000, Russell King - ARM Linux wrote:
> > > > The reason we have platform_device_add_data() is that people think that
> > > > the device data needs to persist for the lifetime of the device.  I
> > > > personally disagree with that - once you unregister the device, it's
> > > > guaranteed that device drivers will have been unregistered, so who's
> > > > going to use the platform data?
> > > 
> > > That doesn't make any sense, in the current case of using the
> > > platform_device_alloc() and those calls the data is only living
> > > for the lifetime of the device, as the release call is tidying up
> > > the result.
> > 
> > What I'm saying is that the lifetime of the data finishes once
> > the _unregister() call has returned.  So:
> > 
> > 	data = pdev->dev.platform_data;
> > 	platform_device_unregister(pdev);
> > 	kfree(data);
> > 
> > is an entirely valid way of handling the "I allocated my platform
> > data" problem - it doesn't need to exist to the point where the
> > device itself is freed.
> 
> Unforutnately pretty much everyone now assumes that the act of
> unregistering the device will get rid of the data that the allocated
> by the add functions.
> 
> This would mean going around fixing a number of current drivers which
> all make that assumption.
> 

So those drivers (ezx-pcap.c, da903x.c) aren't doing anything manifestly
wrong by not calling platform_device_add_data(), and the issue will be
solved in ./drivers/base/platform.c someway eventually, right?

Thanks,
   Antonio

-- 
Antonio Ospite
http://ao2.it

PGP public key ID: 0x4553B001

A: Because it messes up the order in which people normally read text.
   See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20091103/014c463b/attachment.sig>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Using statically allocated memory for platform_data.
  2009-11-02 10:23 ` Antonio Ospite
@ 2009-11-08 21:24   ` Antonio Ospite
  -1 siblings, 0 replies; 26+ messages in thread
From: Antonio Ospite @ 2009-11-08 21:24 UTC (permalink / raw)
  To: linux-arm-kernel, openezx-devel, linux-kernel
  Cc: Samuel Ortiz, Daniel Ribeiro, Mike Rapoport,
	Uwe Kleine-König, Ben Dooks, Russell King - ARM Linux

[-- Attachment #1: Type: text/plain, Size: 2730 bytes --]

On Mon, 2 Nov 2009 11:23:16 +0100
Antonio Ospite <ospite@studenti.unina.it> wrote:

> Hi,
> 
> I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
> drivers/mfd/da903x.c) there is code like this:
> 
> static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
>                                      struct pcap_subdev *subdev)
> {
>         struct platform_device *pdev;
> 
>         pdev = platform_device_alloc(subdev->name, subdev->id);
>         pdev->dev.parent = &pcap->spi->dev;
>         pdev->dev.platform_data = subdev->platform_data;
> 
>         return platform_device_add(pdev);
> }
> 
> Note the _direct_assignment_ of platform data; then in board init code
> there are often global struct pointers passed as subdev platform data,
> see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.
> 
> In these cases, whenever the subdev platform device is unregistered,
> the call to platform_device_release() tries to kfree the platform data,
> and being it statically allocated memory this triggers a bug from SLAB:
> 	kernel BUG at mm/slab.c:521!
> In my case this prevented proper device poweroff.
> 
> The question: should these mfd drivers use platform_device_add_data()
> which allocates dynamic memory for *a copy* of platform data? Is this
> simple solution acceptable even if there will be more memory used?
> Or should we setup platform_data in dynamic memory from the beginning
> in board init code? (which would be way less pretty IMHO).
> 

Just for reference, in our local repository I am _temporarily_ working
around the bug with a change like the following, even if I am leaking
some memory. Any comments?

diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index df405af..e4e999b 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -379,12 +379,17 @@ static int pcap_remove_subdev(struct device *dev, void *unused)
        return 0;
 }

+static void pcap_subdev_release(struct device *dev)
+{
+}
+
 static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
                                                struct pcap_subdev *subdev)
 {
        struct platform_device *pdev;

        pdev = platform_device_alloc(subdev->name, subdev->id);
+       pdev->dev.release = pcap_subdev_release;
        pdev->dev.parent = &pcap->spi->dev;
        pdev->dev.platform_data = subdev->platform_data;

-- 
Antonio Ospite
http://ao2.it

PGP public key ID: 0x4553B001

A: Because it messes up the order in which people normally read text.
   See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Using statically allocated memory for platform_data.
@ 2009-11-08 21:24   ` Antonio Ospite
  0 siblings, 0 replies; 26+ messages in thread
From: Antonio Ospite @ 2009-11-08 21:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2 Nov 2009 11:23:16 +0100
Antonio Ospite <ospite@studenti.unina.it> wrote:

> Hi,
> 
> I noted that in some mfd drivers (drivers/mfd/ezx-pcap.c and
> drivers/mfd/da903x.c) there is code like this:
> 
> static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
>                                      struct pcap_subdev *subdev)
> {
>         struct platform_device *pdev;
> 
>         pdev = platform_device_alloc(subdev->name, subdev->id);
>         pdev->dev.parent = &pcap->spi->dev;
>         pdev->dev.platform_data = subdev->platform_data;
> 
>         return platform_device_add(pdev);
> }
> 
> Note the _direct_assignment_ of platform data; then in board init code
> there are often global struct pointers passed as subdev platform data,
> see arch/arm/mach-pxa/em-x270.c::em_x270_da9030_subdevs for instance.
> 
> In these cases, whenever the subdev platform device is unregistered,
> the call to platform_device_release() tries to kfree the platform data,
> and being it statically allocated memory this triggers a bug from SLAB:
> 	kernel BUG at mm/slab.c:521!
> In my case this prevented proper device poweroff.
> 
> The question: should these mfd drivers use platform_device_add_data()
> which allocates dynamic memory for *a copy* of platform data? Is this
> simple solution acceptable even if there will be more memory used?
> Or should we setup platform_data in dynamic memory from the beginning
> in board init code? (which would be way less pretty IMHO).
> 

Just for reference, in our local repository I am _temporarily_ working
around the bug with a change like the following, even if I am leaking
some memory. Any comments?

diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index df405af..e4e999b 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -379,12 +379,17 @@ static int pcap_remove_subdev(struct device *dev, void *unused)
        return 0;
 }

+static void pcap_subdev_release(struct device *dev)
+{
+}
+
 static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
                                                struct pcap_subdev *subdev)
 {
        struct platform_device *pdev;

        pdev = platform_device_alloc(subdev->name, subdev->id);
+       pdev->dev.release = pcap_subdev_release;
        pdev->dev.parent = &pcap->spi->dev;
        pdev->dev.platform_data = subdev->platform_data;

-- 
Antonio Ospite
http://ao2.it

PGP public key ID: 0x4553B001

A: Because it messes up the order in which people normally read text.
   See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20091108/021a9106/attachment-0001.sig>

^ permalink raw reply related	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2009-11-08 21:24 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-02 10:23 Using statically allocated memory for platform_data Antonio Ospite
2009-11-02 10:23 ` Antonio Ospite
2009-11-02 10:39 ` Uwe Kleine-König
2009-11-02 10:39   ` Uwe Kleine-König
2009-11-02 14:51   ` Ben Dooks
2009-11-02 14:51     ` Ben Dooks
2009-11-02 15:00 ` Ben Dooks
2009-11-02 15:00   ` Ben Dooks
2009-11-02 15:05   ` Russell King - ARM Linux
2009-11-02 15:05     ` Russell King - ARM Linux
2009-11-02 15:25     ` Ben Dooks
2009-11-02 15:25       ` Ben Dooks
2009-11-02 15:52       ` Ben Dooks
2009-11-02 15:52         ` Ben Dooks
2009-11-02 15:56         ` Russell King - ARM Linux
2009-11-02 15:56           ` Russell King - ARM Linux
2009-11-02 16:28           ` Ben Dooks
2009-11-02 16:28             ` Ben Dooks
2009-11-02 16:37             ` Russell King - ARM Linux
2009-11-02 16:37               ` Russell King - ARM Linux
2009-11-02 16:47               ` Ben Dooks
2009-11-02 16:47                 ` Ben Dooks
2009-11-03 17:31                 ` Antonio Ospite
2009-11-03 17:31                   ` Antonio Ospite
2009-11-08 21:24 ` Antonio Ospite
2009-11-08 21:24   ` Antonio Ospite

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.