| 1 | --- a/compat/Makefile |
| 2 | +++ b/compat/Makefile |
| 3 | @@ -38,3 +38,8 @@ compat-$(CONFIG_COMPAT_KERNEL_3_1) += \ |
| 4 | cordic.o \ |
| 5 | crc8.o |
| 6 | |
| 7 | +ifndef CONFIG_64BIT |
| 8 | +ifndef CONFIG_GENERIC_ATOMIC64 |
| 9 | + compat-y += compat_atomic.o |
| 10 | +endif |
| 11 | +endif |
| 12 | --- a/include/linux/compat-2.6.31.h |
| 13 | +++ b/include/linux/compat-2.6.31.h |
| 14 | @@ -202,6 +202,20 @@ void compat_synchronize_threaded_irq(str |
| 15 | #define skb_walk_frags(skb, iter) \ |
| 16 | for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next) |
| 17 | |
| 18 | +#ifndef CONFIG_64BIT |
| 19 | + |
| 20 | +typedef struct { |
| 21 | + long long counter; |
| 22 | +} atomic64_t; |
| 23 | + |
| 24 | +extern long long atomic64_read(const atomic64_t *v); |
| 25 | +extern long long atomic64_add_return(long long a, atomic64_t *v); |
| 26 | + |
| 27 | +#define atomic64_inc_return(v) atomic64_add_return(1LL, (v)) |
| 28 | + |
| 29 | +#endif |
| 30 | + |
| 31 | + |
| 32 | #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) */ |
| 33 | |
| 34 | #endif /* LINUX_26_31_COMPAT_H */ |
| 35 | --- /dev/null |
| 36 | +++ b/compat/compat_atomic.c |
| 37 | @@ -0,0 +1,33 @@ |
| 38 | +#include <linux/spinlock.h> |
| 39 | +#include <linux/module.h> |
| 40 | + |
| 41 | +#if !defined(CONFIG_X86) && !((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) && defined(CONFIG_ARM) && !defined(CONFIG_GENERIC_ATOMIC64)) |
| 42 | + |
| 43 | +static DEFINE_SPINLOCK(lock); |
| 44 | + |
| 45 | +long long atomic64_read(const atomic64_t *v) |
| 46 | +{ |
| 47 | + unsigned long flags; |
| 48 | + long long val; |
| 49 | + |
| 50 | + spin_lock_irqsave(&lock, flags); |
| 51 | + val = v->counter; |
| 52 | + spin_unlock_irqrestore(&lock, flags); |
| 53 | + return val; |
| 54 | +} |
| 55 | +EXPORT_SYMBOL(atomic64_read); |
| 56 | + |
| 57 | +long long atomic64_add_return(long long a, atomic64_t *v) |
| 58 | +{ |
| 59 | + unsigned long flags; |
| 60 | + long long val; |
| 61 | + |
| 62 | + spin_lock_irqsave(&lock, flags); |
| 63 | + val = v->counter += a; |
| 64 | + spin_unlock_irqrestore(&lock, flags); |
| 65 | + return val; |
| 66 | +} |
| 67 | +EXPORT_SYMBOL(atomic64_add_return); |
| 68 | + |
| 69 | +#endif |
| 70 | + |
| 71 | --- a/include/linux/compat-3.1.h |
| 72 | +++ b/include/linux/compat-3.1.h |
| 73 | @@ -19,6 +19,18 @@ |
| 74 | .prod_id = { NULL, NULL, (v3), NULL }, \ |
| 75 | .prod_id_hash = { 0, 0, (vh3), 0 }, } |
| 76 | |
| 77 | +/* |
| 78 | + * In many versions, several architectures do not seem to include an |
| 79 | + * atomic64_t implementation, and do not include the software emulation from |
| 80 | + * asm-generic/atomic64_t. |
| 81 | + * Detect and handle this here. |
| 82 | + */ |
| 83 | +#include <asm/atomic.h> |
| 84 | + |
| 85 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)) && !defined(ATOMIC64_INIT) && !defined(CONFIG_X86) && !((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) && defined(CONFIG_ARM) && !defined(CONFIG_GENERIC_ATOMIC64)) |
| 86 | +#include <asm-generic/atomic64.h> |
| 87 | +#endif |
| 88 | + |
| 89 | #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)) */ |
| 90 | |
| 91 | #endif /* LINUX_3_1_COMPAT_H */ |
| 92 | |