From: Hans de Goede Date: Thu, 19 Oct 2017 11:16:19 +0000 (+0200) Subject: x86/platform/intel/iosf_mbi: Add unlocked PMIC bus access notifier unregister X-Git-Tag: v4.16-rc1~31^2~35^2~83 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=af0ab55ffe2467fab82bc0909e469cba7701fac7;p=uclinux-h8%2Flinux.git x86/platform/intel/iosf_mbi: Add unlocked PMIC bus access notifier unregister For race free unregistration drivers may need to acquire PMIC bus access through iosf_mbi_punit_acquire() and then (un)register the notifier without dropping the lock. This commit adds an unlocked variant of iosf_mbi_unregister_pmic_bus_access_notifier for this use case. Acked-by: Ingo Molnar Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20171019111620.26761-2-hdegoede@redhat.com --- diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h index c313cac36f56..eb959cd77994 100644 --- a/arch/x86/include/asm/iosf_mbi.h +++ b/arch/x86/include/asm/iosf_mbi.h @@ -146,6 +146,18 @@ int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb); int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb); /** + * iosf_mbi_unregister_pmic_bus_access_notifier_unlocked - Unregister PMIC bus + * notifier, unlocked + * + * Like iosf_mbi_unregister_pmic_bus_access_notifier(), but for use when the + * caller has already called iosf_mbi_punit_acquire() itself. + * + * @nb: notifier_block to unregister + */ +int iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( + struct notifier_block *nb); + +/** * iosf_mbi_call_pmic_bus_access_notifier_chain - Call PMIC bus notifier chain * * @val: action to pass into listener's notifier_call function @@ -153,6 +165,11 @@ int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb); */ int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v); +/** + * iosf_mbi_assert_punit_acquired - Assert that the P-Unit has been acquired. + */ +void iosf_mbi_assert_punit_acquired(void); + #else /* CONFIG_IOSF_MBI is not enabled */ static inline bool iosf_mbi_available(void) @@ -196,12 +213,20 @@ int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb) return 0; } +static inline int +iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(struct notifier_block *nb) +{ + return 0; +} + static inline int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v) { return 0; } +static inline void iosf_mbi_assert_punit_acquired(void) {} + #endif /* CONFIG_IOSF_MBI */ #endif /* IOSF_MBI_SYMS_H */ diff --git a/arch/x86/platform/intel/iosf_mbi.c b/arch/x86/platform/intel/iosf_mbi.c index a952ac199741..6f37a2137a79 100644 --- a/arch/x86/platform/intel/iosf_mbi.c +++ b/arch/x86/platform/intel/iosf_mbi.c @@ -218,14 +218,23 @@ int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(iosf_mbi_register_pmic_bus_access_notifier); +int iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( + struct notifier_block *nb) +{ + iosf_mbi_assert_punit_acquired(); + + return blocking_notifier_chain_unregister( + &iosf_mbi_pmic_bus_access_notifier, nb); +} +EXPORT_SYMBOL(iosf_mbi_unregister_pmic_bus_access_notifier_unlocked); + int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb) { int ret; /* Wait for the bus to go inactive before unregistering */ mutex_lock(&iosf_mbi_punit_mutex); - ret = blocking_notifier_chain_unregister( - &iosf_mbi_pmic_bus_access_notifier, nb); + ret = iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(nb); mutex_unlock(&iosf_mbi_punit_mutex); return ret; @@ -239,6 +248,12 @@ int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v) } EXPORT_SYMBOL(iosf_mbi_call_pmic_bus_access_notifier_chain); +void iosf_mbi_assert_punit_acquired(void) +{ + WARN_ON(!mutex_is_locked(&iosf_mbi_punit_mutex)); +} +EXPORT_SYMBOL(iosf_mbi_assert_punit_acquired); + #ifdef CONFIG_IOSF_MBI_DEBUG static u32 dbg_mdr; static u32 dbg_mcr;