From eb97933e2a4ea7d0002571eb780d73c339daa9db Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Wed, 26 Sep 2012 12:54:01 +0000
Subject: [PATCH] backport the upstream entropy changes (#11951)

SVN-Revision: 33559
---
 .../patches-3.3/050-rng_git_backport.patch    | 783 ++++++++++++++++++
 ...t_backport-remove_irqf_sample_random.patch | 543 ++++++++++++
 .../patches-3.3/941-ocf_20120127.patch        |  16 +-
 3 files changed, 1334 insertions(+), 8 deletions(-)
 create mode 100644 target/linux/generic/patches-3.3/050-rng_git_backport.patch
 create mode 100644 target/linux/generic/patches-3.3/051-rng_git_backport-remove_irqf_sample_random.patch

diff --git a/target/linux/generic/patches-3.3/050-rng_git_backport.patch b/target/linux/generic/patches-3.3/050-rng_git_backport.patch
new file mode 100644
index 0000000000..825eb73a43
--- /dev/null
+++ b/target/linux/generic/patches-3.3/050-rng_git_backport.patch
@@ -0,0 +1,783 @@
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -125,21 +125,26 @@
+  * The current exported interfaces for gathering environmental noise
+  * from the devices are:
+  *
++ *	void add_device_randomness(const void *buf, unsigned int size);
+  * 	void add_input_randomness(unsigned int type, unsigned int code,
+  *                                unsigned int value);
+- * 	void add_interrupt_randomness(int irq);
++ *	void add_interrupt_randomness(int irq, int irq_flags);
+  * 	void add_disk_randomness(struct gendisk *disk);
+  *
+  * add_input_randomness() uses the input layer interrupt timing, as well as
+  * the event type information from the hardware.
+  *
+- * add_interrupt_randomness() uses the inter-interrupt timing as random
+- * inputs to the entropy pool.  Note that not all interrupts are good
+- * sources of randomness!  For example, the timer interrupts is not a
+- * good choice, because the periodicity of the interrupts is too
+- * regular, and hence predictable to an attacker.  Network Interface
+- * Controller interrupts are a better measure, since the timing of the
+- * NIC interrupts are more unpredictable.
++ * add_interrupt_randomness() uses the interrupt timing as random
++ * inputs to the entropy pool. Using the cycle counters and the irq source
++ * as inputs, it feeds the randomness roughly once a second.
++ *
++ * add_device_randomness() is for adding data to the random pool that
++ * is likely to differ between two devices (or possibly even per boot).
++ * This would be things like MAC addresses or serial numbers, or the
++ * read-out of the RTC. This does *not* add any actual entropy to the
++ * pool, but it initializes the pool to different values for devices
++ * that might otherwise be identical and have very little entropy
++ * available to them (particularly common in the embedded world).
+  *
+  * add_disk_randomness() uses what amounts to the seek time of block
+  * layer request events, on a per-disk_devt basis, as input to the
+@@ -248,6 +253,7 @@
+ #include <linux/percpu.h>
+ #include <linux/cryptohash.h>
+ #include <linux/fips.h>
++#include <linux/ptrace.h>
+ 
+ #ifdef CONFIG_GENERIC_HARDIRQS
+ # include <linux/irq.h>
+@@ -256,8 +262,12 @@
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/irq.h>
++#include <asm/irq_regs.h>
+ #include <asm/io.h>
+ 
++#define CREATE_TRACE_POINTS
++#include <trace/events/random.h>
++
+ /*
+  * Configuration information
+  */
+@@ -420,8 +430,10 @@ struct entropy_store {
+ 	/* read-write data: */
+ 	spinlock_t lock;
+ 	unsigned add_ptr;
++	unsigned input_rotate;
+ 	int entropy_count;
+-	int input_rotate;
++	int entropy_total;
++	unsigned int initialized:1;
+ 	__u8 last_data[EXTRACT_SIZE];
+ };
+ 
+@@ -454,6 +466,10 @@ static struct entropy_store nonblocking_
+ 	.pool = nonblocking_pool_data
+ };
+ 
++static __u32 const twist_table[8] = {
++	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
++	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
++
+ /*
+  * This function adds bytes into the entropy "pool".  It does not
+  * update the entropy estimate.  The caller should call
+@@ -464,29 +480,24 @@ static struct entropy_store nonblocking_
+  * it's cheap to do so and helps slightly in the expected case where
+  * the entropy is concentrated in the low-order bits.
+  */
+-static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
+-				   int nbytes, __u8 out[64])
++static void _mix_pool_bytes(struct entropy_store *r, const void *in,
++			    int nbytes, __u8 out[64])
+ {
+-	static __u32 const twist_table[8] = {
+-		0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+-		0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+ 	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
+ 	int input_rotate;
+ 	int wordmask = r->poolinfo->poolwords - 1;
+ 	const char *bytes = in;
+ 	__u32 w;
+-	unsigned long flags;
+ 
+-	/* Taps are constant, so we can load them without holding r->lock.  */
+ 	tap1 = r->poolinfo->tap1;
+ 	tap2 = r->poolinfo->tap2;
+ 	tap3 = r->poolinfo->tap3;
+ 	tap4 = r->poolinfo->tap4;
+ 	tap5 = r->poolinfo->tap5;
+ 
+-	spin_lock_irqsave(&r->lock, flags);
+-	input_rotate = r->input_rotate;
+-	i = r->add_ptr;
++	smp_rmb();
++	input_rotate = ACCESS_ONCE(r->input_rotate);
++	i = ACCESS_ONCE(r->add_ptr);
+ 
+ 	/* mix one byte at a time to simplify size handling and churn faster */
+ 	while (nbytes--) {
+@@ -513,19 +524,61 @@ static void mix_pool_bytes_extract(struc
+ 		input_rotate += i ? 7 : 14;
+ 	}
+ 
+-	r->input_rotate = input_rotate;
+-	r->add_ptr = i;
++	ACCESS_ONCE(r->input_rotate) = input_rotate;
++	ACCESS_ONCE(r->add_ptr) = i;
++	smp_wmb();
+ 
+ 	if (out)
+ 		for (j = 0; j < 16; j++)
+ 			((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
++}
++
++static void __mix_pool_bytes(struct entropy_store *r, const void *in,
++			     int nbytes, __u8 out[64])
++{
++	trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
++	_mix_pool_bytes(r, in, nbytes, out);
++}
+ 
++static void mix_pool_bytes(struct entropy_store *r, const void *in,
++			   int nbytes, __u8 out[64])
++{
++	unsigned long flags;
++
++	trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
++	spin_lock_irqsave(&r->lock, flags);
++	_mix_pool_bytes(r, in, nbytes, out);
+ 	spin_unlock_irqrestore(&r->lock, flags);
+ }
+ 
+-static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
++struct fast_pool {
++	__u32		pool[4];
++	unsigned long	last;
++	unsigned short	count;
++	unsigned char	rotate;
++	unsigned char	last_timer_intr;
++};
++
++/*
++ * This is a fast mixing routine used by the interrupt randomness
++ * collector.  It's hardcoded for an 128 bit pool and assumes that any
++ * locks that might be needed are taken by the caller.
++ */
++static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
+ {
+-       mix_pool_bytes_extract(r, in, bytes, NULL);
++	const char	*bytes = in;
++	__u32		w;
++	unsigned	i = f->count;
++	unsigned	input_rotate = f->rotate;
++
++	while (nbytes--) {
++		w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
++			f->pool[(i + 1) & 3];
++		f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
++		input_rotate += (i++ & 3) ? 7 : 14;
++	}
++	f->count = i;
++	f->rotate = input_rotate;
+ }
+ 
+ /*
+@@ -533,30 +586,38 @@ static void mix_pool_bytes(struct entrop
+  */
+ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ {
+-	unsigned long flags;
+-	int entropy_count;
++	int entropy_count, orig;
+ 
+ 	if (!nbits)
+ 		return;
+ 
+-	spin_lock_irqsave(&r->lock, flags);
+-
+ 	DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
+-	entropy_count = r->entropy_count;
++retry:
++	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
+ 	entropy_count += nbits;
++
+ 	if (entropy_count < 0) {
+ 		DEBUG_ENT("negative entropy/overflow\n");
+ 		entropy_count = 0;
+ 	} else if (entropy_count > r->poolinfo->POOLBITS)
+ 		entropy_count = r->poolinfo->POOLBITS;
+-	r->entropy_count = entropy_count;
++	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
++		goto retry;
++
++	if (!r->initialized && nbits > 0) {
++		r->entropy_total += nbits;
++		if (r->entropy_total > 128)
++			r->initialized = 1;
++	}
++
++	trace_credit_entropy_bits(r->name, nbits, entropy_count,
++				  r->entropy_total, _RET_IP_);
+ 
+ 	/* should we wake readers? */
+ 	if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
+ 		wake_up_interruptible(&random_read_wait);
+ 		kill_fasync(&fasync, SIGIO, POLL_IN);
+ 	}
+-	spin_unlock_irqrestore(&r->lock, flags);
+ }
+ 
+ /*********************************************************************
+@@ -609,6 +670,25 @@ static void set_timer_rand_state(unsigne
+ }
+ #endif
+ 
++/*
++ * Add device- or boot-specific data to the input and nonblocking
++ * pools to help initialize them to unique values.
++ *
++ * None of this adds any entropy, it is meant to avoid the
++ * problem of the nonblocking pool having similar initial state
++ * across largely identical devices.
++ */
++void add_device_randomness(const void *buf, unsigned int size)
++{
++	unsigned long time = get_cycles() ^ jiffies;
++
++	mix_pool_bytes(&input_pool, buf, size, NULL);
++	mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
++	mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
++	mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
++}
++EXPORT_SYMBOL(add_device_randomness);
++
+ static struct timer_rand_state input_timer_state;
+ 
+ /*
+@@ -637,13 +717,9 @@ static void add_timer_randomness(struct
+ 		goto out;
+ 
+ 	sample.jiffies = jiffies;
+-
+-	/* Use arch random value, fall back to cycles */
+-	if (!arch_get_random_int(&sample.cycles))
+-		sample.cycles = get_cycles();
+-
++	sample.cycles = get_cycles();
+ 	sample.num = num;
+-	mix_pool_bytes(&input_pool, &sample, sizeof(sample));
++	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
+ 
+ 	/*
+ 	 * Calculate number of bits of randomness we probably added.
+@@ -700,17 +776,48 @@ void add_input_randomness(unsigned int t
+ }
+ EXPORT_SYMBOL_GPL(add_input_randomness);
+ 
+-void add_interrupt_randomness(int irq)
++static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
++
++void add_interrupt_randomness(int irq, int irq_flags)
+ {
+-	struct timer_rand_state *state;
++	struct entropy_store	*r;
++	struct fast_pool	*fast_pool = &__get_cpu_var(irq_randomness);
++	struct pt_regs		*regs = get_irq_regs();
++	unsigned long		now = jiffies;
++	__u32			input[4], cycles = get_cycles();
++
++	input[0] = cycles ^ jiffies;
++	input[1] = irq;
++	if (regs) {
++		__u64 ip = instruction_pointer(regs);
++		input[2] = ip;
++		input[3] = ip >> 32;
++	}
+ 
+-	state = get_timer_rand_state(irq);
++	fast_mix(fast_pool, input, sizeof(input));
+ 
+-	if (state == NULL)
++	if ((fast_pool->count & 1023) &&
++	    !time_after(now, fast_pool->last + HZ))
+ 		return;
+ 
+-	DEBUG_ENT("irq event %d\n", irq);
+-	add_timer_randomness(state, 0x100 + irq);
++	fast_pool->last = now;
++
++	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
++	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
++	/*
++	 * If we don't have a valid cycle counter, and we see
++	 * back-to-back timer interrupts, then skip giving credit for
++	 * any entropy.
++	 */
++	if (cycles == 0) {
++		if (irq_flags & __IRQF_TIMER) {
++			if (fast_pool->last_timer_intr)
++				return;
++			fast_pool->last_timer_intr = 1;
++		} else
++			fast_pool->last_timer_intr = 0;
++	}
++	credit_entropy_bits(r, 1);
+ }
+ 
+ #ifdef CONFIG_BLOCK
+@@ -742,7 +849,11 @@ static ssize_t extract_entropy(struct en
+  */
+ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ {
+-	__u32 tmp[OUTPUT_POOL_WORDS];
++	union {
++		__u32	tmp[OUTPUT_POOL_WORDS];
++		long	hwrand[4];
++	} u;
++	int	i;
+ 
+ 	if (r->pull && r->entropy_count < nbytes * 8 &&
+ 	    r->entropy_count < r->poolinfo->POOLBITS) {
+@@ -753,17 +864,22 @@ static void xfer_secondary_pool(struct e
+ 		/* pull at least as many as BYTES as wakeup BITS */
+ 		bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
+ 		/* but never more than the buffer size */
+-		bytes = min_t(int, bytes, sizeof(tmp));
++		bytes = min_t(int, bytes, sizeof(u.tmp));
+ 
+ 		DEBUG_ENT("going to reseed %s with %d bits "
+ 			  "(%d of %d requested)\n",
+ 			  r->name, bytes * 8, nbytes * 8, r->entropy_count);
+ 
+-		bytes = extract_entropy(r->pull, tmp, bytes,
++		bytes = extract_entropy(r->pull, u.tmp, bytes,
+ 					random_read_wakeup_thresh / 8, rsvd);
+-		mix_pool_bytes(r, tmp, bytes);
++		mix_pool_bytes(r, u.tmp, bytes, NULL);
+ 		credit_entropy_bits(r, bytes*8);
+ 	}
++	for (i = 0; i < 4; i++)
++		if (arch_get_random_long(&u.hwrand[i]))
++			break;
++	if (i)
++		mix_pool_bytes(r, &u.hwrand, i * sizeof(u.hwrand[0]), 0);
+ }
+ 
+ /*
+@@ -822,9 +938,11 @@ static void extract_buf(struct entropy_s
+ 	int i;
+ 	__u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
+ 	__u8 extract[64];
++	unsigned long flags;
+ 
+ 	/* Generate a hash across the pool, 16 words (512 bits) at a time */
+ 	sha_init(hash);
++	spin_lock_irqsave(&r->lock, flags);
+ 	for (i = 0; i < r->poolinfo->poolwords; i += 16)
+ 		sha_transform(hash, (__u8 *)(r->pool + i), workspace);
+ 
+@@ -837,7 +955,8 @@ static void extract_buf(struct entropy_s
+ 	 * brute-forcing the feedback as hard as brute-forcing the
+ 	 * hash.
+ 	 */
+-	mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
++	__mix_pool_bytes(r, hash, sizeof(hash), extract);
++	spin_unlock_irqrestore(&r->lock, flags);
+ 
+ 	/*
+ 	 * To avoid duplicates, we atomically extract a portion of the
+@@ -860,12 +979,12 @@ static void extract_buf(struct entropy_s
+ }
+ 
+ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+-			       size_t nbytes, int min, int reserved)
++				 size_t nbytes, int min, int reserved)
+ {
+ 	ssize_t ret = 0, i;
+ 	__u8 tmp[EXTRACT_SIZE];
+-	unsigned long flags;
+ 
++	trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, min, reserved);
+ 
+@@ -873,6 +992,8 @@ static ssize_t extract_entropy(struct en
+ 		extract_buf(r, tmp);
+ 
+ 		if (fips_enabled) {
++			unsigned long flags;
++
+ 			spin_lock_irqsave(&r->lock, flags);
+ 			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
+ 				panic("Hardware RNG duplicated output!\n");
+@@ -898,6 +1019,7 @@ static ssize_t extract_entropy_user(stru
+ 	ssize_t ret = 0, i;
+ 	__u8 tmp[EXTRACT_SIZE];
+ 
++	trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, 0, 0);
+ 
+@@ -931,17 +1053,35 @@ static ssize_t extract_entropy_user(stru
+ 
+ /*
+  * This function is the exported kernel interface.  It returns some
+- * number of good random numbers, suitable for seeding TCP sequence
+- * numbers, etc.
++ * number of good random numbers, suitable for key generation, seeding
++ * TCP sequence numbers, etc.  It does not use the hw random number
++ * generator, if available; use get_random_bytes_arch() for that.
+  */
+ void get_random_bytes(void *buf, int nbytes)
+ {
++	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
++}
++EXPORT_SYMBOL(get_random_bytes);
++
++/*
++ * This function will use the architecture-specific hardware random
++ * number generator if it is available.  The arch-specific hw RNG will
++ * almost certainly be faster than what we can do in software, but it
++ * is impossible to verify that it is implemented securely (as
++ * opposed, to, say, the AES encryption of a sequence number using a
++ * key known by the NSA).  So it's useful if we need the speed, but
++ * only if we're willing to trust the hardware manufacturer not to
++ * have put in a back door.
++ */
++void get_random_bytes_arch(void *buf, int nbytes)
++{
+ 	char *p = buf;
+ 
++	trace_get_random_bytes(nbytes, _RET_IP_);
+ 	while (nbytes) {
+ 		unsigned long v;
+ 		int chunk = min(nbytes, (int)sizeof(unsigned long));
+-		
++
+ 		if (!arch_get_random_long(&v))
+ 			break;
+ 		
+@@ -950,9 +1090,11 @@ void get_random_bytes(void *buf, int nby
+ 		nbytes -= chunk;
+ 	}
+ 
+-	extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
++	if (nbytes)
++		extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
+ }
+-EXPORT_SYMBOL(get_random_bytes);
++EXPORT_SYMBOL(get_random_bytes_arch);
++
+ 
+ /*
+  * init_std_data - initialize pool with system data
+@@ -966,21 +1108,18 @@ EXPORT_SYMBOL(get_random_bytes);
+ static void init_std_data(struct entropy_store *r)
+ {
+ 	int i;
+-	ktime_t now;
+-	unsigned long flags;
++	ktime_t now = ktime_get_real();
++	unsigned long rv;
+ 
+-	spin_lock_irqsave(&r->lock, flags);
+ 	r->entropy_count = 0;
+-	spin_unlock_irqrestore(&r->lock, flags);
+-
+-	now = ktime_get_real();
+-	mix_pool_bytes(r, &now, sizeof(now));
+-	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) {
+-		if (!arch_get_random_long(&flags))
++	r->entropy_total = 0;
++	mix_pool_bytes(r, &now, sizeof(now), NULL);
++	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
++		if (!arch_get_random_long(&rv))
+ 			break;
+-		mix_pool_bytes(r, &flags, sizeof(flags));
++		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
+ 	}
+-	mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
++	mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
+ }
+ 
+ static int rand_initialize(void)
+@@ -1117,7 +1256,7 @@ write_pool(struct entropy_store *r, cons
+ 		count -= bytes;
+ 		p += bytes;
+ 
+-		mix_pool_bytes(r, buf, bytes);
++		mix_pool_bytes(r, buf, bytes, NULL);
+ 		cond_resched();
+ 	}
+ 
+@@ -1274,6 +1413,7 @@ static int proc_do_uuid(ctl_table *table
+ }
+ 
+ static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
++extern ctl_table random_table[];
+ ctl_table random_table[] = {
+ 	{
+ 		.procname	= "poolsize",
+@@ -1339,7 +1479,7 @@ late_initcall(random_int_secret_init);
+  * value is not cryptographically secure but for several uses the cost of
+  * depleting entropy is too high
+  */
+-DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
++static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
+ unsigned int get_random_int(void)
+ {
+ 	__u32 *hash;
+--- a/drivers/mfd/ab3100-core.c
++++ b/drivers/mfd/ab3100-core.c
+@@ -409,8 +409,6 @@ static irqreturn_t ab3100_irq_handler(in
+ 	u32 fatevent;
+ 	int err;
+ 
+-	add_interrupt_randomness(irq);
+-
+ 	err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
+ 				       event_regs, 3);
+ 	if (err)
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -24,6 +24,7 @@
+ #include <linux/kthread.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/random.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+@@ -1896,6 +1897,14 @@ int usb_new_device(struct usb_device *ud
+ 	/* Tell the world! */
+ 	announce_device(udev);
+ 
++	if (udev->serial)
++		add_device_randomness(udev->serial, strlen(udev->serial));
++	if (udev->product)
++		add_device_randomness(udev->product, strlen(udev->product));
++	if (udev->manufacturer)
++		add_device_randomness(udev->manufacturer,
++				      strlen(udev->manufacturer));
++
+ 	device_enable_async_suspend(&udev->dev);
+ 	/* Register the device.  The device driver is responsible
+ 	 * for configuring the device and invoking the add-device
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -50,11 +50,13 @@ struct rnd_state {
+ 
+ extern void rand_initialize_irq(int irq);
+ 
++extern void add_device_randomness(const void *, unsigned int);
+ extern void add_input_randomness(unsigned int type, unsigned int code,
+ 				 unsigned int value);
+-extern void add_interrupt_randomness(int irq);
++extern void add_interrupt_randomness(int irq, int irq_flags);
+ 
+ extern void get_random_bytes(void *buf, int nbytes);
++extern void get_random_bytes_arch(void *buf, int nbytes);
+ void generate_random_uuid(unsigned char uuid_out[16]);
+ 
+ #ifndef MODULE
+--- /dev/null
++++ b/include/trace/events/random.h
+@@ -0,0 +1,134 @@
++#undef TRACE_SYSTEM
++#define TRACE_SYSTEM random
++
++#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ)
++#define _TRACE_RANDOM_H
++
++#include <linux/writeback.h>
++#include <linux/tracepoint.h>
++
++DECLARE_EVENT_CLASS(random__mix_pool_bytes,
++	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
++
++	TP_ARGS(pool_name, bytes, IP),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	bytes			)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->bytes		= bytes;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("%s pool: bytes %d caller %pF",
++		  __entry->pool_name, __entry->bytes, (void *)__entry->IP)
++);
++
++DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes,
++	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
++
++	TP_ARGS(pool_name, bytes, IP)
++);
++
++DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
++	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
++
++	TP_ARGS(pool_name, bytes, IP)
++);
++
++TRACE_EVENT(credit_entropy_bits,
++	TP_PROTO(const char *pool_name, int bits, int entropy_count,
++		 int entropy_total, unsigned long IP),
++
++	TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	bits			)
++		__field(	  int,	entropy_count		)
++		__field(	  int,	entropy_total		)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->bits		= bits;
++		__entry->entropy_count	= entropy_count;
++		__entry->entropy_total	= entropy_total;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
++		  "caller %pF", __entry->pool_name, __entry->bits,
++		  __entry->entropy_count, __entry->entropy_total,
++		  (void *)__entry->IP)
++);
++
++TRACE_EVENT(get_random_bytes,
++	TP_PROTO(int nbytes, unsigned long IP),
++
++	TP_ARGS(nbytes, IP),
++
++	TP_STRUCT__entry(
++		__field(	  int,	nbytes			)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->nbytes		= nbytes;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP)
++);
++
++DECLARE_EVENT_CLASS(random__extract_entropy,
++	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
++		 unsigned long IP),
++
++	TP_ARGS(pool_name, nbytes, entropy_count, IP),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	nbytes			)
++		__field(	  int,	entropy_count		)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->nbytes		= nbytes;
++		__entry->entropy_count	= entropy_count;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("%s pool: nbytes %d entropy_count %d caller %pF",
++		  __entry->pool_name, __entry->nbytes, __entry->entropy_count,
++		  (void *)__entry->IP)
++);
++
++
++DEFINE_EVENT(random__extract_entropy, extract_entropy,
++	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
++		 unsigned long IP),
++
++	TP_ARGS(pool_name, nbytes, entropy_count, IP)
++);
++
++DEFINE_EVENT(random__extract_entropy, extract_entropy_user,
++	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
++		 unsigned long IP),
++
++	TP_ARGS(pool_name, nbytes, entropy_count, IP)
++);
++
++
++
++#endif /* _TRACE_RANDOM_H */
++
++/* This part must be outside protection */
++#include <trace/define_trace.h>
+--- a/kernel/irq/handle.c
++++ b/kernel/irq/handle.c
+@@ -117,7 +117,7 @@ irqreturn_t
+ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
+ {
+ 	irqreturn_t retval = IRQ_NONE;
+-	unsigned int random = 0, irq = desc->irq_data.irq;
++	unsigned int flags = 0, irq = desc->irq_data.irq;
+ 
+ 	do {
+ 		irqreturn_t res;
+@@ -145,7 +145,7 @@ handle_irq_event_percpu(struct irq_desc
+ 
+ 			/* Fall through to add to randomness */
+ 		case IRQ_HANDLED:
+-			random |= action->flags;
++			flags |= action->flags;
+ 			break;
+ 
+ 		default:
+@@ -156,8 +156,7 @@ handle_irq_event_percpu(struct irq_desc
+ 		action = action->next;
+ 	} while (action);
+ 
+-	if (random & IRQF_SAMPLE_RANDOM)
+-		add_interrupt_randomness(irq);
++	add_interrupt_randomness(irq, flags);
+ 
+ 	if (!noirqdebug)
+ 		note_interrupt(irq, desc, retval);
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -1176,6 +1176,7 @@ static int __dev_open(struct net_device
+ 		net_dmaengine_get();
+ 		dev_set_rx_mode(dev);
+ 		dev_activate(dev);
++		add_device_randomness(dev->dev_addr, dev->addr_len);
+ 	}
+ 
+ 	return ret;
+@@ -4823,6 +4824,7 @@ int dev_set_mac_address(struct net_devic
+ 	err = ops->ndo_set_mac_address(dev, sa);
+ 	if (!err)
+ 		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
++	add_device_randomness(dev->dev_addr, dev->addr_len);
+ 	return err;
+ }
+ EXPORT_SYMBOL(dev_set_mac_address);
+@@ -5602,6 +5604,7 @@ int register_netdevice(struct net_device
+ 	dev_init_scheduler(dev);
+ 	dev_hold(dev);
+ 	list_netdevice(dev);
++	add_device_randomness(dev->dev_addr, dev->addr_len);
+ 
+ 	/* Notify protocols, that a new device appeared. */
+ 	ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -1371,6 +1371,7 @@ static int do_setlink(struct net_device
+ 			goto errout;
+ 		send_addr_notify = 1;
+ 		modified = 1;
++		add_device_randomness(dev->dev_addr, dev->addr_len);
+ 	}
+ 
+ 	if (tb[IFLA_MTU]) {
diff --git a/target/linux/generic/patches-3.3/051-rng_git_backport-remove_irqf_sample_random.patch b/target/linux/generic/patches-3.3/051-rng_git_backport-remove_irqf_sample_random.patch
new file mode 100644
index 0000000000..93706ed3f6
--- /dev/null
+++ b/target/linux/generic/patches-3.3/051-rng_git_backport-remove_irqf_sample_random.patch
@@ -0,0 +1,543 @@
+--- a/arch/arm/mach-omap1/board-palmz71.c
++++ b/arch/arm/mach-omap1/board-palmz71.c
+@@ -291,8 +291,7 @@ palmz71_gpio_setup(int early)
+ 		}
+ 		gpio_direction_input(PALMZ71_USBDETECT_GPIO);
+ 		if (request_irq(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+-				palmz71_powercable, IRQF_SAMPLE_RANDOM,
+-				"palmz71-cable", 0))
++				palmz71_powercable, 0, "palmz71-cable", 0))
+ 			printk(KERN_ERR
+ 					"IRQ request for power cable failed!\n");
+ 		palmz71_powercable(gpio_to_irq(PALMZ71_USBDETECT_GPIO), 0);
+--- a/arch/arm/mach-pxa/lubbock.c
++++ b/arch/arm/mach-pxa/lubbock.c
+@@ -455,7 +455,7 @@ static int lubbock_mci_init(struct devic
+ 	init_timer(&mmc_timer);
+ 	mmc_timer.data = (unsigned long) data;
+ 	return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int,
+-			IRQF_SAMPLE_RANDOM, "lubbock-sd-detect", data);
++			   0, "lubbock-sd-detect", data);
+ }
+ 
+ static int lubbock_mci_get_ro(struct device *dev)
+--- a/arch/arm/mach-pxa/magician.c
++++ b/arch/arm/mach-pxa/magician.c
+@@ -617,9 +617,8 @@ static struct platform_device bq24022 =
+ static int magician_mci_init(struct device *dev,
+ 				irq_handler_t detect_irq, void *data)
+ {
+-	return request_irq(IRQ_MAGICIAN_SD, detect_irq,
+-				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+-				"mmc card detect", data);
++	return request_irq(IRQ_MAGICIAN_SD, detect_irq, IRQF_DISABLED,
++			   "mmc card detect", data);
+ }
+ 
+ static void magician_mci_exit(struct device *dev, void *data)
+--- a/arch/arm/mach-pxa/trizeps4.c
++++ b/arch/arm/mach-pxa/trizeps4.c
+@@ -332,8 +332,8 @@ static int trizeps4_mci_init(struct devi
+ 	int err;
+ 
+ 	err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int,
+-		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_SAMPLE_RANDOM,
+-		"MMC card detect", data);
++			  IRQF_DISABLED | IRQF_TRIGGER_RISING,
++			  "MMC card detect", data);
+ 	if (err) {
+ 		printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request"
+ 						"MMC card detect IRQ\n");
+--- a/arch/ia64/kernel/irq_ia64.c
++++ b/arch/ia64/kernel/irq_ia64.c
+@@ -23,7 +23,6 @@
+ #include <linux/ioport.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/ptrace.h>
+-#include <linux/random.h>	/* for rand_initialize_irq() */
+ #include <linux/signal.h>
+ #include <linux/smp.h>
+ #include <linux/threads.h>
+--- a/arch/sparc/kernel/ldc.c
++++ b/arch/sparc/kernel/ldc.c
+@@ -1250,14 +1250,12 @@ int ldc_bind(struct ldc_channel *lp, con
+ 	snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
+ 	snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
+ 
+-	err = request_irq(lp->cfg.rx_irq, ldc_rx,
+-			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
++	err = request_irq(lp->cfg.rx_irq, ldc_rx, IRQF_DISABLED,
+ 			  lp->rx_irq_name, lp);
+ 	if (err)
+ 		return err;
+ 
+-	err = request_irq(lp->cfg.tx_irq, ldc_tx,
+-			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
++	err = request_irq(lp->cfg.tx_irq, ldc_tx, IRQF_DISABLED,
+ 			  lp->tx_irq_name, lp);
+ 	if (err) {
+ 		free_irq(lp->cfg.rx_irq, lp);
+--- a/arch/um/drivers/line.c
++++ b/arch/um/drivers/line.c
+@@ -371,7 +371,7 @@ static irqreturn_t line_write_interrupt(
+ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
+ {
+ 	const struct line_driver *driver = line->driver;
+-	int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
++	int err = 0, flags = IRQF_DISABLED | IRQF_SHARED;
+ 
+ 	if (input)
+ 		err = um_request_irq(driver->read_irq, fd, IRQ_READ,
+@@ -807,7 +807,7 @@ void register_winch_irq(int fd, int tty_
+ 				   .stack	= stack });
+ 
+ 	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
+-			   IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
++			   IRQF_DISABLED | IRQF_SHARED,
+ 			   "winch", winch) < 0) {
+ 		printk(KERN_ERR "register_winch_irq - failed to register "
+ 		       "IRQ\n");
+--- a/arch/um/drivers/mconsole_kern.c
++++ b/arch/um/drivers/mconsole_kern.c
+@@ -773,7 +773,7 @@ static int __init mconsole_init(void)
+ 	register_reboot_notifier(&reboot_notifier);
+ 
+ 	err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
+-			     IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
++			     IRQF_DISABLED | IRQF_SHARED,
+ 			     "mconsole", (void *)sock);
+ 	if (err) {
+ 		printk(KERN_ERR "Failed to get IRQ for management console\n");
+--- a/arch/um/drivers/port_kern.c
++++ b/arch/um/drivers/port_kern.c
+@@ -100,7 +100,7 @@ static int port_accept(struct port_list
+ 		  .port 	= port });
+ 
+ 	if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
+-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
++			  IRQF_DISABLED | IRQF_SHARED,
+ 			  "telnetd", conn)) {
+ 		printk(KERN_ERR "port_accept : failed to get IRQ for "
+ 		       "telnetd\n");
+@@ -184,7 +184,7 @@ void *port_data(int port_num)
+ 	}
+ 
+ 	if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
+-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
++			  IRQF_DISABLED | IRQF_SHARED,
+ 			  "port", port)) {
+ 		printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
+ 		goto out_close;
+--- a/arch/um/drivers/random.c
++++ b/arch/um/drivers/random.c
+@@ -131,8 +131,7 @@ static int __init rng_init (void)
+ 	random_fd = err;
+ 
+ 	err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
+-			     IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random",
+-			     NULL);
++			     IRQF_DISABLED, "random", NULL);
+ 	if (err)
+ 		goto err_out_cleanup_hw;
+ 
+--- a/arch/um/drivers/xterm_kern.c
++++ b/arch/um/drivers/xterm_kern.c
+@@ -50,8 +50,7 @@ int xterm_fd(int socket, int *pid_out)
+ 	init_completion(&data->ready);
+ 
+ 	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
+-			     IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+-			     "xterm", data);
++			     IRQF_DISABLED | IRQF_SHARED, "xterm", data);
+ 	if (err) {
+ 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
+ 		       "err = %d\n",  err);
+--- a/arch/um/kernel/sigio.c
++++ b/arch/um/kernel/sigio.c
+@@ -25,8 +25,7 @@ int write_sigio_irq(int fd)
+ 	int err;
+ 
+ 	err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
+-			     IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
+-			     NULL);
++			     IRQF_DISABLED, "write sigio", NULL);
+ 	if (err) {
+ 		printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
+ 		       "err = %d\n", err);
+--- a/Documentation/feature-removal-schedule.txt
++++ b/Documentation/feature-removal-schedule.txt
+@@ -71,20 +71,6 @@ Who:	Luis R. Rodriguez <lrodriguez@ather
+ 
+ ---------------------------
+ 
+-What:	IRQF_SAMPLE_RANDOM
+-Check:	IRQF_SAMPLE_RANDOM
+-When:	July 2009
+-
+-Why:	Many of IRQF_SAMPLE_RANDOM users are technically bogus as entropy
+-	sources in the kernel's current entropy model. To resolve this, every
+-	input point to the kernel's entropy pool needs to better document the
+-	type of entropy source it actually is. This will be replaced with
+-	additional add_*_randomness functions in drivers/char/random.c
+-
+-Who:	Robin Getz <rgetz@blackfin.uclinux.org> & Matt Mackall <mpm@selenic.com>
+-
+----------------------------
+-
+ What:	The ieee80211_regdom module parameter
+ When:	March 2010 / desktop catchup
+ 
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -852,9 +852,8 @@ static int setup_blkring(struct xenbus_d
+ 	if (err)
+ 		goto fail;
+ 
+-	err = bind_evtchn_to_irqhandler(info->evtchn,
+-					blkif_interrupt,
+-					IRQF_SAMPLE_RANDOM, "blkif", info);
++	err = bind_evtchn_to_irqhandler(info->evtchn, blkif_interrupt, 0,
++					"blkif", info);
+ 	if (err <= 0) {
+ 		xenbus_dev_fatal(dev, err,
+ 				 "bind_evtchn_to_irqhandler failed");
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -633,43 +633,6 @@ struct timer_rand_state {
+ 	unsigned dont_count_entropy:1;
+ };
+ 
+-#ifndef CONFIG_GENERIC_HARDIRQS
+-
+-static struct timer_rand_state *irq_timer_state[NR_IRQS];
+-
+-static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+-{
+-	return irq_timer_state[irq];
+-}
+-
+-static void set_timer_rand_state(unsigned int irq,
+-				 struct timer_rand_state *state)
+-{
+-	irq_timer_state[irq] = state;
+-}
+-
+-#else
+-
+-static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+-{
+-	struct irq_desc *desc;
+-
+-	desc = irq_to_desc(irq);
+-
+-	return desc->timer_rand_state;
+-}
+-
+-static void set_timer_rand_state(unsigned int irq,
+-				 struct timer_rand_state *state)
+-{
+-	struct irq_desc *desc;
+-
+-	desc = irq_to_desc(irq);
+-
+-	desc->timer_rand_state = state;
+-}
+-#endif
+-
+ /*
+  * Add device- or boot-specific data to the input and nonblocking
+  * pools to help initialize them to unique values.
+@@ -1131,24 +1094,6 @@ static int rand_initialize(void)
+ }
+ module_init(rand_initialize);
+ 
+-void rand_initialize_irq(int irq)
+-{
+-	struct timer_rand_state *state;
+-
+-	state = get_timer_rand_state(irq);
+-
+-	if (state)
+-		return;
+-
+-	/*
+-	 * If kzalloc returns null, we just won't use that entropy
+-	 * source.
+-	 */
+-	state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
+-	if (state)
+-		set_timer_rand_state(irq, state);
+-}
+-
+ #ifdef CONFIG_BLOCK
+ void rand_initialize_disk(struct gendisk *disk)
+ {
+--- a/drivers/crypto/n2_core.c
++++ b/drivers/crypto/n2_core.c
+@@ -1607,8 +1607,7 @@ static int spu_map_ino(struct platform_d
+ 
+ 	sprintf(p->irq_name, "%s-%d", irq_name, index);
+ 
+-	return request_irq(p->irq, handler, IRQF_SAMPLE_RANDOM,
+-			   p->irq_name, p);
++	return request_irq(p->irq, handler, 0, p->irq_name, p);
+ }
+ 
+ static struct kmem_cache *queue_cache[2];
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -545,8 +545,7 @@ static int vmbus_bus_init(int irq)
+ 	if (ret)
+ 		goto err_cleanup;
+ 
+-	ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
+-			driver_name, hv_acpi_dev);
++	ret = request_irq(irq, vmbus_isr, 0, driver_name, hv_acpi_dev);
+ 
+ 	if (ret != 0) {
+ 		pr_err("Unable to request IRQ %d\n",
+--- a/drivers/i2c/busses/i2c-pmcmsp.c
++++ b/drivers/i2c/busses/i2c-pmcmsp.c
+@@ -306,8 +306,7 @@ static int __devinit pmcmsptwi_probe(str
+ 	pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
+ 	if (pmcmsptwi_data.irq) {
+ 		rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
+-			IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+-			pldev->name, &pmcmsptwi_data);
++				 IRQF_SHARED, pldev->name, &pmcmsptwi_data);
+ 		if (rc == 0) {
+ 			/*
+ 			 * Enable 'DONE' interrupt only.
+--- a/drivers/input/serio/hp_sdc.c
++++ b/drivers/input/serio/hp_sdc.c
+@@ -879,7 +879,7 @@ static int __init hp_sdc_init(void)
+ #endif
+ 
+ 	errstr = "IRQ not available for";
+-	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
++	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED,
+ 			"HP SDC", &hp_sdc))
+ 		goto err1;
+ 
+--- a/drivers/mfd/ab3100-core.c
++++ b/drivers/mfd/ab3100-core.c
+@@ -937,9 +937,6 @@ static int __devinit ab3100_probe(struct
+ 
+ 	err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler,
+ 				IRQF_ONESHOT, "ab3100-core", ab3100);
+-	/* This real unpredictable IRQ is of course sampled for entropy */
+-	rand_initialize_irq(client->irq);
+-
+ 	if (err)
+ 		goto exit_no_irq;
+ 
+--- a/drivers/mfd/tps65010.c
++++ b/drivers/mfd/tps65010.c
+@@ -563,8 +563,7 @@ static int tps65010_probe(struct i2c_cli
+ 	 */
+ 	if (client->irq > 0) {
+ 		status = request_irq(client->irq, tps65010_irq,
+-			IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_FALLING,
+-			DRIVER_NAME, tps);
++			IRQF_TRIGGER_FALLING, DRIVER_NAME, tps);
+ 		if (status < 0) {
+ 			dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
+ 					client->irq, status);
+--- a/drivers/net/ethernet/broadcom/tg3.c
++++ b/drivers/net/ethernet/broadcom/tg3.c
+@@ -9415,7 +9415,7 @@ static int tg3_test_interrupt(struct tg3
+ 	}
+ 
+ 	err = request_irq(tnapi->irq_vec, tg3_test_isr,
+-			  IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
++			  IRQF_SHARED, dev->name, tnapi);
+ 	if (err)
+ 		return err;
+ 
+--- a/drivers/power/pda_power.c
++++ b/drivers/power/pda_power.c
+@@ -24,11 +24,7 @@
+ 
+ static inline unsigned int get_irq_flags(struct resource *res)
+ {
+-	unsigned int flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED;
+-
+-	flags |= res->flags & IRQF_TRIGGER_MASK;
+-
+-	return flags;
++	return IRQF_SHARED | (res->flags & IRQF_TRIGGER_MASK);
+ }
+ 
+ static struct device *dev;
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -216,8 +216,7 @@ static int ulite_startup(struct uart_por
+ {
+ 	int ret;
+ 
+-	ret = request_irq(port->irq, ulite_isr,
+-			  IRQF_SHARED | IRQF_SAMPLE_RANDOM, "uartlite", port);
++	ret = request_irq(port->irq, ulite_isr, IRQF_SHARED, "uartlite", port);
+ 	if (ret)
+ 		return ret;
+ 
+--- a/drivers/usb/gadget/goku_udc.c
++++ b/drivers/usb/gadget/goku_udc.c
+@@ -1839,7 +1839,7 @@ static int goku_probe(struct pci_dev *pd
+ 	/* init to known state, then setup irqs */
+ 	udc_reset(dev);
+ 	udc_reinit (dev);
+-	if (request_irq(pdev->irq, goku_irq, IRQF_SHARED/*|IRQF_SAMPLE_RANDOM*/,
++	if (request_irq(pdev->irq, goku_irq, IRQF_SHARED,
+ 			driver_name, dev) != 0) {
+ 		DBG(dev, "request interrupt %d failed\n", pdev->irq);
+ 		retval = -EBUSY;
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -2943,7 +2943,7 @@ known:
+ 
+ 	/* USB general purpose IRQ:  ep0, state changes, dma, etc */
+ 	status = request_irq(pdev->resource[1].start, omap_udc_irq,
+-			IRQF_SAMPLE_RANDOM, driver_name, udc);
++			     0, driver_name, udc);
+ 	if (status != 0) {
+ 		ERR("can't get irq %d, err %d\n",
+ 			(int) pdev->resource[1].start, status);
+@@ -2952,7 +2952,7 @@ known:
+ 
+ 	/* USB "non-iso" IRQ (PIO for all but ep0) */
+ 	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
+-			IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
++			     0, "omap_udc pio", udc);
+ 	if (status != 0) {
+ 		ERR("can't get irq %d, err %d\n",
+ 			(int) pdev->resource[2].start, status);
+--- a/drivers/usb/gadget/pxa25x_udc.c
++++ b/drivers/usb/gadget/pxa25x_udc.c
+@@ -2202,19 +2202,15 @@ static int __init pxa25x_udc_probe(struc
+ 
+ #ifdef CONFIG_ARCH_LUBBOCK
+ 	if (machine_is_lubbock()) {
+-		retval = request_irq(LUBBOCK_USB_DISC_IRQ,
+-				lubbock_vbus_irq,
+-				IRQF_SAMPLE_RANDOM,
+-				driver_name, dev);
++		retval = request_irq(LUBBOCK_USB_DISC_IRQ, lubbock_vbus_irq,
++				     0, driver_name, dev);
+ 		if (retval != 0) {
+ 			pr_err("%s: can't get irq %i, err %d\n",
+ 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
+ 			goto err_irq_lub;
+ 		}
+-		retval = request_irq(LUBBOCK_USB_IRQ,
+-				lubbock_vbus_irq,
+-				IRQF_SAMPLE_RANDOM,
+-				driver_name, dev);
++		retval = request_irq(LUBBOCK_USB_IRQ, lubbock_vbus_irq,
++				     0, driver_name, dev);
+ 		if (retval != 0) {
+ 			pr_err("%s: can't get irq %i, err %d\n",
+ 				driver_name, LUBBOCK_USB_IRQ, retval);
+--- a/drivers/usb/otg/gpio_vbus.c
++++ b/drivers/usb/otg/gpio_vbus.c
+@@ -51,8 +51,7 @@ struct gpio_vbus_data {
+  * edges might be workable.
+  */
+ #define VBUS_IRQ_FLAGS \
+-	( IRQF_SAMPLE_RANDOM | IRQF_SHARED \
+-	| IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING )
++	( IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING )
+ 
+ 
+ /* interface to regulator framework */
+@@ -253,7 +252,7 @@ static int __init gpio_vbus_probe(struct
+ 	if (res) {
+ 		irq = res->start;
+ 		res->flags &= IRQF_TRIGGER_MASK;
+-		res->flags |= IRQF_SAMPLE_RANDOM | IRQF_SHARED;
++		res->flags |= IRQF_SHARED;
+ 	} else
+ 		irq = gpio_to_irq(gpio);
+ 
+--- a/drivers/usb/otg/isp1301_omap.c
++++ b/drivers/usb/otg/isp1301_omap.c
+@@ -1567,7 +1567,6 @@ isp1301_probe(struct i2c_client *i2c, co
+ 		isp->irq_type = IRQF_TRIGGER_FALLING;
+ 	}
+ 
+-	isp->irq_type |= IRQF_SAMPLE_RANDOM;
+ 	status = request_irq(i2c->irq, isp1301_irq,
+ 			isp->irq_type, DRIVER_NAME, isp);
+ 	if (status < 0) {
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -44,7 +44,6 @@
+  *
+  * IRQF_DISABLED - keep irqs disabled when calling the action handler.
+  *                 DEPRECATED. This flag is a NOOP and scheduled to be removed
+- * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator
+  * IRQF_SHARED - allow sharing the irq among several devices
+  * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
+  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
+@@ -63,7 +62,6 @@
+  *                resume time.
+  */
+ #define IRQF_DISABLED		0x00000020
+-#define IRQF_SAMPLE_RANDOM	0x00000040
+ #define IRQF_SHARED		0x00000080
+ #define IRQF_PROBE_SHARED	0x00000100
+ #define __IRQF_TIMER		0x00000200
+--- a/include/linux/irqdesc.h
++++ b/include/linux/irqdesc.h
+@@ -39,7 +39,6 @@ struct module;
+  */
+ struct irq_desc {
+ 	struct irq_data		irq_data;
+-	struct timer_rand_state *timer_rand_state;
+ 	unsigned int __percpu	*kstat_irqs;
+ 	irq_flow_handler_t	handle_irq;
+ #ifdef CONFIG_IRQ_PREFLOW_FASTEOI
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -48,8 +48,6 @@ struct rnd_state {
+ 
+ #ifdef __KERNEL__
+ 
+-extern void rand_initialize_irq(int irq);
+-
+ extern void add_device_randomness(const void *, unsigned int);
+ extern void add_input_randomness(unsigned int type, unsigned int code,
+ 				 unsigned int value);
+--- a/kernel/irq/manage.c
++++ b/kernel/irq/manage.c
+@@ -891,22 +891,6 @@ __setup_irq(unsigned int irq, struct irq
+ 		return -ENOSYS;
+ 	if (!try_module_get(desc->owner))
+ 		return -ENODEV;
+-	/*
+-	 * Some drivers like serial.c use request_irq() heavily,
+-	 * so we have to be careful not to interfere with a
+-	 * running system.
+-	 */
+-	if (new->flags & IRQF_SAMPLE_RANDOM) {
+-		/*
+-		 * This function might sleep, we want to call it first,
+-		 * outside of the atomic block.
+-		 * Yes, this might clear the entropy pool if the wrong
+-		 * driver is attempted to be loaded, without actually
+-		 * installing a new handler, but is this really a problem,
+-		 * only the sysadmin is able to do this.
+-		 */
+-		rand_initialize_irq(irq);
+-	}
+ 
+ 	/*
+ 	 * Check whether the interrupt nests into another interrupt
+@@ -1342,7 +1326,6 @@ EXPORT_SYMBOL(free_irq);
+  *	Flags:
+  *
+  *	IRQF_SHARED		Interrupt is shared
+- *	IRQF_SAMPLE_RANDOM	The interrupt can be used for entropy
+  *	IRQF_TRIGGER_*		Specify active edge(s) or level
+  *
+  */
diff --git a/target/linux/generic/patches-3.3/941-ocf_20120127.patch b/target/linux/generic/patches-3.3/941-ocf_20120127.patch
index 366a2586d4..794627a854 100644
--- a/target/linux/generic/patches-3.3/941-ocf_20120127.patch
+++ b/target/linux/generic/patches-3.3/941-ocf_20120127.patch
@@ -1,7 +1,7 @@
 --- a/drivers/char/random.c
 +++ b/drivers/char/random.c
-@@ -130,6 +130,9 @@
-  * 	void add_interrupt_randomness(int irq);
+@@ -131,6 +131,9 @@
+  *	void add_interrupt_randomness(int irq, int irq_flags);
   * 	void add_disk_randomness(struct gendisk *disk);
   *
 + *      void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
@@ -10,7 +10,7 @@
   * add_input_randomness() uses the input layer interrupt timing, as well as
   * the event type information from the hardware.
   *
-@@ -147,6 +150,13 @@
+@@ -152,6 +155,13 @@
   * seek times do not make for good sources of entropy, as their seek
   * times are usually fairly consistent.
   *
@@ -24,7 +24,7 @@
   * All of these routines try to estimate how many bits of randomness a
   * particular randomness source.  They do this by keeping track of the
   * first and second order deltas of the event timings.
-@@ -726,6 +736,63 @@ void add_disk_randomness(struct gendisk
+@@ -796,6 +806,63 @@ void add_disk_randomness(struct gendisk
  }
  #endif
  
@@ -40,7 +40,7 @@
 + */
 +void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
 +{
-+	mix_pool_bytes(&input_pool, buf, wordcount*4);
++	mix_pool_bytes(&input_pool, buf, wordcount*4, NULL);
 +
 +	credit_entropy_bits(&input_pool, ent_count);
 +
@@ -141,17 +141,17 @@
  struct rand_pool_info {
  	int	entropy_count;
  	int	buf_size;
-@@ -54,6 +78,10 @@ extern void add_input_randomness(unsigne
+@@ -53,6 +77,10 @@ extern void add_input_randomness(unsigne
  				 unsigned int value);
- extern void add_interrupt_randomness(int irq);
+ extern void add_interrupt_randomness(int irq, int irq_flags);
  
 +extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count);
 +extern int random_input_wait(void);
 +#define HAS_RANDOM_INPUT_WAIT 1
 +
  extern void get_random_bytes(void *buf, int nbytes);
+ extern void get_random_bytes_arch(void *buf, int nbytes);
  void generate_random_uuid(unsigned char uuid_out[16]);
- 
 --- a/kernel/pid.c
 +++ b/kernel/pid.c
 @@ -430,6 +430,7 @@ struct task_struct *find_task_by_vpid(pi
-- 
2.30.2