diff options
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r-- | drivers/rtc/interface.c | 97 |
1 files changed, 16 insertions, 81 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index bac1eeb3d312..3d577e259e91 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -607,12 +607,6 @@ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) | |||
607 | rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode); | 607 | rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode); |
608 | spin_unlock_irqrestore(&rtc->irq_lock, flags); | 608 | spin_unlock_irqrestore(&rtc->irq_lock, flags); |
609 | 609 | ||
610 | /* call the task func */ | ||
611 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | ||
612 | if (rtc->irq_task) | ||
613 | rtc->irq_task->func(rtc->irq_task->private_data); | ||
614 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
615 | |||
616 | wake_up_interruptible(&rtc->irq_queue); | 610 | wake_up_interruptible(&rtc->irq_queue); |
617 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); | 611 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); |
618 | } | 612 | } |
@@ -721,39 +715,6 @@ void rtc_class_close(struct rtc_device *rtc) | |||
721 | } | 715 | } |
722 | EXPORT_SYMBOL_GPL(rtc_class_close); | 716 | EXPORT_SYMBOL_GPL(rtc_class_close); |
723 | 717 | ||
724 | int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) | ||
725 | { | ||
726 | int retval = -EBUSY; | ||
727 | |||
728 | if (task == NULL || task->func == NULL) | ||
729 | return -EINVAL; | ||
730 | |||
731 | /* Cannot register while the char dev is in use */ | ||
732 | if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) | ||
733 | return -EBUSY; | ||
734 | |||
735 | spin_lock_irq(&rtc->irq_task_lock); | ||
736 | if (rtc->irq_task == NULL) { | ||
737 | rtc->irq_task = task; | ||
738 | retval = 0; | ||
739 | } | ||
740 | spin_unlock_irq(&rtc->irq_task_lock); | ||
741 | |||
742 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); | ||
743 | |||
744 | return retval; | ||
745 | } | ||
746 | EXPORT_SYMBOL_GPL(rtc_irq_register); | ||
747 | |||
748 | void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) | ||
749 | { | ||
750 | spin_lock_irq(&rtc->irq_task_lock); | ||
751 | if (rtc->irq_task == task) | ||
752 | rtc->irq_task = NULL; | ||
753 | spin_unlock_irq(&rtc->irq_task_lock); | ||
754 | } | ||
755 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); | ||
756 | |||
757 | static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) | 718 | static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) |
758 | { | 719 | { |
759 | /* | 720 | /* |
@@ -785,71 +746,45 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) | |||
785 | * Context: any | 746 | * Context: any |
786 | * | 747 | * |
787 | * Note that rtc_irq_set_freq() should previously have been used to | 748 | * Note that rtc_irq_set_freq() should previously have been used to |
788 | * specify the desired frequency of periodic IRQ task->func() callbacks. | 749 | * specify the desired frequency of periodic IRQ. |
789 | */ | 750 | */ |
790 | int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) | 751 | int rtc_irq_set_state(struct rtc_device *rtc, int enabled) |
791 | { | 752 | { |
792 | int err = 0; | 753 | int err = 0; |
793 | unsigned long flags; | ||
794 | 754 | ||
795 | retry: | 755 | while (rtc_update_hrtimer(rtc, enabled) < 0) |
796 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 756 | cpu_relax(); |
797 | if (rtc->irq_task != NULL && task == NULL) | 757 | |
798 | err = -EBUSY; | 758 | rtc->pie_enabled = enabled; |
799 | else if (rtc->irq_task != task) | ||
800 | err = -EACCES; | ||
801 | else { | ||
802 | if (rtc_update_hrtimer(rtc, enabled) < 0) { | ||
803 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
804 | cpu_relax(); | ||
805 | goto retry; | ||
806 | } | ||
807 | rtc->pie_enabled = enabled; | ||
808 | } | ||
809 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
810 | 759 | ||
811 | trace_rtc_irq_set_state(enabled, err); | 760 | trace_rtc_irq_set_state(enabled, err); |
812 | return err; | 761 | return err; |
813 | } | 762 | } |
814 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); | ||
815 | 763 | ||
816 | /** | 764 | /** |
817 | * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ | 765 | * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ |
818 | * @rtc: the rtc device | 766 | * @rtc: the rtc device |
819 | * @task: currently registered with rtc_irq_register() | 767 | * @task: currently registered with rtc_irq_register() |
820 | * @freq: positive frequency with which task->func() will be called | 768 | * @freq: positive frequency |
821 | * Context: any | 769 | * Context: any |
822 | * | 770 | * |
823 | * Note that rtc_irq_set_state() is used to enable or disable the | 771 | * Note that rtc_irq_set_state() is used to enable or disable the |
824 | * periodic IRQs. | 772 | * periodic IRQs. |
825 | */ | 773 | */ |
826 | int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | 774 | int rtc_irq_set_freq(struct rtc_device *rtc, int freq) |
827 | { | 775 | { |
828 | int err = 0; | 776 | int err = 0; |
829 | unsigned long flags; | ||
830 | 777 | ||
831 | if (freq <= 0 || freq > RTC_MAX_FREQ) | 778 | if (freq <= 0 || freq > RTC_MAX_FREQ) |
832 | return -EINVAL; | 779 | return -EINVAL; |
833 | retry: | 780 | |
834 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 781 | rtc->irq_freq = freq; |
835 | if (rtc->irq_task != NULL && task == NULL) | 782 | while (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) |
836 | err = -EBUSY; | 783 | cpu_relax(); |
837 | else if (rtc->irq_task != task) | ||
838 | err = -EACCES; | ||
839 | else { | ||
840 | rtc->irq_freq = freq; | ||
841 | if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) { | ||
842 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
843 | cpu_relax(); | ||
844 | goto retry; | ||
845 | } | ||
846 | } | ||
847 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
848 | 784 | ||
849 | trace_rtc_irq_set_freq(freq, err); | 785 | trace_rtc_irq_set_freq(freq, err); |
850 | return err; | 786 | return err; |
851 | } | 787 | } |
852 | EXPORT_SYMBOL_GPL(rtc_irq_set_freq); | ||
853 | 788 | ||
854 | /** | 789 | /** |
855 | * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue | 790 | * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue |
@@ -979,8 +914,8 @@ again: | |||
979 | timerqueue_del(&rtc->timerqueue, &timer->node); | 914 | timerqueue_del(&rtc->timerqueue, &timer->node); |
980 | trace_rtc_timer_dequeue(timer); | 915 | trace_rtc_timer_dequeue(timer); |
981 | timer->enabled = 0; | 916 | timer->enabled = 0; |
982 | if (timer->task.func) | 917 | if (timer->func) |
983 | timer->task.func(timer->task.private_data); | 918 | timer->func(timer->private_data); |
984 | 919 | ||
985 | trace_rtc_timer_fired(timer); | 920 | trace_rtc_timer_fired(timer); |
986 | /* Re-add/fwd periodic timers */ | 921 | /* Re-add/fwd periodic timers */ |
@@ -1035,8 +970,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data) | |||
1035 | { | 970 | { |
1036 | timerqueue_init(&timer->node); | 971 | timerqueue_init(&timer->node); |
1037 | timer->enabled = 0; | 972 | timer->enabled = 0; |
1038 | timer->task.func = f; | 973 | timer->func = f; |
1039 | timer->task.private_data = data; | 974 | timer->private_data = data; |
1040 | } | 975 | } |
1041 | 976 | ||
1042 | /* rtc_timer_start - Sets an rtc_timer to fire in the future | 977 | /* rtc_timer_start - Sets an rtc_timer to fire in the future |