diff options
author | Roland Stigge <stigge@antcom.de> | 2012-02-08 15:41:05 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-02-09 19:00:33 -0500 |
commit | 93d199a13a6fb8db05d851a1afa8bf938a307be4 (patch) | |
tree | 7d6a2351696d1ca2b5622bebda64d6bb84f2fe76 /arch/arm/mach-lpc32xx | |
parent | 9862048abfe5fbd134553a8de30cf8767291fb1f (diff) |
ARM: LPC32xx: clock.c: Fix mutex lock issues
This patch fixes the mutex issue in clock.c, as done in Kevin Wells' original
driver update:
In some cases, the clock drivers could grab a mutex twice in an improper
context. This patch changes the mutex mechanism to a simple irq lock/unlock
mechanism and removes un-needed locks from some functions.
(See also git.lpclinux.com)
Signed-off-by: Roland Stigge <stigge@antcom.de>
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Kevin Wells <kevin.wells@nxp.com>
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-lpc32xx')
-rw-r--r-- | arch/arm/mach-lpc32xx/clock.c | 41 |
1 files changed, 11 insertions, 30 deletions
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 39dcbd0e68b2..fef863062a5e 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c | |||
@@ -97,9 +97,10 @@ | |||
97 | #include "clock.h" | 97 | #include "clock.h" |
98 | #include "common.h" | 98 | #include "common.h" |
99 | 99 | ||
100 | static DEFINE_SPINLOCK(global_clkregs_lock); | ||
101 | |||
100 | static struct clk clk_armpll; | 102 | static struct clk clk_armpll; |
101 | static struct clk clk_usbpll; | 103 | static struct clk clk_usbpll; |
102 | static DEFINE_MUTEX(clkm_lock); | ||
103 | 104 | ||
104 | /* | 105 | /* |
105 | * Post divider values for PLLs based on selected register value | 106 | * Post divider values for PLLs based on selected register value |
@@ -891,16 +892,6 @@ static struct clk clk_lcd = { | |||
891 | .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, | 892 | .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, |
892 | }; | 893 | }; |
893 | 894 | ||
894 | static inline void clk_lock(void) | ||
895 | { | ||
896 | mutex_lock(&clkm_lock); | ||
897 | } | ||
898 | |||
899 | static inline void clk_unlock(void) | ||
900 | { | ||
901 | mutex_unlock(&clkm_lock); | ||
902 | } | ||
903 | |||
904 | static void local_clk_disable(struct clk *clk) | 895 | static void local_clk_disable(struct clk *clk) |
905 | { | 896 | { |
906 | /* Don't attempt to disable clock if it has no users */ | 897 | /* Don't attempt to disable clock if it has no users */ |
@@ -945,10 +936,11 @@ static int local_clk_enable(struct clk *clk) | |||
945 | int clk_enable(struct clk *clk) | 936 | int clk_enable(struct clk *clk) |
946 | { | 937 | { |
947 | int ret; | 938 | int ret; |
939 | unsigned long flags; | ||
948 | 940 | ||
949 | clk_lock(); | 941 | spin_lock_irqsave(&global_clkregs_lock, flags); |
950 | ret = local_clk_enable(clk); | 942 | ret = local_clk_enable(clk); |
951 | clk_unlock(); | 943 | spin_unlock_irqrestore(&global_clkregs_lock, flags); |
952 | 944 | ||
953 | return ret; | 945 | return ret; |
954 | } | 946 | } |
@@ -959,9 +951,11 @@ EXPORT_SYMBOL(clk_enable); | |||
959 | */ | 951 | */ |
960 | void clk_disable(struct clk *clk) | 952 | void clk_disable(struct clk *clk) |
961 | { | 953 | { |
962 | clk_lock(); | 954 | unsigned long flags; |
955 | |||
956 | spin_lock_irqsave(&global_clkregs_lock, flags); | ||
963 | local_clk_disable(clk); | 957 | local_clk_disable(clk); |
964 | clk_unlock(); | 958 | spin_unlock_irqrestore(&global_clkregs_lock, flags); |
965 | } | 959 | } |
966 | EXPORT_SYMBOL(clk_disable); | 960 | EXPORT_SYMBOL(clk_disable); |
967 | 961 | ||
@@ -970,13 +964,7 @@ EXPORT_SYMBOL(clk_disable); | |||
970 | */ | 964 | */ |
971 | unsigned long clk_get_rate(struct clk *clk) | 965 | unsigned long clk_get_rate(struct clk *clk) |
972 | { | 966 | { |
973 | unsigned long rate; | 967 | return clk->get_rate(clk); |
974 | |||
975 | clk_lock(); | ||
976 | rate = clk->get_rate(clk); | ||
977 | clk_unlock(); | ||
978 | |||
979 | return rate; | ||
980 | } | 968 | } |
981 | EXPORT_SYMBOL(clk_get_rate); | 969 | EXPORT_SYMBOL(clk_get_rate); |
982 | 970 | ||
@@ -992,11 +980,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
992 | * the actual rate set as part of the peripheral dividers | 980 | * the actual rate set as part of the peripheral dividers |
993 | * instead of high level clock control | 981 | * instead of high level clock control |
994 | */ | 982 | */ |
995 | if (clk->set_rate) { | 983 | if (clk->set_rate) |
996 | clk_lock(); | ||
997 | ret = clk->set_rate(clk, rate); | 984 | ret = clk->set_rate(clk, rate); |
998 | clk_unlock(); | ||
999 | } | ||
1000 | 985 | ||
1001 | return ret; | 986 | return ret; |
1002 | } | 987 | } |
@@ -1007,15 +992,11 @@ EXPORT_SYMBOL(clk_set_rate); | |||
1007 | */ | 992 | */ |
1008 | long clk_round_rate(struct clk *clk, unsigned long rate) | 993 | long clk_round_rate(struct clk *clk, unsigned long rate) |
1009 | { | 994 | { |
1010 | clk_lock(); | ||
1011 | |||
1012 | if (clk->round_rate) | 995 | if (clk->round_rate) |
1013 | rate = clk->round_rate(clk, rate); | 996 | rate = clk->round_rate(clk, rate); |
1014 | else | 997 | else |
1015 | rate = clk->get_rate(clk); | 998 | rate = clk->get_rate(clk); |
1016 | 999 | ||
1017 | clk_unlock(); | ||
1018 | |||
1019 | return rate; | 1000 | return rate; |
1020 | } | 1001 | } |
1021 | EXPORT_SYMBOL(clk_round_rate); | 1002 | EXPORT_SYMBOL(clk_round_rate); |