Loading drivers/platform/msm/ipa/ipa_rm_inactivity_timer.c +35 −22 Original line number Original line Diff line number Diff line /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -28,8 +28,10 @@ * @resource_name - resource name * @resource_name - resource name * @work: delayed work object for running delayed releas * @work: delayed work object for running delayed releas * function * function * @release_in_prog: boolean flag indicates if release resource * @resource_requested: boolean flag indicates if resource was requested * is scheduled for happen in the future. * @reschedule_work: boolean flag indicates to not release and to * reschedule the release work. * @work_in_progress: boolean flag indicates is release work was scheduled. * @jiffies: number of jiffies for timeout * @jiffies: number of jiffies for timeout * * * WWAN private - holds all relevant info about WWAN driver * WWAN private - holds all relevant info about WWAN driver Loading @@ -39,7 +41,9 @@ struct ipa_rm_it_private { enum ipa_rm_resource_name resource_name; enum ipa_rm_resource_name resource_name; spinlock_t lock; spinlock_t lock; struct delayed_work work; struct delayed_work work; bool release_in_prog; bool resource_requested; bool reschedule_work; bool work_in_progress; unsigned long jiffies; unsigned long jiffies; }; }; Loading @@ -47,13 +51,11 @@ static struct ipa_rm_it_private ipa_rm_it_handles[IPA_RM_RESOURCE_MAX]; /** /** * ipa_rm_inactivity_timer_func() - called when timer expired in * ipa_rm_inactivity_timer_func() - called when timer expired in * the context of the shared workqueue. Checks internally is * the context of the shared workqueue. Checks internally if * release_in_prog flag is set and calls to * reschedule_work flag is set. In case it is not set this function calls to * ipa_rm_release_resource(). release_in_prog is cleared when * ipa_rm_release_resource(). In case reschedule_work is set this function * calling to ipa_rm_inactivity_timer_request_resource(). In * reschedule the work. This flag is cleared cleared when * this situation this function shall not call to * calling to ipa_rm_inactivity_timer_release_resource(). * ipa_rm_release_resource() since the resource needs to remain * up * * * @work: work object provided by the work queue * @work: work object provided by the work queue * * Loading @@ -71,14 +73,22 @@ static void ipa_rm_inactivity_timer_func(struct work_struct *work) IPADBG("%s: timer expired for resource %d!\n", __func__, IPADBG("%s: timer expired for resource %d!\n", __func__, me->resource_name); me->resource_name); /* check that release still need to be performed */ spin_lock_irqsave( spin_lock_irqsave( &ipa_rm_it_handles[me->resource_name].lock, flags); &ipa_rm_it_handles[me->resource_name].lock, flags); if (ipa_rm_it_handles[me->resource_name].release_in_prog) { if (ipa_rm_it_handles[me->resource_name].reschedule_work) { IPADBG("%s: setting delayed work\n", __func__); ipa_rm_it_handles[me->resource_name].reschedule_work = false; schedule_delayed_work( &ipa_rm_it_handles[me->resource_name].work, ipa_rm_it_handles[me->resource_name].jiffies); } else if (ipa_rm_it_handles[me->resource_name].resource_requested) { IPADBG("%s: not calling release\n", __func__); ipa_rm_it_handles[me->resource_name].work_in_progress = false; } else { IPADBG("%s: calling release_resource on resource %d!\n", IPADBG("%s: calling release_resource on resource %d!\n", __func__, me->resource_name); __func__, me->resource_name); ipa_rm_release_resource(me->resource_name); ipa_rm_release_resource(me->resource_name); ipa_rm_it_handles[me->resource_name].release_in_prog = false; ipa_rm_it_handles[me->resource_name].work_in_progress = false; } } spin_unlock_irqrestore( spin_unlock_irqrestore( &ipa_rm_it_handles[me->resource_name].lock, flags); &ipa_rm_it_handles[me->resource_name].lock, flags); Loading Loading @@ -117,7 +127,9 @@ int ipa_rm_inactivity_timer_init(enum ipa_rm_resource_name resource_name, spin_lock_init(&ipa_rm_it_handles[resource_name].lock); spin_lock_init(&ipa_rm_it_handles[resource_name].lock); ipa_rm_it_handles[resource_name].resource_name = resource_name; ipa_rm_it_handles[resource_name].resource_name = resource_name; ipa_rm_it_handles[resource_name].jiffies = msecs_to_jiffies(msecs); ipa_rm_it_handles[resource_name].jiffies = msecs_to_jiffies(msecs); ipa_rm_it_handles[resource_name].release_in_prog = false; ipa_rm_it_handles[resource_name].resource_requested = false; ipa_rm_it_handles[resource_name].reschedule_work = false; ipa_rm_it_handles[resource_name].work_in_progress = false; INIT_DELAYED_WORK(&ipa_rm_it_handles[resource_name].work, INIT_DELAYED_WORK(&ipa_rm_it_handles[resource_name].work, ipa_rm_inactivity_timer_func); ipa_rm_inactivity_timer_func); Loading Loading @@ -193,8 +205,7 @@ int ipa_rm_inactivity_timer_request_resource( } } spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags); spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags); cancel_delayed_work(&ipa_rm_it_handles[resource_name].work); ipa_rm_it_handles[resource_name].resource_requested = true; ipa_rm_it_handles[resource_name].release_in_prog = false; spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags); spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags); ret = ipa_rm_request_resource(resource_name); ret = ipa_rm_request_resource(resource_name); IPADBG("%s: resource %d: returning %d\n", __func__, resource_name, ret); IPADBG("%s: resource %d: returning %d\n", __func__, resource_name, ret); Loading Loading @@ -235,19 +246,21 @@ int ipa_rm_inactivity_timer_release_resource( } } spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags); spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags); if (ipa_rm_it_handles[resource_name].release_in_prog) { ipa_rm_it_handles[resource_name].resource_requested = false; if (ipa_rm_it_handles[resource_name].work_in_progress) { IPADBG("%s: Timer already set, not scheduling again %d\n", IPADBG("%s: Timer already set, not scheduling again %d\n", __func__, resource_name); __func__, resource_name); ipa_rm_it_handles[resource_name].reschedule_work = true; spin_unlock_irqrestore( spin_unlock_irqrestore( &ipa_rm_it_handles[resource_name].lock, flags); &ipa_rm_it_handles[resource_name].lock, flags); return 0; return 0; } } ipa_rm_it_handles[resource_name].release_in_prog = true; ipa_rm_it_handles[resource_name].work_in_progress = true; spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags); ipa_rm_it_handles[resource_name].reschedule_work = false; IPADBG("%s: setting delayed work\n", __func__); IPADBG("%s: setting delayed work\n", __func__); schedule_delayed_work(&ipa_rm_it_handles[resource_name].work, schedule_delayed_work(&ipa_rm_it_handles[resource_name].work, ipa_rm_it_handles[resource_name].jiffies); ipa_rm_it_handles[resource_name].jiffies); spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags); return 0; return 0; } } Loading Loading
drivers/platform/msm/ipa/ipa_rm_inactivity_timer.c +35 −22 Original line number Original line Diff line number Diff line /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -28,8 +28,10 @@ * @resource_name - resource name * @resource_name - resource name * @work: delayed work object for running delayed releas * @work: delayed work object for running delayed releas * function * function * @release_in_prog: boolean flag indicates if release resource * @resource_requested: boolean flag indicates if resource was requested * is scheduled for happen in the future. * @reschedule_work: boolean flag indicates to not release and to * reschedule the release work. * @work_in_progress: boolean flag indicates is release work was scheduled. * @jiffies: number of jiffies for timeout * @jiffies: number of jiffies for timeout * * * WWAN private - holds all relevant info about WWAN driver * WWAN private - holds all relevant info about WWAN driver Loading @@ -39,7 +41,9 @@ struct ipa_rm_it_private { enum ipa_rm_resource_name resource_name; enum ipa_rm_resource_name resource_name; spinlock_t lock; spinlock_t lock; struct delayed_work work; struct delayed_work work; bool release_in_prog; bool resource_requested; bool reschedule_work; bool work_in_progress; unsigned long jiffies; unsigned long jiffies; }; }; Loading @@ -47,13 +51,11 @@ static struct ipa_rm_it_private ipa_rm_it_handles[IPA_RM_RESOURCE_MAX]; /** /** * ipa_rm_inactivity_timer_func() - called when timer expired in * ipa_rm_inactivity_timer_func() - called when timer expired in * the context of the shared workqueue. Checks internally is * the context of the shared workqueue. Checks internally if * release_in_prog flag is set and calls to * reschedule_work flag is set. In case it is not set this function calls to * ipa_rm_release_resource(). release_in_prog is cleared when * ipa_rm_release_resource(). In case reschedule_work is set this function * calling to ipa_rm_inactivity_timer_request_resource(). In * reschedule the work. This flag is cleared cleared when * this situation this function shall not call to * calling to ipa_rm_inactivity_timer_release_resource(). * ipa_rm_release_resource() since the resource needs to remain * up * * * @work: work object provided by the work queue * @work: work object provided by the work queue * * Loading @@ -71,14 +73,22 @@ static void ipa_rm_inactivity_timer_func(struct work_struct *work) IPADBG("%s: timer expired for resource %d!\n", __func__, IPADBG("%s: timer expired for resource %d!\n", __func__, me->resource_name); me->resource_name); /* check that release still need to be performed */ spin_lock_irqsave( spin_lock_irqsave( &ipa_rm_it_handles[me->resource_name].lock, flags); &ipa_rm_it_handles[me->resource_name].lock, flags); if (ipa_rm_it_handles[me->resource_name].release_in_prog) { if (ipa_rm_it_handles[me->resource_name].reschedule_work) { IPADBG("%s: setting delayed work\n", __func__); ipa_rm_it_handles[me->resource_name].reschedule_work = false; schedule_delayed_work( &ipa_rm_it_handles[me->resource_name].work, ipa_rm_it_handles[me->resource_name].jiffies); } else if (ipa_rm_it_handles[me->resource_name].resource_requested) { IPADBG("%s: not calling release\n", __func__); ipa_rm_it_handles[me->resource_name].work_in_progress = false; } else { IPADBG("%s: calling release_resource on resource %d!\n", IPADBG("%s: calling release_resource on resource %d!\n", __func__, me->resource_name); __func__, me->resource_name); ipa_rm_release_resource(me->resource_name); ipa_rm_release_resource(me->resource_name); ipa_rm_it_handles[me->resource_name].release_in_prog = false; ipa_rm_it_handles[me->resource_name].work_in_progress = false; } } spin_unlock_irqrestore( spin_unlock_irqrestore( &ipa_rm_it_handles[me->resource_name].lock, flags); &ipa_rm_it_handles[me->resource_name].lock, flags); Loading Loading @@ -117,7 +127,9 @@ int ipa_rm_inactivity_timer_init(enum ipa_rm_resource_name resource_name, spin_lock_init(&ipa_rm_it_handles[resource_name].lock); spin_lock_init(&ipa_rm_it_handles[resource_name].lock); ipa_rm_it_handles[resource_name].resource_name = resource_name; ipa_rm_it_handles[resource_name].resource_name = resource_name; ipa_rm_it_handles[resource_name].jiffies = msecs_to_jiffies(msecs); ipa_rm_it_handles[resource_name].jiffies = msecs_to_jiffies(msecs); ipa_rm_it_handles[resource_name].release_in_prog = false; ipa_rm_it_handles[resource_name].resource_requested = false; ipa_rm_it_handles[resource_name].reschedule_work = false; ipa_rm_it_handles[resource_name].work_in_progress = false; INIT_DELAYED_WORK(&ipa_rm_it_handles[resource_name].work, INIT_DELAYED_WORK(&ipa_rm_it_handles[resource_name].work, ipa_rm_inactivity_timer_func); ipa_rm_inactivity_timer_func); Loading Loading @@ -193,8 +205,7 @@ int ipa_rm_inactivity_timer_request_resource( } } spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags); spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags); cancel_delayed_work(&ipa_rm_it_handles[resource_name].work); ipa_rm_it_handles[resource_name].resource_requested = true; ipa_rm_it_handles[resource_name].release_in_prog = false; spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags); spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags); ret = ipa_rm_request_resource(resource_name); ret = ipa_rm_request_resource(resource_name); IPADBG("%s: resource %d: returning %d\n", __func__, resource_name, ret); IPADBG("%s: resource %d: returning %d\n", __func__, resource_name, ret); Loading Loading @@ -235,19 +246,21 @@ int ipa_rm_inactivity_timer_release_resource( } } spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags); spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags); if (ipa_rm_it_handles[resource_name].release_in_prog) { ipa_rm_it_handles[resource_name].resource_requested = false; if (ipa_rm_it_handles[resource_name].work_in_progress) { IPADBG("%s: Timer already set, not scheduling again %d\n", IPADBG("%s: Timer already set, not scheduling again %d\n", __func__, resource_name); __func__, resource_name); ipa_rm_it_handles[resource_name].reschedule_work = true; spin_unlock_irqrestore( spin_unlock_irqrestore( &ipa_rm_it_handles[resource_name].lock, flags); &ipa_rm_it_handles[resource_name].lock, flags); return 0; return 0; } } ipa_rm_it_handles[resource_name].release_in_prog = true; ipa_rm_it_handles[resource_name].work_in_progress = true; spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags); ipa_rm_it_handles[resource_name].reschedule_work = false; IPADBG("%s: setting delayed work\n", __func__); IPADBG("%s: setting delayed work\n", __func__); schedule_delayed_work(&ipa_rm_it_handles[resource_name].work, schedule_delayed_work(&ipa_rm_it_handles[resource_name].work, ipa_rm_it_handles[resource_name].jiffies); ipa_rm_it_handles[resource_name].jiffies); spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags); return 0; return 0; } } Loading