aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/dcdbas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/dcdbas.c')
-rw-r--r--drivers/firmware/dcdbas.c110
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);
530static DCDBAS_DEV_ATTR_RW(host_control_smi_type); 530static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
531static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown); 531static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
532 532
533static struct device_attribute *dcdbas_dev_attrs[] = { 533static 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/** 543static struct attribute_group dcdbas_attr_group = {
544 * dcdbas_init: initialize driver 544 .attrs = dcdbas_dev_attrs,
545 */ 545};
546static int __init dcdbas_init(void) 546
547static 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
585static 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", 597static 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 */
609static 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
593module_init(dcdbas_init); 659module_init(dcdbas_init);