s390/qeth: free netdevice when removing a card
[pandora-kernel.git] / drivers / char / random.c
index 8ae9235..edf45ae 100644 (file)
@@ -668,7 +668,7 @@ static void set_timer_rand_state(unsigned int irq,
  */
 void add_device_randomness(const void *buf, unsigned int size)
 {
-       unsigned long time = get_cycles() ^ jiffies;
+       unsigned long time = random_get_entropy() ^ jiffies;
 
        mix_pool_bytes(&input_pool, buf, size, NULL);
        mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
@@ -705,7 +705,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
                goto out;
 
        sample.jiffies = jiffies;
-       sample.cycles = get_cycles();
+       sample.cycles = random_get_entropy();
        sample.num = num;
        mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
 
@@ -772,7 +772,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
        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();
+       __u32                   input[4], cycles = random_get_entropy();
 
        input[0] = cycles ^ jiffies;
        input[1] = irq;
@@ -889,16 +889,24 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
        if (r->entropy_count / 8 < min + reserved) {
                nbytes = 0;
        } else {
+               int entropy_count, orig;
+retry:
+               entropy_count = orig = ACCESS_ONCE(r->entropy_count);
                /* If limited, never pull more than available */
-               if (r->limit && nbytes + reserved >= r->entropy_count / 8)
-                       nbytes = r->entropy_count/8 - reserved;
-
-               if (r->entropy_count / 8 >= nbytes + reserved)
-                       r->entropy_count -= nbytes*8;
-               else
-                       r->entropy_count = reserved;
+               if (r->limit && nbytes + reserved >= entropy_count / 8)
+                       nbytes = entropy_count/8 - reserved;
+
+               if (entropy_count / 8 >= nbytes + reserved) {
+                       entropy_count -= nbytes*8;
+                       if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+                               goto retry;
+               } else {
+                       entropy_count = reserved;
+                       if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+                               goto retry;
+               }
 
-               if (r->entropy_count < random_write_wakeup_thresh) {
+               if (entropy_count < random_write_wakeup_thresh) {
                        wake_up_interruptible(&random_write_wait);
                        kill_fasync(&fasync, SIGIO, POLL_OUT);
                }
@@ -946,8 +954,8 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
         * pool while mixing, and hash one final time.
         */
        sha_transform(hash.w, extract, workspace);
-       memset(extract, 0, sizeof(extract));
-       memset(workspace, 0, sizeof(workspace));
+       memzero_explicit(extract, sizeof(extract));
+       memzero_explicit(workspace, sizeof(workspace));
 
        /*
         * In case the hash function has some recognizable output
@@ -970,7 +978,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
        }
 
        memcpy(out, &hash, EXTRACT_SIZE);
-       memset(&hash, 0, sizeof(hash));
+       memzero_explicit(&hash, sizeof(hash));
 }
 
 static ssize_t extract_entropy(struct entropy_store *r, void *buf,
@@ -1002,7 +1010,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
        }
 
        /* Wipe data just returned from memory */
-       memset(tmp, 0, sizeof(tmp));
+       memzero_explicit(tmp, sizeof(tmp));
 
        return ret;
 }
@@ -1039,7 +1047,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
        }
 
        /* Wipe data just returned from memory */
-       memset(tmp, 0, sizeof(tmp));
+       memzero_explicit(tmp, sizeof(tmp));
 
        return ret;
 }
@@ -1472,12 +1480,11 @@ ctl_table random_table[] = {
 
 static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
 
-static int __init random_int_secret_init(void)
+int random_int_secret_init(void)
 {
        get_random_bytes(random_int_secret, sizeof(random_int_secret));
        return 0;
 }
-late_initcall(random_int_secret_init);
 
 /*
  * Get a random word for internal kernel use only. Similar to urandom but
@@ -1496,7 +1503,7 @@ unsigned int get_random_int(void)
 
        hash = get_cpu_var(get_random_int_hash);
 
-       hash[0] += current->pid + jiffies + get_cycles();
+       hash[0] += current->pid + jiffies + random_get_entropy();
        md5_transform(hash, random_int_secret);
        ret = hash[0];
        put_cpu_var(get_random_int_hash);