diff options
author | Ming Lei <tom.leiming@gmail.com> | 2009-02-06 10:40:12 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-03-24 19:38:25 -0400 |
commit | 7a192ec334cab9fafe3a8665a65af398b0e24730 (patch) | |
tree | eea572863500f94d446cfded69835e188dba3447 /drivers/pcmcia/au1000_generic.c | |
parent | 6da2d377bba06c29d0bc41c8dee014164dec82a7 (diff) |
platform driver: fix incorrect use of 'platform_bus_type' with 'struct device_driver'
This patch fixes the bug reported in
http://bugzilla.kernel.org/show_bug.cgi?id=11681.
"Lots of device drivers register a 'struct device_driver' with
the '.bus' member set to '&platform_bus_type'. This is wrong,
since the platform_bus functions expect the 'struct device_driver'
to be wrapped up in a 'struct platform_driver' which provides
some additional callbacks (like suspend_late, resume_early).
The effect may be that platform_suspend_late() uses bogus data
outside the device_driver struct as a pointer pointer to the
device driver's suspend_late() function or other hard to
reproduce failures."(Lothar Wassmann)
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pcmcia/au1000_generic.c')
-rw-r--r-- | drivers/pcmcia/au1000_generic.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index fc1de46fd20a..90013341cd5f 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c | |||
@@ -468,13 +468,13 @@ out: | |||
468 | return ret; | 468 | return ret; |
469 | } | 469 | } |
470 | 470 | ||
471 | int au1x00_drv_pcmcia_remove(struct device *dev) | 471 | int au1x00_drv_pcmcia_remove(struct platform_device *dev) |
472 | { | 472 | { |
473 | struct skt_dev_info *sinfo = dev_get_drvdata(dev); | 473 | struct skt_dev_info *sinfo = platform_get_drvdata(dev); |
474 | int i; | 474 | int i; |
475 | 475 | ||
476 | mutex_lock(&pcmcia_sockets_lock); | 476 | mutex_lock(&pcmcia_sockets_lock); |
477 | dev_set_drvdata(dev, NULL); | 477 | platform_set_drvdata(dev, NULL); |
478 | 478 | ||
479 | for (i = 0; i < sinfo->nskt; i++) { | 479 | for (i = 0; i < sinfo->nskt; i++) { |
480 | struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i); | 480 | struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i); |
@@ -498,13 +498,13 @@ int au1x00_drv_pcmcia_remove(struct device *dev) | |||
498 | * PCMCIA "Driver" API | 498 | * PCMCIA "Driver" API |
499 | */ | 499 | */ |
500 | 500 | ||
501 | static int au1x00_drv_pcmcia_probe(struct device *dev) | 501 | static int au1x00_drv_pcmcia_probe(struct platform_device *dev) |
502 | { | 502 | { |
503 | int i, ret = -ENODEV; | 503 | int i, ret = -ENODEV; |
504 | 504 | ||
505 | mutex_lock(&pcmcia_sockets_lock); | 505 | mutex_lock(&pcmcia_sockets_lock); |
506 | for (i=0; i < ARRAY_SIZE(au1x00_pcmcia_hw_init); i++) { | 506 | for (i=0; i < ARRAY_SIZE(au1x00_pcmcia_hw_init); i++) { |
507 | ret = au1x00_pcmcia_hw_init[i](dev); | 507 | ret = au1x00_pcmcia_hw_init[i](&dev->dev); |
508 | if (ret == 0) | 508 | if (ret == 0) |
509 | break; | 509 | break; |
510 | } | 510 | } |
@@ -512,14 +512,26 @@ static int au1x00_drv_pcmcia_probe(struct device *dev) | |||
512 | return ret; | 512 | return ret; |
513 | } | 513 | } |
514 | 514 | ||
515 | static int au1x00_drv_pcmcia_suspend(struct platform_device *dev, | ||
516 | pm_message_t state) | ||
517 | { | ||
518 | return pcmcia_socket_dev_suspend(&dev->dev, state); | ||
519 | } | ||
520 | |||
521 | static int au1x00_drv_pcmcia_resume(struct platform_device *dev) | ||
522 | { | ||
523 | return pcmcia_socket_dev_resume(&dev->dev); | ||
524 | } | ||
515 | 525 | ||
516 | static struct device_driver au1x00_pcmcia_driver = { | 526 | static struct platform_driver au1x00_pcmcia_driver = { |
527 | .driver = { | ||
528 | .name = "au1x00-pcmcia", | ||
529 | .owner = THIS_MODULE, | ||
530 | }, | ||
517 | .probe = au1x00_drv_pcmcia_probe, | 531 | .probe = au1x00_drv_pcmcia_probe, |
518 | .remove = au1x00_drv_pcmcia_remove, | 532 | .remove = au1x00_drv_pcmcia_remove, |
519 | .name = "au1x00-pcmcia", | 533 | .suspend = au1x00_drv_pcmcia_suspend, |
520 | .bus = &platform_bus_type, | 534 | .resume = au1x00_drv_pcmcia_resume, |
521 | .suspend = pcmcia_socket_dev_suspend, | ||
522 | .resume = pcmcia_socket_dev_resume, | ||
523 | }; | 535 | }; |
524 | 536 | ||
525 | 537 | ||
@@ -533,8 +545,7 @@ static struct device_driver au1x00_pcmcia_driver = { | |||
533 | static int __init au1x00_pcmcia_init(void) | 545 | static int __init au1x00_pcmcia_init(void) |
534 | { | 546 | { |
535 | int error = 0; | 547 | int error = 0; |
536 | if ((error = driver_register(&au1x00_pcmcia_driver))) | 548 | error = platform_driver_register(&au1x00_pcmcia_driver); |
537 | return error; | ||
538 | return error; | 549 | return error; |
539 | } | 550 | } |
540 | 551 | ||
@@ -544,7 +555,7 @@ static int __init au1x00_pcmcia_init(void) | |||
544 | */ | 555 | */ |
545 | static void __exit au1x00_pcmcia_exit(void) | 556 | static void __exit au1x00_pcmcia_exit(void) |
546 | { | 557 | { |
547 | driver_unregister(&au1x00_pcmcia_driver); | 558 | platform_driver_unregister(&au1x00_pcmcia_driver); |
548 | } | 559 | } |
549 | 560 | ||
550 | module_init(au1x00_pcmcia_init); | 561 | module_init(au1x00_pcmcia_init); |