From 53eb8c82d581fdd4b389a3e417261f3ae924e603 Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Thu, 21 Feb 2013 16:41:31 -0800 Subject: device_cgroup: don't grab mutex in rcu callback Commit 103a197c0c4e ("security/device_cgroup: lock assert fails in dev_exception_clean()") grabs devcgroup_mutex to fix assert failure, but a mutex can't be grabbed in rcu callback. Since there shouldn't be any other references when css_free is called, mutex isn't needed for list cleanup in devcgroup_css_free(). Signed-off-by: Jerry Snitselaar Acked-by: Tejun Heo Acked-by: Aristeu Rozanski Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/security/device_cgroup.c b/security/device_cgroup.c index d794abc..1c69e38 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -159,6 +159,16 @@ static void dev_exception_rm(struct dev_cgroup *dev_cgroup, } } +static void __dev_exception_clean(struct dev_cgroup *dev_cgroup) +{ + struct dev_exception_item *ex, *tmp; + + list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) { + list_del_rcu(&ex->list); + kfree_rcu(ex, rcu); + } +} + /** * dev_exception_clean - frees all entries of the exception list * @dev_cgroup: dev_cgroup with the exception list to be cleaned @@ -167,14 +177,9 @@ static void dev_exception_rm(struct dev_cgroup *dev_cgroup, */ static void dev_exception_clean(struct dev_cgroup *dev_cgroup) { - struct dev_exception_item *ex, *tmp; - lockdep_assert_held(&devcgroup_mutex); - list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) { - list_del_rcu(&ex->list); - kfree_rcu(ex, rcu); - } + __dev_exception_clean(dev_cgroup); } /* @@ -215,9 +220,7 @@ static void devcgroup_css_free(struct cgroup *cgroup) struct dev_cgroup *dev_cgroup; dev_cgroup = cgroup_to_devcgroup(cgroup); - mutex_lock(&devcgroup_mutex); - dev_exception_clean(dev_cgroup); - mutex_unlock(&devcgroup_mutex); + __dev_exception_clean(dev_cgroup); kfree(dev_cgroup); } -- cgit v0.10.2 From 6640dfdf6fff387c0a8f7fb8ac1d47c6b093484e Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:32 -0800 Subject: compiler-gcc4.h: Reorder macros based upon gcc ver This helps to keep the file from getting confusing, removes one duplicate version check and should encourage future editors to put new macros where they belong. Signed-off-by: Daniel Santos Acked-by: David Rientjes Acked-by: Borislav Petkov Cc: Andi Kleen Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 662fd1b..c9785c2 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -13,6 +13,10 @@ #define __must_check __attribute__((warn_unused_result)) #define __compiler_offsetof(a,b) __builtin_offsetof(a,b) +#if __GNUC_MINOR__ > 0 +# define __compiletime_object_size(obj) __builtin_object_size(obj, 0) +#endif + #if __GNUC_MINOR__ >= 3 /* Mark functions as cold. gcc will assume any path leading to a call to them will be unlikely. This means a lot of manual unlikely()s @@ -33,6 +37,12 @@ #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) +#ifndef __CHECKER__ +# define __compiletime_warning(message) __attribute__((warning(message))) +# define __compiletime_error(message) __attribute__((error(message))) +#endif /* __CHECKER__ */ +#endif /* __GNUC_MINOR__ >= 3 */ + #if __GNUC_MINOR__ >= 5 /* * Mark a position in code as unreachable. This can be used to @@ -48,8 +58,7 @@ /* Mark a function definition as prohibited from being cloned. */ #define __noclone __attribute__((__noclone__)) -#endif -#endif +#endif /* __GNUC_MINOR__ >= 5 */ #if __GNUC_MINOR__ >= 6 /* @@ -58,13 +67,6 @@ #define __visible __attribute__((externally_visible)) #endif -#if __GNUC_MINOR__ > 0 -#define __compiletime_object_size(obj) __builtin_object_size(obj, 0) -#endif -#if __GNUC_MINOR__ >= 3 && !defined(__CHECKER__) -#define __compiletime_warning(message) __attribute__((warning(message))) -#define __compiletime_error(message) __attribute__((error(message))) -#endif #ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP #if __GNUC_MINOR__ >= 4 -- cgit v0.10.2 From 3f3f8d2f48acfd8ed3b8e6b7377935da57b27b16 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:39 -0800 Subject: compiler-gcc.h: Add gcc-recommended GCC_VERSION macro Throughout compiler*.h, many version checks are made. These can be simplified by using the macro that gcc's documentation recommends. However, my primary reason for adding this is that I need bug-check macros that are enabled at certain gcc versions and it's cleaner to use this macro than the tradition method: #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ => 2) If you add patch level, it gets this ugly: #if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 2 || \ __GNUC_MINOR__ == 2 __GNUC_PATCHLEVEL__ >= 1)) As opposed to: #if GCC_VERSION >= 40201 While having separate headers for gcc 3 & 4 eliminates some of this verbosity, they can still be cleaned up by this. See also: http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html Signed-off-by: Daniel Santos Acked-by: Borislav Petkov Acked-by: David Rientjes Cc: Andi Kleen Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 6a6d7ae..24545cd 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -5,6 +5,9 @@ /* * Common definitions for all gcc versions go here. */ +#define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) /* Optimization barrier */ -- cgit v0.10.2 From 733ed6e43756b0aec25c9429b810ba74e24c980c Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:41 -0800 Subject: compiler-gcc{3,4}.h: Use GCC_VERSION macro Using GCC_VERSION reduces complexity, is easier to read and is GCC's recommended mechanism for doing version checks. (Just don't ask me why they didn't define it in the first place.) This also makes it easy to merge compiler-gcc{,3,4}.h should somebody want to. Signed-off-by: Daniel Santos Acked-by: David Rientjes Acked-by: Borislav Petkov Cc: Andi Kleen Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h index 37d4124..7d89feb 100644 --- a/include/linux/compiler-gcc3.h +++ b/include/linux/compiler-gcc3.h @@ -2,22 +2,22 @@ #error "Please don't include directly, include instead." #endif -#if __GNUC_MINOR__ < 2 +#if GCC_VERSION < 30200 # error Sorry, your compiler is too old - please upgrade it. #endif -#if __GNUC_MINOR__ >= 3 +#if GCC_VERSION >= 30300 # define __used __attribute__((__used__)) #else # define __used __attribute__((__unused__)) #endif -#if __GNUC_MINOR__ >= 4 +#if GCC_VERSION >= 30400 #define __must_check __attribute__((warn_unused_result)) #endif #ifdef CONFIG_GCOV_KERNEL -# if __GNUC_MINOR__ < 4 +# if GCC_VERSION < 30400 # error "GCOV profiling support for gcc versions below 3.4 not included" # endif /* __GNUC_MINOR__ */ #endif /* CONFIG_GCOV_KERNEL */ diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index c9785c2..a9ffdfe 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -4,7 +4,7 @@ /* GCC 4.1.[01] miscompiles __weak */ #ifdef __KERNEL__ -# if __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ <= 1 +# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101 # error Your version of gcc miscompiles the __weak directive # endif #endif @@ -13,11 +13,11 @@ #define __must_check __attribute__((warn_unused_result)) #define __compiler_offsetof(a,b) __builtin_offsetof(a,b) -#if __GNUC_MINOR__ > 0 +#if GCC_VERSION >= 40100 # define __compiletime_object_size(obj) __builtin_object_size(obj, 0) #endif -#if __GNUC_MINOR__ >= 3 +#if GCC_VERSION >= 40300 /* Mark functions as cold. gcc will assume any path leading to a call to them will be unlikely. This means a lot of manual unlikely()s are unnecessary now for any paths leading to the usual suspects @@ -41,9 +41,9 @@ # define __compiletime_warning(message) __attribute__((warning(message))) # define __compiletime_error(message) __attribute__((error(message))) #endif /* __CHECKER__ */ -#endif /* __GNUC_MINOR__ >= 3 */ +#endif /* GCC_VERSION >= 40300 */ -#if __GNUC_MINOR__ >= 5 +#if GCC_VERSION >= 40500 /* * Mark a position in code as unreachable. This can be used to * suppress control flow warnings after asm blocks that transfer @@ -58,9 +58,9 @@ /* Mark a function definition as prohibited from being cloned. */ #define __noclone __attribute__((__noclone__)) -#endif /* __GNUC_MINOR__ >= 5 */ +#endif /* GCC_VERSION >= 40500 */ -#if __GNUC_MINOR__ >= 6 +#if GCC_VERSION >= 40600 /* * Tell the optimizer that something else uses this function or variable. */ @@ -69,11 +69,11 @@ #ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP -#if __GNUC_MINOR__ >= 4 +#if GCC_VERSION >= 40400 #define __HAVE_BUILTIN_BSWAP32__ #define __HAVE_BUILTIN_BSWAP64__ #endif -#if __GNUC_MINOR__ >= 8 || (defined(__powerpc__) && __GNUC_MINOR__ >= 6) +#if GCC_VERSION >= 40800 || (defined(__powerpc__) && GCC_VERSION >= 40600) #define __HAVE_BUILTIN_BSWAP16__ #endif -#endif +#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ -- cgit v0.10.2 From 6ae8d04871f84d853673e9e9f3f713e77a2fe145 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:42 -0800 Subject: compiler{,-gcc4}.h, bug.h: Remove duplicate macros __linktime_error() does the same thing as __compiletime_error() and is only used in bug.h. Since the macro defines a function attribute that will cause a failure at compile-time (not link-time), it makes more sense to keep __compiletime_error(), which is also neatly mated with __compiletime_warning(). Signed-off-by: Daniel Santos Acked-by: David Rientjes Acked-by: Borislav Petkov Cc: Andi Kleen Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/bug.h b/include/linux/bug.h index b1cf40d..2a11774 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -74,7 +74,7 @@ extern int __build_bug_on_failed; #define BUILD_BUG() \ do { \ extern void __build_bug_failed(void) \ - __linktime_error("BUILD_BUG failed"); \ + __compiletime_error("BUILD_BUG failed");\ __build_bug_failed(); \ } while (0) diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index a9ffdfe..68b162d 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -33,8 +33,6 @@ the kernel context */ #define __cold __attribute__((__cold__)) -#define __linktime_error(message) __attribute__((__error__(message))) - #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) #ifndef __CHECKER__ diff --git a/include/linux/compiler.h b/include/linux/compiler.h index dd852b7..4c638be 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -308,9 +308,6 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #ifndef __compiletime_error # define __compiletime_error(message) #endif -#ifndef __linktime_error -# define __linktime_error(message) -#endif /* * Prevent the compiler from merging or refetching accesses. The compiler * is also forbidden from reordering successive instances of ACCESS_ONCE(), -- cgit v0.10.2 From ca623c914e82c3351cd657073fdb24a1df8c27b9 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:44 -0800 Subject: bug.h: fix BUILD_BUG_ON macro in __CHECKER__ When __CHECKER__ is defined, we disable all of the BUILD_BUG.* macros. However, both BUILD_BUG_ON_NOT_POWER_OF_2 and BUILD_BUG_ON was evaluating to nothing in this case, and we want (0) since this is a function-like macro that will be followed by a semicolon. Signed-off-by: Daniel Santos Acked-by: Borislav Petkov Cc: Andi Kleen Cc: David Rientjes Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/bug.h b/include/linux/bug.h index 2a11774..27d404f 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -12,11 +12,11 @@ enum bug_trap_type { struct pt_regs; #ifdef __CHECKER__ -#define BUILD_BUG_ON_NOT_POWER_OF_2(n) +#define BUILD_BUG_ON_NOT_POWER_OF_2(n) (0) #define BUILD_BUG_ON_ZERO(e) (0) #define BUILD_BUG_ON_NULL(e) ((void*)0) #define BUILD_BUG_ON_INVALID(e) (0) -#define BUILD_BUG_ON(condition) +#define BUILD_BUG_ON(condition) (0) #define BUILD_BUG() (0) #else /* __CHECKER__ */ -- cgit v0.10.2 From 1d6a0d19c85587581a364850b77f30446810a560 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:45 -0800 Subject: bug.h: prevent double evaulation of `condition' in BUILD_BUG_ON When calling BUILD_BUG_ON in an optimized build using gcc 4.3 and later, the condition will be evaulated twice, possibily with side-effects. This patch eliminates that error. [akpm@linux-foundation.org: tweak code layout] Signed-off-by: Daniel Santos Cc: Andi Kleen Cc: Borislav Petkov Cc: David Rientjes Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/bug.h b/include/linux/bug.h index 27d404f..89fb91d 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -59,9 +59,10 @@ struct pt_regs; extern int __build_bug_on_failed; #define BUILD_BUG_ON(condition) \ do { \ - ((void)sizeof(char[1 - 2*!!(condition)])); \ - if (condition) __build_bug_on_failed = 1; \ - } while(0) + bool __cond = !!(condition); \ + ((void)sizeof(char[1 - 2 * __cond])); \ + if (__cond) __build_bug_on_failed = 1; \ + } while (0) #endif /** -- cgit v0.10.2 From a3ccc497cd17147713363a4bf975f1a269fadb6d Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:52 -0800 Subject: bug.h: make BUILD_BUG_ON generate compile-time error Negative sized arrays wont create a compile-time error in some cases starting with gcc 4.4 (e.g., inlined functions), but gcc 4.3 introduced the error function attribute that will. This patch modifies BUILD_BUG_ON to behave like BUILD_BUG already does, using the error function attribute so that you don't have to build the entire kernel to discover that you have a problem, and then enjoy trying to track it down from a link-time error. Also, we are only including asm/bug.h and then expecting that linux/compiler.h will eventually be included to define __linktime_error (used in BUILD_BUG_ON). This patch includes it directly for clarity and to avoid the possibility of changes in /*/include/asm/bug.h being changed or not including linux/compiler.h for some reason. Signed-off-by: Daniel Santos Acked-by: Borislav Petkov Cc: Andi Kleen Cc: David Rientjes Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/bug.h b/include/linux/bug.h index 89fb91d..73af37c 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -2,6 +2,7 @@ #define _LINUX_BUG_H #include +#include enum bug_trap_type { BUG_TRAP_TYPE_NONE = 0, @@ -43,25 +44,30 @@ struct pt_regs; * @condition: the condition which the compiler should know is false. * * If you have some code which relies on certain constants being equal, or - * other compile-time-evaluated condition, you should use BUILD_BUG_ON to + * some other compile-time-evaluated condition, you should use BUILD_BUG_ON to * detect if someone changes it. * - * The implementation uses gcc's reluctance to create a negative array, but - * gcc (as of 4.4) only emits that error for obvious cases (eg. not arguments - * to inline functions). So as a fallback we use the optimizer; if it can't - * prove the condition is false, it will cause a link error on the undefined - * "__build_bug_on_failed". This error message can be harder to track down - * though, hence the two different methods. + * The implementation uses gcc's reluctance to create a negative array, but gcc + * (as of 4.4) only emits that error for obvious cases (e.g. not arguments to + * inline functions). Luckily, in 4.3 they added the "error" function + * attribute just for this type of case. Thus, we use a negative sized array + * (should always create an error on gcc versions older than 4.4) and then call + * an undefined function with the error attribute (should always create an + * error on gcc 4.3 and later). If for some reason, neither creates a + * compile-time error, we'll still have a link-time error, which is harder to + * track down. */ #ifndef __OPTIMIZE__ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) #else -extern int __build_bug_on_failed; -#define BUILD_BUG_ON(condition) \ - do { \ - bool __cond = !!(condition); \ - ((void)sizeof(char[1 - 2 * __cond])); \ - if (__cond) __build_bug_on_failed = 1; \ +#define BUILD_BUG_ON(condition) \ + do { \ + bool __cond = !!(condition); \ + extern void __build_bug_on_failed(void) \ + __compiletime_error("BUILD_BUG_ON failed"); \ + if (__cond) \ + __build_bug_on_failed(); \ + ((void)sizeof(char[1 - 2 * __cond])); \ } while (0) #endif -- cgit v0.10.2 From c361d3e54364d19bb5e803d6e766e94674da7b0e Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:54 -0800 Subject: compiler.h, bug.h: prevent double error messages with BUILD_BUG{,_ON} Prior to the introduction of __attribute__((error("msg"))) in gcc 4.3, creating compile-time errors required a little trickery. BUILD_BUG{,_ON} uses this attribute when available to generate compile-time errors, but also uses the negative-sized array trick for older compilers, resulting in two error messages in some cases. The reason it's "some" cases is that as of gcc 4.4, the negative-sized array will not create an error in some situations, like inline functions. This patch replaces the negative-sized array code with the new __compiletime_error_fallback() macro which expands to the same thing unless the the error attribute is available, in which case it expands to do{}while(0), resulting in exactly one compile-time error on all versions of gcc. Note that we are not changing the negative-sized array code for the unoptimized version of BUILD_BUG_ON, since it has the potential to catch problems that would be disabled in later versions of gcc were __compiletime_error_fallback used. The reason is that that an unoptimized build can't always remove calls to an error-attributed function call (like we are using) that should effectively become dead code if it were optimized. However, using a negative-sized array with a similar value will not result in an false-positive (error). The only caveat being that it will also fail to catch valid conditions, which we should be expecting in an unoptimized build anyway. Signed-off-by: Daniel Santos Cc: Andi Kleen Cc: Borislav Petkov Cc: David Rientjes Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/bug.h b/include/linux/bug.h index 73af37c..dc11dc7 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -67,7 +67,7 @@ struct pt_regs; __compiletime_error("BUILD_BUG_ON failed"); \ if (__cond) \ __build_bug_on_failed(); \ - ((void)sizeof(char[1 - 2 * __cond])); \ + __compiletime_error_fallback(__cond); \ } while (0) #endif diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 4c638be..423bb6b 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -307,7 +307,12 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #endif #ifndef __compiletime_error # define __compiletime_error(message) +# define __compiletime_error_fallback(condition) \ + do { ((void)sizeof(char[1 - 2*!!(condition)])); } while (0) +#else +# define __compiletime_error_fallback(condition) do { } while (0) #endif + /* * Prevent the compiler from merging or refetching accesses. The compiler * is also forbidden from reordering successive instances of ACCESS_ONCE(), -- cgit v0.10.2 From 9a8ab1c39970a4938a72d94e6fd13be88a797590 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Thu, 21 Feb 2013 16:41:55 -0800 Subject: bug.h, compiler.h: introduce compiletime_assert & BUILD_BUG_ON_MSG Introduce compiletime_assert to compiler.h, which moves the details of how to break a build and emit an error message for a specific compiler to the headers where these details should be. Following in the tradition of the POSIX assert macro, compiletime_assert creates a build-time error when the supplied condition is *false*. Next, we add BUILD_BUG_ON_MSG to bug.h which simply wraps compiletime_assert, inverting the logic, so that it fails when the condition is *true*, consistent with the language "build bug on." This macro allows you to specify the error message you want emitted when the supplied condition is true. Finally, we remove all other code from bug.h that mucks with these details (BUILD_BUG & BUILD_BUG_ON), and have them all call BUILD_BUG_ON_MSG. This not only reduces source code bloat, but also prevents the possibility of code being changed for one macro and not for the other (which was previously the case for BUILD_BUG and BUILD_BUG_ON). Since __compiletime_error_fallback is now only used in compiler.h, I'm considering it a private macro and removing the double negation that's now extraneous. [akpm@linux-foundation.org: checkpatch fixes] Signed-off-by: Daniel Santos Cc: Andi Kleen Cc: Borislav Petkov Cc: David Rientjes Cc: Joe Perches Cc: Josh Triplett Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/bug.h b/include/linux/bug.h index dc11dc7..7f48186 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -17,6 +17,7 @@ struct pt_regs; #define BUILD_BUG_ON_ZERO(e) (0) #define BUILD_BUG_ON_NULL(e) ((void*)0) #define BUILD_BUG_ON_INVALID(e) (0) +#define BUILD_BUG_ON_MSG(cond, msg) (0) #define BUILD_BUG_ON(condition) (0) #define BUILD_BUG() (0) #else /* __CHECKER__ */ @@ -40,6 +41,15 @@ struct pt_regs; #define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e)))) /** + * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied + * error message. + * @condition: the condition which the compiler should know is false. + * + * See BUILD_BUG_ON for description. + */ +#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) + +/** * BUILD_BUG_ON - break compile if a condition is true. * @condition: the condition which the compiler should know is false. * @@ -60,15 +70,8 @@ struct pt_regs; #ifndef __OPTIMIZE__ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) #else -#define BUILD_BUG_ON(condition) \ - do { \ - bool __cond = !!(condition); \ - extern void __build_bug_on_failed(void) \ - __compiletime_error("BUILD_BUG_ON failed"); \ - if (__cond) \ - __build_bug_on_failed(); \ - __compiletime_error_fallback(__cond); \ - } while (0) +#define BUILD_BUG_ON(condition) \ + BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) #endif /** @@ -78,12 +81,7 @@ struct pt_regs; * build time, you should use BUILD_BUG to detect if it is * unexpectedly used. */ -#define BUILD_BUG() \ - do { \ - extern void __build_bug_failed(void) \ - __compiletime_error("BUILD_BUG failed");\ - __build_bug_failed(); \ - } while (0) +#define BUILD_BUG() BUILD_BUG_ON_MSG(1, "BUILD_BUG failed") #endif /* __CHECKER__ */ diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 423bb6b..10b8f23 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -308,11 +308,35 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #ifndef __compiletime_error # define __compiletime_error(message) # define __compiletime_error_fallback(condition) \ - do { ((void)sizeof(char[1 - 2*!!(condition)])); } while (0) + do { ((void)sizeof(char[1 - 2 * condition])); } while (0) #else # define __compiletime_error_fallback(condition) do { } while (0) #endif +#define __compiletime_assert(condition, msg, prefix, suffix) \ + do { \ + bool __cond = !(condition); \ + extern void prefix ## suffix(void) __compiletime_error(msg); \ + if (__cond) \ + prefix ## suffix(); \ + __compiletime_error_fallback(__cond); \ + } while (0) + +#define _compiletime_assert(condition, msg, prefix, suffix) \ + __compiletime_assert(condition, msg, prefix, suffix) + +/** + * compiletime_assert - break build and emit msg if condition is false + * @condition: a compile-time constant condition to check + * @msg: a message to emit if condition is false + * + * In tradition of POSIX assert, this macro will break the build if the + * supplied condition is *false*, emitting the supplied error message if the + * compiler has support to do so. + */ +#define compiletime_assert(condition, msg) \ + _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) + /* * Prevent the compiler from merging or refetching accesses. The compiler * is also forbidden from reordering successive instances of ACCESS_ONCE(), -- cgit v0.10.2 From bffea77c08c361d174af7ad94887f6aecc3f340b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 21 Feb 2013 16:41:57 -0800 Subject: compat: return -EFAULT on error in waitid() The copy_to_user() call returns the number of bytes remaining but we want to return -EFAULT on error. Fixes "x32: fix waitid()" Signed-off-by: Dan Carpenter Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/compat.c b/kernel/compat.c index 36700e9..f4bddb9 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -593,7 +593,7 @@ COMPAT_SYSCALL_DEFINE5(waitid, else ret = put_compat_rusage(&ru, uru); if (ret) - return ret; + return -EFAULT; } BUG_ON(info.si_code & __SI_MASK); -- cgit v0.10.2 From 676a0675cf9200ac047fb50825f80867b3bb733b Mon Sep 17 00:00:00 2001 From: Jim Somerville Date: Thu, 21 Feb 2013 16:41:59 -0800 Subject: inotify: remove broken mask checks causing unmount to be EINVAL Running the command: inotifywait -e unmount /mnt/disk immediately aborts with a -EINVAL return code. This is however a valid parameter. This abort occurs only if unmount is the sole event parameter. If other event parameters are supplied, then the unmount event wait will work. The problem was introduced by commit 44b350fc23e ("inotify: Fix mask checks"). In that commit, it states: The mask checks in inotify_update_existing_watch() and inotify_new_watch() are useless because inotify_arg_to_mask() sets FS_IN_IGNORED and FS_EVENT_ON_CHILD bits anyway. But instead of removing the useless checks, it did this: mask = inotify_arg_to_mask(arg); - if (unlikely(!mask)) + if (unlikely(!(mask & IN_ALL_EVENTS))) return -EINVAL; The problem is that IN_ALL_EVENTS doesn't include IN_UNMOUNT, and other parts of the code keep IN_UNMOUNT separate from IN_ALL_EVENTS. So the check should be: if (unlikely(!(mask & (IN_ALL_EVENTS | IN_UNMOUNT)))) But inotify_arg_to_mask(arg) always sets the IN_UNMOUNT bit in the mask anyway, so the check is always going to pass and thus should simply be removed. Also note that inotify_arg_to_mask completely controls what mask bits get set from arg, there's no way for invalid bits to get enabled there. Lets fix it by simply removing the useless broken checks. Signed-off-by: Jim Somerville Signed-off-by: Paul Gortmaker Cc: Jerome Marchand Cc: John McCutchan Cc: Robert Love Cc: Eric Paris Cc: [2.6.37+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 228a2c2..07f7a92 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -576,8 +576,6 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, /* don't allow invalid bits: we don't want flags set */ mask = inotify_arg_to_mask(arg); - if (unlikely(!(mask & IN_ALL_EVENTS))) - return -EINVAL; fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) @@ -629,8 +627,6 @@ static int inotify_new_watch(struct fsnotify_group *group, /* don't allow invalid bits: we don't want flags set */ mask = inotify_arg_to_mask(arg); - if (unlikely(!(mask & IN_ALL_EVENTS))) - return -EINVAL; tmp_i_mark = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL); if (unlikely(!tmp_i_mark)) -- cgit v0.10.2 From 7630b661da330b35dd57b6f5d6d62b386f2dd751 Mon Sep 17 00:00:00 2001 From: MITSUNARI Shigeo Date: Thu, 21 Feb 2013 16:42:01 -0800 Subject: fs/block_dev.c: page cache wrongly left invalidated after revalidate_disk() We found that bdev->bd_invalidated was left set once revalidate_disk() is called, which results in page cache flush every time that device is open. Specifically, we found this problem in MD block device. Once we resize a MD device, mdadm --monitor periodically flush all page cache for that device every 60 or 1000 seconds when it opens the device. This bug lies since at least 3.2.0 till the latest kernel(3.6.2). Patch is attached. The following steps will reproduce the problem. 1. prepair a block device (eg /dev/sdb). 2. create two partitions: sudo parted /dev/sdb mklabel gpt mkpart primary 0% 50% mkpart primary 50% 100% 3. create a md device. sudo mdadm -C /dev/md/hoge -l 1 -n 2 -e 1.2 --assume-clean --auto=md --symlink=no /dev/sdb1 /dev/sdb2 4. create file system and mount it sudo mkfs.ext3 /dev/md/hoge sudo mkdir /mnt/test sudo mount /dev/md/hoge /mnt/test 5. try to resize the device sudo mdadm -G /dev/md/hoge --size=max 6. create a file to fill file cache. sudo dd if=/dev/urandom of=/mnt/test/data bs=1M count=10 and verify the current status of file by free command. 7. mdadm monitor will open the md device every 1000 seconds and you will find all file cache on the device are cleared. The timing can be reduced by the following steps. a) kill mdadm and restart it with --delay option /sbin/mdadm --monitor --delay=30 --pid-file /var/run/mdadm/monitor.pid --daemonise --scan --syslog or open the md device directly. sudo dd if=/dev/md/hoge of=/dev/null bs=4096 count=1 Signed-off-by: MITSUNARI Shigeo Cc: Al Viro Cc: Jeff Moyer Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/block_dev.c b/fs/block_dev.c index 172f849..78333a3 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -994,6 +994,7 @@ int revalidate_disk(struct gendisk *disk) mutex_lock(&bdev->bd_mutex); check_disk_size_change(disk, bdev); + bdev->bd_invalidated = 0; mutex_unlock(&bdev->bd_mutex); bdput(bdev); return ret; -- cgit v0.10.2 From 3b6391834d0aa87a15e2d3997537933cafe185bd Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 21 Feb 2013 16:42:03 -0800 Subject: mn10300: use for_each_pci_dev to simplify the code Signed-off-by: Wei Yongjun Cc: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/mn10300/unit-asb2305/pci-irq.c b/arch/mn10300/unit-asb2305/pci-irq.c index 91212ea..77439da 100644 --- a/arch/mn10300/unit-asb2305/pci-irq.c +++ b/arch/mn10300/unit-asb2305/pci-irq.c @@ -29,7 +29,7 @@ void __init pcibios_fixup_irqs(void) struct pci_dev *dev = NULL; u8 line, pin; - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin) { dev->irq = XIRQ1; -- cgit v0.10.2 From ddfe9b359f8a256e711430c29d7c553b1569faed Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 21 Feb 2013 16:42:04 -0800 Subject: cris: use "int" for ssize_t to match size_t On cris-linux-gcc, __SIZE_TYPE__ expands to "unsigned int", as gcc-4.6.3-nolibc/cris-linux/lib/gcc/cris-linux/4.6.3/plugin/include/config/cris/linux.h has #define SIZE_TYPE "unsigned int" Hence __kernel_size_t is also "unsigned int". But __kernel_ssize_t is "long", which has a different base type, causing compiler warnings like: fs/quota/quota_tree.c:372:4: warning: format '%zd' expects argument of type 'signed size_t', but argument 4 has type 'ssize_t' [-Wformat] To fix this, __kernel_ssize_t should be changed to "int". Hence cris can just use the generic 32-bit versions from include/asm-generic/posix_types.h for all size-related types. Signed-off-by: Geert Uytterhoeven Cc: Mikael Starvik Acked-by: Jesper Nilsson Cc: Hans-Peter Nilsson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/cris/include/uapi/asm/posix_types.h b/arch/cris/include/uapi/asm/posix_types.h index ce4e517..0f22e6a 100644 --- a/arch/cris/include/uapi/asm/posix_types.h +++ b/arch/cris/include/uapi/asm/posix_types.h @@ -22,11 +22,6 @@ typedef unsigned short __kernel_uid_t; typedef unsigned short __kernel_gid_t; #define __kernel_uid_t __kernel_uid_t -typedef __SIZE_TYPE__ __kernel_size_t; -typedef long __kernel_ssize_t; -typedef int __kernel_ptrdiff_t; -#define __kernel_size_t __kernel_size_t - typedef unsigned short __kernel_old_dev_t; #define __kernel_old_dev_t __kernel_old_dev_t -- cgit v0.10.2 From 42b5dd51930c04dc6fb59c7c7a79354ff91bc9a4 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 21 Feb 2013 16:42:06 -0800 Subject: pcmcia: move unbind/rebind into dev_pm_ops.complete Move the device rebind procedures for cardbus devices from the pm.resume into the pm.complete callback. The reason for moving the code is: "[...] The PM code needs to send suspend and resume messages to every device in the right order, and it can't do that if new devices are being added at the same time. [...]" However the situation really isn't quite that rigid. In particular, adding new children during a resume callback shouldn't cause much of problem because the children don't need to be resumed anyway (since they were never suspended). On the other hand, if you do it you will get a dev_warn() from the PM core, something like 'parent should not be sleeping'. Still, it is considered bad form and should be avoided if possible." (Alan Stern's full comment about the topic can be found here: ) Signed-off-by: Christian Lamparter Cc: Dominik Brodowski Cc: Alan Stern Cc: Greg KH Acked-by: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 673c14e..5292db6 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -484,7 +484,7 @@ static int socket_early_resume(struct pcmcia_socket *skt) static int socket_late_resume(struct pcmcia_socket *skt) { - int ret; + int ret = 0; mutex_lock(&skt->ops_mutex); skt->state &= ~SOCKET_SUSPEND; @@ -511,19 +511,31 @@ static int socket_late_resume(struct pcmcia_socket *skt) return socket_insert(skt); } + if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) + ret = skt->callback->early_resume(skt); + return ret; +} + +/* + * Finalize the resume. In case of a cardbus socket, we have + * to rebind the devices as we can't be certain that it has been + * replaced, or not. + */ +static int socket_complete_resume(struct pcmcia_socket *skt) +{ + int ret = 0; #ifdef CONFIG_CARDBUS if (skt->state & SOCKET_CARDBUS) { /* We can't be sure the CardBus card is the same * as the one previously inserted. Therefore, remove * and re-add... */ cb_free(skt); - cb_alloc(skt); - return 0; + ret = cb_alloc(skt); + if (ret) + cb_free(skt); } #endif - if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) - skt->callback->early_resume(skt); - return 0; + return ret; } /* @@ -533,11 +545,15 @@ static int socket_late_resume(struct pcmcia_socket *skt) */ static int socket_resume(struct pcmcia_socket *skt) { + int err; if (!(skt->state & SOCKET_SUSPEND)) return -EBUSY; socket_early_resume(skt); - return socket_late_resume(skt); + err = socket_late_resume(skt); + if (!err) + err = socket_complete_resume(skt); + return err; } static void socket_remove(struct pcmcia_socket *skt) @@ -848,6 +864,12 @@ static int __used pcmcia_socket_dev_resume(struct device *dev) return __pcmcia_pm_op(dev, socket_late_resume); } +static void __used pcmcia_socket_dev_complete(struct device *dev) +{ + WARN(__pcmcia_pm_op(dev, socket_complete_resume), + "failed to complete resume"); +} + static const struct dev_pm_ops pcmcia_socket_pm_ops = { /* dev_resume may be called with IRQs enabled */ SET_SYSTEM_SLEEP_PM_OPS(NULL, @@ -862,6 +884,7 @@ static const struct dev_pm_ops pcmcia_socket_pm_ops = { .resume_noirq = pcmcia_socket_dev_resume_noirq, .thaw_noirq = pcmcia_socket_dev_resume_noirq, .restore_noirq = pcmcia_socket_dev_resume_noirq, + .complete = pcmcia_socket_dev_complete, }; #define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops) -- cgit v0.10.2 From 256fc0e57dc0fce1e698d1be55bedd26f6d6bb5a Mon Sep 17 00:00:00 2001 From: Kamal Mostafa Date: Thu, 21 Feb 2013 16:42:07 -0800 Subject: fbcon: clear the logo bitmap from the margin area Explicitly clear_margins when clearing the logo, in case the font dimensions are non-integral to the framebuffer dimensions. Signed-off-by: Kamal Mostafa Cc: Florian Tobias Schandinat Cc: Tomi Valkeinen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index fdefa8f..f8a61e2 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -1242,8 +1242,16 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, if (!height || !width) return; - if (sy < vc->vc_top && vc->vc_top == logo_lines) + if (sy < vc->vc_top && vc->vc_top == logo_lines) { vc->vc_top = 0; + /* + * If the font dimensions are not an integral of the display + * dimensions then the ops->clear below won't end up clearing + * the margins. Call clear_margins here in case the logo + * bitmap stretched into the margin area. + */ + fbcon_clear_margins(vc, 0); + } /* Split blits that cross physical y_wrap boundary */ -- cgit v0.10.2 From c289ba2d26cf872570ba23fceee8d80ae64be351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Thu, 21 Feb 2013 16:42:09 -0800 Subject: goldfish: framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Framebuffer support for the Goldfish emulator. This takes the Google emulator and applies the x86 cleanups as well as moving the blank methods to the usual Linux place and dropping the Android early suspend logic (for now at least, that can be looked at as Android and upstream converge). Dropped various oddities like setting MTRRs on a virtual frame buffer emulation... With the drivers so far you can now boot a Linux initrd and have fun. [sheng@linux.intel.com: cleaned up to handle x86] [thomas.keel@intel.com: ported to 3.4] [alan@linux.intel.com: cleaned up for style and 3.7, moved blank methods] [akpm@linux-foundation.org: fix (silly) sparse warnings] Signed-off-by: Mike A. Chan Signed-off-by: Arve Hjønnevåg Signed-off-by: Sheng Yang Signed-off-by: Yunhong Jiang Signed-off-by: Xiaohui Xin Signed-off-by: Jun Nakajima Signed-off-by: Bruce Beare Signed-off-by: Tom Keel Signed-off-by: Alan Cox Cc: Florian Tobias Schandinat Cc: Tomi Valkeinen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e7068c5..a913997 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2183,6 +2183,15 @@ config FB_XILINX framebuffer. ML300 carries a 640*480 LCD display on the board, ML403 uses a standard DB15 VGA connector. +config FB_GOLDFISH + tristate "Goldfish Framebuffer" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for Goldfish Virtual Platform + config FB_COBALT tristate "Cobalt server LCD frame buffer support" depends on FB && (MIPS_COBALT || MIPS_SEAD3) diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 768a137..3363f67 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o +obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o obj-$(CONFIG_FB_68328) += 68328fb.o obj-$(CONFIG_FB_GBE) += gbefb.o obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o diff --git a/drivers/video/goldfishfb.c b/drivers/video/goldfishfb.c new file mode 100644 index 0000000..489abb3 --- /dev/null +++ b/drivers/video/goldfishfb.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (C) 2012 Intel, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + FB_GET_WIDTH = 0x00, + FB_GET_HEIGHT = 0x04, + FB_INT_STATUS = 0x08, + FB_INT_ENABLE = 0x0c, + FB_SET_BASE = 0x10, + FB_SET_ROTATION = 0x14, + FB_SET_BLANK = 0x18, + FB_GET_PHYS_WIDTH = 0x1c, + FB_GET_PHYS_HEIGHT = 0x20, + + FB_INT_VSYNC = 1U << 0, + FB_INT_BASE_UPDATE_DONE = 1U << 1 +}; + +struct goldfish_fb { + void __iomem *reg_base; + int irq; + spinlock_t lock; + wait_queue_head_t wait; + int base_update_count; + int rotation; + struct fb_info fb; + u32 cmap[16]; +}; + +static irqreturn_t goldfish_fb_interrupt(int irq, void *dev_id) +{ + unsigned long irq_flags; + struct goldfish_fb *fb = dev_id; + u32 status; + + spin_lock_irqsave(&fb->lock, irq_flags); + status = readl(fb->reg_base + FB_INT_STATUS); + if (status & FB_INT_BASE_UPDATE_DONE) { + fb->base_update_count++; + wake_up(&fb->wait); + } + spin_unlock_irqrestore(&fb->lock, irq_flags); + return status ? IRQ_HANDLED : IRQ_NONE; +} + +static inline u32 convert_bitfield(int val, struct fb_bitfield *bf) +{ + unsigned int mask = (1 << bf->length) - 1; + + return (val >> (16 - bf->length) & mask) << bf->offset; +} + +static int +goldfish_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, + unsigned int blue, unsigned int transp, struct fb_info *info) +{ + struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb); + + if (regno < 16) { + fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) | + convert_bitfield(blue, &fb->fb.var.blue) | + convert_bitfield(green, &fb->fb.var.green) | + convert_bitfield(red, &fb->fb.var.red); + return 0; + } else { + return 1; + } +} + +static int goldfish_fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + if ((var->rotate & 1) != (info->var.rotate & 1)) { + if ((var->xres != info->var.yres) || + (var->yres != info->var.xres) || + (var->xres_virtual != info->var.yres) || + (var->yres_virtual > info->var.xres * 2) || + (var->yres_virtual < info->var.xres)) { + return -EINVAL; + } + } else { + if ((var->xres != info->var.xres) || + (var->yres != info->var.yres) || + (var->xres_virtual != info->var.xres) || + (var->yres_virtual > info->var.yres * 2) || + (var->yres_virtual < info->var.yres)) { + return -EINVAL; + } + } + if ((var->xoffset != info->var.xoffset) || + (var->bits_per_pixel != info->var.bits_per_pixel) || + (var->grayscale != info->var.grayscale)) { + return -EINVAL; + } + return 0; +} + +static int goldfish_fb_set_par(struct fb_info *info) +{ + struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb); + if (fb->rotation != fb->fb.var.rotate) { + info->fix.line_length = info->var.xres * 2; + fb->rotation = fb->fb.var.rotate; + writel(fb->rotation, fb->reg_base + FB_SET_ROTATION); + } + return 0; +} + + +static int goldfish_fb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + unsigned long irq_flags; + int base_update_count; + struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb); + + spin_lock_irqsave(&fb->lock, irq_flags); + base_update_count = fb->base_update_count; + writel(fb->fb.fix.smem_start + fb->fb.var.xres * 2 * var->yoffset, + fb->reg_base + FB_SET_BASE); + spin_unlock_irqrestore(&fb->lock, irq_flags); + wait_event_timeout(fb->wait, + fb->base_update_count != base_update_count, HZ / 15); + if (fb->base_update_count == base_update_count) + pr_err("goldfish_fb_pan_display: timeout wating for base update\n"); + return 0; +} + +static int goldfish_fb_blank(int blank, struct fb_info *info) +{ + struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb); + switch (blank) { + case FB_BLANK_NORMAL: + writel(1, fb->reg_base + FB_SET_BLANK); + break; + case FB_BLANK_UNBLANK: + writel(0, fb->reg_base + FB_SET_BLANK); + break; + } + return 0; +} + +static struct fb_ops goldfish_fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = goldfish_fb_check_var, + .fb_set_par = goldfish_fb_set_par, + .fb_setcolreg = goldfish_fb_setcolreg, + .fb_pan_display = goldfish_fb_pan_display, + .fb_blank = goldfish_fb_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + + +static int goldfish_fb_probe(struct platform_device *pdev) +{ + int ret; + struct resource *r; + struct goldfish_fb *fb; + size_t framesize; + u32 width, height; + dma_addr_t fbpaddr; + + fb = kzalloc(sizeof(*fb), GFP_KERNEL); + if (fb == NULL) { + ret = -ENOMEM; + goto err_fb_alloc_failed; + } + spin_lock_init(&fb->lock); + init_waitqueue_head(&fb->wait); + platform_set_drvdata(pdev, fb); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (r == NULL) { + ret = -ENODEV; + goto err_no_io_base; + } + fb->reg_base = ioremap(r->start, PAGE_SIZE); + if (fb->reg_base == NULL) { + ret = -ENOMEM; + goto err_no_io_base; + } + + fb->irq = platform_get_irq(pdev, 0); + if (fb->irq <= 0) { + ret = -ENODEV; + goto err_no_irq; + } + + width = readl(fb->reg_base + FB_GET_WIDTH); + height = readl(fb->reg_base + FB_GET_HEIGHT); + + fb->fb.fbops = &goldfish_fb_ops; + fb->fb.flags = FBINFO_FLAG_DEFAULT; + fb->fb.pseudo_palette = fb->cmap; + fb->fb.fix.type = FB_TYPE_PACKED_PIXELS; + fb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + fb->fb.fix.line_length = width * 2; + fb->fb.fix.accel = FB_ACCEL_NONE; + fb->fb.fix.ypanstep = 1; + + fb->fb.var.xres = width; + fb->fb.var.yres = height; + fb->fb.var.xres_virtual = width; + fb->fb.var.yres_virtual = height * 2; + fb->fb.var.bits_per_pixel = 16; + fb->fb.var.activate = FB_ACTIVATE_NOW; + fb->fb.var.height = readl(fb->reg_base + FB_GET_PHYS_HEIGHT); + fb->fb.var.width = readl(fb->reg_base + FB_GET_PHYS_WIDTH); + fb->fb.var.pixclock = 10000; + + fb->fb.var.red.offset = 11; + fb->fb.var.red.length = 5; + fb->fb.var.green.offset = 5; + fb->fb.var.green.length = 6; + fb->fb.var.blue.offset = 0; + fb->fb.var.blue.length = 5; + + framesize = width * height * 2 * 2; + fb->fb.screen_base = (char __force __iomem *)dma_alloc_coherent( + &pdev->dev, framesize, + &fbpaddr, GFP_KERNEL); + pr_debug("allocating frame buffer %d * %d, got %p\n", + width, height, fb->fb.screen_base); + if (fb->fb.screen_base == NULL) { + ret = -ENOMEM; + goto err_alloc_screen_base_failed; + } + fb->fb.fix.smem_start = fbpaddr; + fb->fb.fix.smem_len = framesize; + + ret = fb_set_var(&fb->fb, &fb->fb.var); + if (ret) + goto err_fb_set_var_failed; + + ret = request_irq(fb->irq, goldfish_fb_interrupt, IRQF_SHARED, + pdev->name, fb); + if (ret) + goto err_request_irq_failed; + + writel(FB_INT_BASE_UPDATE_DONE, fb->reg_base + FB_INT_ENABLE); + goldfish_fb_pan_display(&fb->fb.var, &fb->fb); /* updates base */ + + ret = register_framebuffer(&fb->fb); + if (ret) + goto err_register_framebuffer_failed; + return 0; + +err_register_framebuffer_failed: + free_irq(fb->irq, fb); +err_request_irq_failed: +err_fb_set_var_failed: + dma_free_coherent(&pdev->dev, framesize, + (void *)fb->fb.screen_base, + fb->fb.fix.smem_start); +err_alloc_screen_base_failed: +err_no_irq: + iounmap(fb->reg_base); +err_no_io_base: + kfree(fb); +err_fb_alloc_failed: + return ret; +} + +static int goldfish_fb_remove(struct platform_device *pdev) +{ + size_t framesize; + struct goldfish_fb *fb = platform_get_drvdata(pdev); + + framesize = fb->fb.var.xres_virtual * fb->fb.var.yres_virtual * 2; + unregister_framebuffer(&fb->fb); + free_irq(fb->irq, fb); + + dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base, + fb->fb.fix.smem_start); + iounmap(fb->reg_base); + return 0; +} + + +static struct platform_driver goldfish_fb_driver = { + .probe = goldfish_fb_probe, + .remove = goldfish_fb_remove, + .driver = { + .name = "goldfish_fb" + } +}; + +module_platform_driver(goldfish_fb_driver); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 59393bb94c103fca48c29348d2415cc67d772045 Mon Sep 17 00:00:00 2001 From: Zhou Zhu Date: Thu, 21 Feb 2013 16:42:11 -0800 Subject: video: mmp display subsystem Add mmp display subsystem to support Marvell MMP display controllers. This subsystem contains 4 parts: --fb folder --core.c --hw folder --panel folder 1. fb folder contains implementation of fb. fb get path and overlay from common interface and operates on these structures. 2. core.c provides common interface for a hardware abstraction. Major parts of this interface are: a) Path: path is a output device connected to a panel or HDMI TV. Main operations of the path is set/get timing/output color. fb operates output device through path structure. b) Ovly: Ovly is a buffer shown on the path. Ovly describes frame buffer and its source/destination size, offset, input color, buffer address, z-order, and so on. Each fb device maps to one overlay. 3. hw folder contains implementation of hardware operations defined by core.c. It registers paths for fb use. 4. panel folder contains implementation of panels. It's connected to path. Panel drivers would also regiester panels and linked to path when probe. Signed-off-by: Zhou Zhu Signed-off-by: Lisa Du Cc: Guoqing Li Acked-by: Haojian Zhuang Cc: Florian Tobias Schandinat Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index a913997..6c2c991 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2431,6 +2431,7 @@ config FB_PUV3_UNIGFX source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" source "drivers/video/exynos/Kconfig" +source "drivers/video/mmp/Kconfig" source "drivers/video/backlight/Kconfig" if VT diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 3363f67..0577f83 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o obj-$(CONFIG_FB_PXA) += pxafb.o obj-$(CONFIG_FB_PXA168) += pxa168fb.o obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o +obj-$(CONFIG_MMP_DISP) += mmp/ obj-$(CONFIG_FB_W100) += w100fb.o obj-$(CONFIG_FB_TMIO) += tmiofb.o obj-$(CONFIG_FB_AU1100) += au1100fb.o diff --git a/drivers/video/mmp/Kconfig b/drivers/video/mmp/Kconfig new file mode 100644 index 0000000..0554336 --- /dev/null +++ b/drivers/video/mmp/Kconfig @@ -0,0 +1,5 @@ +menuconfig MMP_DISP + tristate "Marvell MMP Display Subsystem support" + depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988 + help + Marvell Display Subsystem support. diff --git a/drivers/video/mmp/Makefile b/drivers/video/mmp/Makefile new file mode 100644 index 0000000..820eb10 --- /dev/null +++ b/drivers/video/mmp/Makefile @@ -0,0 +1 @@ +obj-y += core.o diff --git a/drivers/video/mmp/core.c b/drivers/video/mmp/core.c new file mode 100644 index 0000000..9ed8341 --- /dev/null +++ b/drivers/video/mmp/core.c @@ -0,0 +1,258 @@ +/* + * linux/drivers/video/mmp/common.c + * This driver is a common framework for Marvell Display Controller + * + * Copyright (C) 2012 Marvell Technology Group Ltd. + * Authors: Zhou Zhu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + */ + +#include +#include +#include +#include