Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright © 2016 Intel Corporation
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice (including the next
0012  * paragraph) shall be included in all copies or substantial portions of the
0013  * Software.
0014  *
0015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0018  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0020  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
0021  * IN THE SOFTWARE.
0022  *
0023  */
0024 
0025 #include <linux/bitops.h>
0026 #include <linux/kernel.h>
0027 #include <linux/random.h>
0028 #include <linux/slab.h>
0029 #include <linux/types.h>
0030 
0031 #include "i915_random.h"
0032 #include "i915_utils.h"
0033 
0034 u64 i915_prandom_u64_state(struct rnd_state *rnd)
0035 {
0036     u64 x;
0037 
0038     x = prandom_u32_state(rnd);
0039     x <<= 32;
0040     x |= prandom_u32_state(rnd);
0041 
0042     return x;
0043 }
0044 
0045 void i915_prandom_shuffle(void *arr, size_t elsz, size_t count,
0046               struct rnd_state *state)
0047 {
0048     char stack[128];
0049 
0050     if (WARN_ON(elsz > sizeof(stack) || count > U32_MAX))
0051         return;
0052 
0053     if (!elsz || !count)
0054         return;
0055 
0056     /* Fisher-Yates shuffle courtesy of Knuth */
0057     while (--count) {
0058         size_t swp;
0059 
0060         swp = i915_prandom_u32_max_state(count + 1, state);
0061         if (swp == count)
0062             continue;
0063 
0064         memcpy(stack, arr + count * elsz, elsz);
0065         memcpy(arr + count * elsz, arr + swp * elsz, elsz);
0066         memcpy(arr + swp * elsz, stack, elsz);
0067     }
0068 }
0069 
0070 void i915_random_reorder(unsigned int *order, unsigned int count,
0071              struct rnd_state *state)
0072 {
0073     i915_prandom_shuffle(order, sizeof(*order), count, state);
0074 }
0075 
0076 unsigned int *i915_random_order(unsigned int count, struct rnd_state *state)
0077 {
0078     unsigned int *order, i;
0079 
0080     order = kmalloc_array(count, sizeof(*order),
0081                   GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
0082     if (!order)
0083         return order;
0084 
0085     for (i = 0; i < count; i++)
0086         order[i] = i;
0087 
0088     i915_random_reorder(order, count, state);
0089     return order;
0090 }
0091 
0092 u64 igt_random_offset(struct rnd_state *state,
0093               u64 start, u64 end,
0094               u64 len, u64 align)
0095 {
0096     u64 range, addr;
0097 
0098     BUG_ON(range_overflows(start, len, end));
0099     BUG_ON(round_up(start, align) > round_down(end - len, align));
0100 
0101     range = round_down(end - len, align) - round_up(start, align);
0102     if (range) {
0103         addr = i915_prandom_u64_state(state);
0104         div64_u64_rem(addr, range, &addr);
0105         start += addr;
0106     }
0107 
0108     return round_up(start, align);
0109 }