diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-03-22 03:07:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-22 10:53:56 -0500 |
commit | a7f3ea728b36aff520dff1611b3ce10cff46d8fe (patch) | |
tree | a3bd942d1e2a25529ecae24bdfb16f28a89fddf2 /drivers/firmware | |
parent | d0497614e0bd54f113041966532035edba463f8e (diff) |
[PATCH] dcdbas: convert to the new platform device interface
Do not use platform_device_register_simple() as it is going away, define
dcdbas_driver and implement ->probe() and ->remove() functions so manual
binding and unbinding will work with this driver.
Also switch to using attribute_group when creating sysfs attributes and
make sure to check and handle errors; explicitely remove attributes when
detaching driver.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/dcdbas.c | 110 |
1 files changed, 88 insertions, 22 deletions
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 4652512f7d1a..3a4e5c5b4e1f 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c | |||
@@ -530,30 +530,27 @@ static DCDBAS_DEV_ATTR_RW(host_control_action); | |||
530 | static DCDBAS_DEV_ATTR_RW(host_control_smi_type); | 530 | static DCDBAS_DEV_ATTR_RW(host_control_smi_type); |
531 | static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown); | 531 | static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown); |
532 | 532 | ||
533 | static struct device_attribute *dcdbas_dev_attrs[] = { | 533 | static struct attribute *dcdbas_dev_attrs[] = { |
534 | &dev_attr_smi_data_buf_size, | 534 | &dev_attr_smi_data_buf_size.attr, |
535 | &dev_attr_smi_data_buf_phys_addr, | 535 | &dev_attr_smi_data_buf_phys_addr.attr, |
536 | &dev_attr_smi_request, | 536 | &dev_attr_smi_request.attr, |
537 | &dev_attr_host_control_action, | 537 | &dev_attr_host_control_action.attr, |
538 | &dev_attr_host_control_smi_type, | 538 | &dev_attr_host_control_smi_type.attr, |
539 | &dev_attr_host_control_on_shutdown, | 539 | &dev_attr_host_control_on_shutdown.attr, |
540 | NULL | 540 | NULL |
541 | }; | 541 | }; |
542 | 542 | ||
543 | /** | 543 | static struct attribute_group dcdbas_attr_group = { |
544 | * dcdbas_init: initialize driver | 544 | .attrs = dcdbas_dev_attrs, |
545 | */ | 545 | }; |
546 | static int __init dcdbas_init(void) | 546 | |
547 | static int __devinit dcdbas_probe(struct platform_device *dev) | ||
547 | { | 548 | { |
548 | int i; | 549 | int i, error; |
549 | 550 | ||
550 | host_control_action = HC_ACTION_NONE; | 551 | host_control_action = HC_ACTION_NONE; |
551 | host_control_smi_type = HC_SMITYPE_NONE; | 552 | host_control_smi_type = HC_SMITYPE_NONE; |
552 | 553 | ||
553 | dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | ||
554 | if (IS_ERR(dcdbas_pdev)) | ||
555 | return PTR_ERR(dcdbas_pdev); | ||
556 | |||
557 | /* | 554 | /* |
558 | * BIOS SMI calls require buffer addresses be in 32-bit address space. | 555 | * BIOS SMI calls require buffer addresses be in 32-bit address space. |
559 | * This is done by setting the DMA mask below. | 556 | * This is done by setting the DMA mask below. |
@@ -561,19 +558,79 @@ static int __init dcdbas_init(void) | |||
561 | dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; | 558 | dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; |
562 | dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask; | 559 | dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask; |
563 | 560 | ||
561 | error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group); | ||
562 | if (error) | ||
563 | return error; | ||
564 | |||
565 | for (i = 0; dcdbas_bin_attrs[i]; i++) { | ||
566 | error = sysfs_create_bin_file(&dev->dev.kobj, | ||
567 | dcdbas_bin_attrs[i]); | ||
568 | if (error) { | ||
569 | while (--i >= 0) | ||
570 | sysfs_remove_bin_file(&dev->dev.kobj, | ||
571 | dcdbas_bin_attrs[i]); | ||
572 | sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group); | ||
573 | return error; | ||
574 | } | ||
575 | } | ||
576 | |||
564 | register_reboot_notifier(&dcdbas_reboot_nb); | 577 | register_reboot_notifier(&dcdbas_reboot_nb); |
565 | 578 | ||
579 | dev_info(&dev->dev, "%s (version %s)\n", | ||
580 | DRIVER_DESCRIPTION, DRIVER_VERSION); | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static int __devexit dcdbas_remove(struct platform_device *dev) | ||
586 | { | ||
587 | int i; | ||
588 | |||
589 | unregister_reboot_notifier(&dcdbas_reboot_nb); | ||
566 | for (i = 0; dcdbas_bin_attrs[i]; i++) | 590 | for (i = 0; dcdbas_bin_attrs[i]; i++) |
567 | sysfs_create_bin_file(&dcdbas_pdev->dev.kobj, | 591 | sysfs_remove_bin_file(&dev->dev.kobj, dcdbas_bin_attrs[i]); |
568 | dcdbas_bin_attrs[i]); | 592 | sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group); |
569 | 593 | ||
570 | for (i = 0; dcdbas_dev_attrs[i]; i++) | 594 | return 0; |
571 | device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]); | 595 | } |
572 | 596 | ||
573 | dev_info(&dcdbas_pdev->dev, "%s (version %s)\n", | 597 | static struct platform_driver dcdbas_driver = { |
574 | DRIVER_DESCRIPTION, DRIVER_VERSION); | 598 | .driver = { |
599 | .name = DRIVER_NAME, | ||
600 | .owner = THIS_MODULE, | ||
601 | }, | ||
602 | .probe = dcdbas_probe, | ||
603 | .remove = __devexit_p(dcdbas_remove), | ||
604 | }; | ||
605 | |||
606 | /** | ||
607 | * dcdbas_init: initialize driver | ||
608 | */ | ||
609 | static int __init dcdbas_init(void) | ||
610 | { | ||
611 | int error; | ||
612 | |||
613 | error = platform_driver_register(&dcdbas_driver); | ||
614 | if (error) | ||
615 | return error; | ||
616 | |||
617 | dcdbas_pdev = platform_device_alloc(DRIVER_NAME, -1); | ||
618 | if (!dcdbas_pdev) { | ||
619 | error = -ENOMEM; | ||
620 | goto err_unregister_driver; | ||
621 | } | ||
622 | |||
623 | error = platform_device_add(dcdbas_pdev); | ||
624 | if (error) | ||
625 | goto err_free_device; | ||
575 | 626 | ||
576 | return 0; | 627 | return 0; |
628 | |||
629 | err_free_device: | ||
630 | platform_device_put(dcdbas_pdev); | ||
631 | err_unregister_driver: | ||
632 | platform_driver_unregister(&dcdbas_driver); | ||
633 | return error; | ||
577 | } | 634 | } |
578 | 635 | ||
579 | /** | 636 | /** |
@@ -588,6 +645,15 @@ static void __exit dcdbas_exit(void) | |||
588 | unregister_reboot_notifier(&dcdbas_reboot_nb); | 645 | unregister_reboot_notifier(&dcdbas_reboot_nb); |
589 | smi_data_buf_free(); | 646 | smi_data_buf_free(); |
590 | platform_device_unregister(dcdbas_pdev); | 647 | platform_device_unregister(dcdbas_pdev); |
648 | platform_driver_unregister(&dcdbas_driver); | ||
649 | |||
650 | /* | ||
651 | * We have to free the buffer here instead of dcdbas_remove | ||
652 | * because only in module exit function we can be sure that | ||
653 | * all sysfs attributes belonging to this module have been | ||
654 | * released. | ||
655 | */ | ||
656 | smi_data_buf_free(); | ||
591 | } | 657 | } |
592 | 658 | ||
593 | module_init(dcdbas_init); | 659 | module_init(dcdbas_init); |