summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-08-07 06:15:23 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2014-08-07 13:13:31 +0200
commit38c3b2455edea648f38d3e11baf478488fd698ed (patch)
treea66280a235dfd3fdb5c0411f4efc64b2b98aec0c
parent5b7b7ee5d943c6b58d9b7f974167d0105ca1b787 (diff)
parentca22ccd7cdbb6b2bd720dd7e14280ee1efa29074 (diff)
downloadbarebox-38c3b2455edea648f38d3e11baf478488fd698ed.tar.gz
barebox-38c3b2455edea648f38d3e11baf478488fd698ed.tar.xz
Merge branch 'for-next/misc'
Conflicts: lib/Makefile
-rw-r--r--Documentation/devicetree/bindings/leds/common.rst2
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/blackfin/Kconfig1
-rw-r--r--arch/blackfin/include/asm/bitops.h361
-rw-r--r--arch/efi/Kconfig1
-rw-r--r--arch/efi/include/asm/bitops.h7
-rw-r--r--arch/mips/dts/jz4755.dtsi5
-rw-r--r--arch/mips/include/asm/bitops.h26
-rw-r--r--arch/mips/mach-xburst/Kconfig2
-rw-r--r--arch/mips/mach-xburst/include/mach/jz4750d_regs.h22
-rw-r--r--arch/mips/mach-xburst/reset-jz4750.c18
-rw-r--r--arch/nios2/Kconfig2
-rw-r--r--arch/nios2/include/asm/bitops.h32
-rw-r--r--arch/openrisc/Kconfig2
-rw-r--r--arch/openrisc/include/asm/bitops.h29
-rw-r--r--arch/ppc/Kconfig2
-rw-r--r--arch/ppc/include/asm/bitops.h49
-rw-r--r--arch/sandbox/include/asm/bitops.h25
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/include/asm/bitops.h32
-rw-r--r--arch/x86/include/asm/types.h2
-rw-r--r--common/Kconfig19
-rw-r--r--common/dlmalloc.c169
-rw-r--r--common/hush.c2
-rw-r--r--common/resource.c2
-rw-r--r--drivers/ata/Kconfig1
-rw-r--r--drivers/clk/clk-divider.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c4
-rw-r--r--drivers/input/Kconfig2
-rw-r--r--drivers/led/led-gpio.c6
-rw-r--r--drivers/mci/mci-core.c6
-rw-r--r--drivers/mfd/mc34704.c6
-rw-r--r--drivers/mtd/nand/atmel_nand.c11
-rw-r--r--drivers/net/Kconfig4
-rw-r--r--drivers/net/gianfar.c70
-rw-r--r--drivers/net/gianfar.h16
-rw-r--r--drivers/of/of_mtd.c2
-rw-r--r--drivers/regulator/Kconfig1
-rw-r--r--drivers/regulator/fixed.c9
-rw-r--r--drivers/usb/gadget/u_serial.c8
-rw-r--r--drivers/usb/host/Kconfig1
-rw-r--r--drivers/video/imx-ipu-v3/Kconfig1
-rw-r--r--drivers/watchdog/Kconfig7
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/imxwd.c4
-rw-r--r--drivers/watchdog/jz4740.c102
-rw-r--r--include/asm-generic/bitops/hweight.h15
-rw-r--r--include/bbu.h2
-rw-r--r--include/linux/bitmap.h285
-rw-r--r--include/linux/bitops.h214
-rw-r--r--include/linux/byteorder/generic.h29
-rw-r--r--include/linux/kernel.h13
-rw-r--r--include/linux/types.h3
-rw-r--r--include/malloc.h22
-rw-r--r--include/printk.h8
-rw-r--r--lib/Makefile1
-rw-r--r--lib/bitmap.c839
-rw-r--r--lib/readline.c122
58 files changed, 1842 insertions, 790 deletions
diff --git a/Documentation/devicetree/bindings/leds/common.rst b/Documentation/devicetree/bindings/leds/common.rst
index c1fd1ab89e..1f5ae42caf 100644
--- a/Documentation/devicetree/bindings/leds/common.rst
+++ b/Documentation/devicetree/bindings/leds/common.rst
@@ -8,3 +8,5 @@ Common leds properties
* ``panic`` - LED turns on when barebox panics
* ``net`` - LED indicates network activity
+* ``label``: The label for this LED. If omitted, the label is taken
+ from the node name (excluding the unit address).
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a3208d27e4..9f34e1089b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2,6 +2,8 @@ config ARM
bool
select HAS_KALLSYMS
select HAS_MODULES
+ select HAS_DMA
+ select HAS_CACHE
select HAVE_CONFIGURABLE_TEXT_BASE
select HAVE_PBL_IMAGE
select HAVE_IMAGE_COMPRESSION
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index bea9f51e1e..6233614e19 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -5,6 +5,7 @@ config BLACKFIN
select HAS_MODULES
select HAVE_CONFIGURABLE_MEMORY_LAYOUT
select HAVE_CONFIGURABLE_TEXT_BASE
+ select GENERIC_FIND_NEXT_BIT
default y
config BF561
diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h
index 4ab1471522..e77ab83202 100644
--- a/arch/blackfin/include/asm/bitops.h
+++ b/arch/blackfin/include/asm/bitops.h
@@ -1,11 +1,4 @@
/*
- * barebox - bitops.h Routines for bit operations
- *
- * Copyright (c) 2005 blackfin.uclinux.org
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* 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
@@ -16,349 +9,27 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
+ *
*/
-#ifndef _BLACKFIN_BITOPS_H
-#define _BLACKFIN_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-#include <asm/byteorder.h>
-#include <asm/system.h>
-
-#ifdef __KERNEL__
-/*
- * Function prototypes to keep gcc -Wall happy
- */
-
-/*
- * The __ functions are not atomic
- */
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static __inline__ unsigned long ffz(unsigned long word)
-{
- unsigned long result = 0;
-
- while (word & 1) {
- result++;
- word >>= 1;
- }
- return result;
-}
-
-static __inline__ void set_bit(int nr, volatile void *addr)
-{
- int *a = (int *) addr;
- int mask;
- unsigned long flags;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- save_and_cli(flags);
- *a |= mask;
- restore_flags(flags);
-}
-
-static __inline__ void __set_bit(int nr, volatile void *addr)
-{
- int *a = (int *) addr;
- int mask;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- *a |= mask;
-}
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit() barrier()
-#define smp_mb__after_clear_bit() barrier()
-
-static __inline__ void clear_bit(int nr, volatile void *addr)
-{
- int *a = (int *) addr;
- int mask;
- unsigned long flags;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- save_and_cli(flags);
- *a &= ~mask;
- restore_flags(flags);
-}
-
-static __inline__ void change_bit(int nr, volatile void *addr)
-{
- int mask, flags;
- unsigned long *ADDR = (unsigned long *) addr;
-
- ADDR += nr >> 5;
- mask = 1 << (nr & 31);
- save_and_cli(flags);
- *ADDR ^= mask;
- restore_flags(flags);
-}
-
-static __inline__ void __change_bit(int nr, volatile void *addr)
-{
- int mask;
- unsigned long *ADDR = (unsigned long *) addr;
-
- ADDR += nr >> 5;
- mask = 1 << (nr & 31);
- *ADDR ^= mask;
-}
-
-static __inline__ int test_and_set_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- volatile unsigned int *a = (volatile unsigned int *) addr;
- unsigned long flags;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- save_and_cli(flags);
- retval = (mask & *a) != 0;
- *a |= mask;
- restore_flags(flags);
-
- return retval;
-}
-
-static __inline__ int __test_and_set_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- volatile unsigned int *a = (volatile unsigned int *) addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a |= mask;
- return retval;
-}
-
-static __inline__ int test_and_clear_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- volatile unsigned int *a = (volatile unsigned int *) addr;
- unsigned long flags;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- save_and_cli(flags);
- retval = (mask & *a) != 0;
- *a &= ~mask;
- restore_flags(flags);
-
- return retval;
-}
-
-static __inline__ int __test_and_clear_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- volatile unsigned int *a = (volatile unsigned int *) addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a &= ~mask;
- return retval;
-}
-
-static __inline__ int test_and_change_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- volatile unsigned int *a = (volatile unsigned int *) addr;
- unsigned long flags;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- save_and_cli(flags);
- retval = (mask & *a) != 0;
- *a ^= mask;
- restore_flags(flags);
-
- return retval;
-}
-
-static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- volatile unsigned int *a = (volatile unsigned int *) addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a ^= mask;
- return retval;
-}
-
-/*
- * This routine doesn't need to be atomic.
- */
-static __inline__ int __constant_test_bit(int nr,
- const volatile void *addr)
-{
- return ((1UL << (nr & 31)) &
- (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
-}
-
-static __inline__ int __test_bit(int nr, volatile void *addr)
-{
- int *a = (int *) addr;
- int mask;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- return ((mask & *a) != 0);
-}
-
-#define test_bit(nr,addr) \
-(__builtin_constant_p(nr) ? \
- __constant_test_bit((nr),(addr)) : \
- __test_bit((nr),(addr)))
-
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32 - offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
- found_first:
- tmp |= ~0UL >> size;
- found_middle:
- return result + ffz(tmp);
-}
+#ifndef _ASM_BITOPS_H_
+#define _ASM_BITOPS_H_
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/hweight.h>
-
-static __inline__ int ext2_set_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- unsigned long flags;
- volatile unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- save_and_cli(flags);
- retval = (mask & *ADDR) != 0;
- *ADDR |= mask;
- restore_flags(flags);
- return retval;
-}
-
-static __inline__ int ext2_clear_bit(int nr, volatile void *addr)
-{
- int mask, retval;
- unsigned long flags;
- volatile unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- save_and_cli(flags);
- retval = (mask & *ADDR) != 0;
- *ADDR &= ~mask;
- restore_flags(flags);
- return retval;
-}
-
-static __inline__ int ext2_test_bit(int nr, const volatile void *addr)
-{
- int mask;
- const volatile unsigned char *ADDR = (const unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- return ((mask & *ADDR) != 0);
-}
-
-#define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-static __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
- unsigned long size,
- unsigned long
- offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32 - offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
- found_first:
- tmp |= ~0UL >> size;
- found_middle:
- return result + ffz(tmp);
-}
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
-
-#endif
-
-#endif
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ops.h>
+
+#define set_bit(x, y) __set_bit(x, y)
+#define clear_bit(x, y) __clear_bit(x, y)
+#define change_bit(x, y) __change_bit(x, y)
+#define test_and_set_bit(x, y) __test_and_set_bit(x, y)
+#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y)
+#define test_and_change_bit(x, y) __test_and_change_bit(x, y)
+
+#endif /* _ASM_BITOPS_H_ */
diff --git a/arch/efi/Kconfig b/arch/efi/Kconfig
index 71ac1c74e8..26fecaa392 100644
--- a/arch/efi/Kconfig
+++ b/arch/efi/Kconfig
@@ -7,6 +7,7 @@ config ARCH_EFI
select EFI_GUID
select EFI_DEVICEPATH
select PRINTF_UUID
+ select GENERIC_FIND_NEXT_BIT
config ARCH_TEXT_BASE
hex
diff --git a/arch/efi/include/asm/bitops.h b/arch/efi/include/asm/bitops.h
index 94646d4d0d..447023da63 100644
--- a/arch/efi/include/asm/bitops.h
+++ b/arch/efi/include/asm/bitops.h
@@ -12,4 +12,11 @@
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/ops.h>
+#define set_bit(x, y) __set_bit(x, y)
+#define clear_bit(x, y) __clear_bit(x, y)
+#define change_bit(x, y) __change_bit(x, y)
+#define test_and_set_bit(x, y) __test_and_set_bit(x, y)
+#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y)
+#define test_and_change_bit(x, y) __test_and_change_bit(x, y)
+
#endif
diff --git a/arch/mips/dts/jz4755.dtsi b/arch/mips/dts/jz4755.dtsi
index 0e655b65a1..718463548b 100644
--- a/arch/mips/dts/jz4755.dtsi
+++ b/arch/mips/dts/jz4755.dtsi
@@ -8,6 +8,11 @@
#size-cells = <1>;
ranges;
+ wdt: wdt@b0002000 {
+ compatible = "ingenic,jz4740-wdt";
+ reg = <0xb0002000 0x10>;
+ };
+
serial0: serial@b0030000 {
compatible = "ingenic,jz4740-uart";
reg = <0xb0030000 0x20>;
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index ebf8cf04d3..e77ab83202 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -12,20 +12,24 @@
*
*/
-/**
- * @file
- * @brief mips bit operations
- *
- * This file is required only to make all sources happy including
- * 'linux/bitops.h'
- */
-
-#ifndef _ASM_MIPS_BITOPS_H_
-#define _ASM_MIPS_BITOPS_H_
+#ifndef _ASM_BITOPS_H_
+#define _ASM_BITOPS_H_
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ops.h>
+
+#define set_bit(x, y) __set_bit(x, y)
+#define clear_bit(x, y) __clear_bit(x, y)
+#define change_bit(x, y) __change_bit(x, y)
+#define test_and_set_bit(x, y) __test_and_set_bit(x, y)
+#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y)
+#define test_and_change_bit(x, y) __test_and_change_bit(x, y)
-#endif /* _ASM_MIPS_BITOPS_H_ */
+#endif /* _ASM_BITOPS_H_ */
diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig
index 706d59249b..f7b8470cb8 100644
--- a/arch/mips/mach-xburst/Kconfig
+++ b/arch/mips/mach-xburst/Kconfig
@@ -6,6 +6,8 @@ config ARCH_TEXT_BASE
config CPU_JZ4755
bool
+ select WATCHDOG
+ select WATCHDOG_JZ4740
choice
prompt "Board type"
diff --git a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h
index 7a3daadb18..396c823a1f 100644
--- a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h
+++ b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h
@@ -59,28 +59,6 @@
#define TCU_OSTCSR_PCK_EN (1 << 0) /* select pclk as the timer clock input */
/*************************************************************************
- * WDT (WatchDog Timer)
- *************************************************************************/
-#define WDT_TDR (WDT_BASE + 0x00)
-#define WDT_TCER (WDT_BASE + 0x04)
-#define WDT_TCNT (WDT_BASE + 0x08)
-#define WDT_TCSR (WDT_BASE + 0x0c)
-
-#define WDT_TCSR_PRESCALE_BIT 3
-#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT)
- #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT)
- #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT)
- #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT)
- #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT)
- #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT)
- #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT)
-#define WDT_TCSR_EXT_EN (1 << 2)
-#define WDT_TCSR_RTC_EN (1 << 1)
-#define WDT_TCSR_PCK_EN (1 << 0)
-
-#define WDT_TCER_TCEN (1 << 0)
-
-/*************************************************************************
* RTC
*************************************************************************/
#define RTC_RCR (RTC_BASE + 0x00) /* RTC Control Register */
diff --git a/arch/mips/mach-xburst/reset-jz4750.c b/arch/mips/mach-xburst/reset-jz4750.c
index 8f33672280..25830f130e 100644
--- a/arch/mips/mach-xburst/reset-jz4750.c
+++ b/arch/mips/mach-xburst/reset-jz4750.c
@@ -24,8 +24,6 @@
#include <io.h>
#include <mach/jz4750d_regs.h>
-#define JZ_EXTAL 24000000
-
static void __noreturn jz4750d_halt(void)
{
while (1) {
@@ -39,22 +37,6 @@ static void __noreturn jz4750d_halt(void)
unreachable();
}
-void __noreturn reset_cpu(ulong addr)
-{
- __raw_writew(WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN, (u16 *)WDT_TCSR);
- __raw_writew(0, (u16 *)WDT_TCNT);
-
- /* reset after 4ms */
- __raw_writew(JZ_EXTAL / 1000, (u16 *)WDT_TDR);
- /* enable wdt clock */
- __raw_writel(TCU_TSCR_WDTSC, (u32 *)TCU_TSCR);
- /* start wdt */
- __raw_writeb(WDT_TCER_TCEN, (u8 *)WDT_TCER);
-
- unreachable();
-}
-EXPORT_SYMBOL(reset_cpu);
-
void __noreturn poweroff()
{
u32 ctrl;
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index 116daa9bb9..199540ba74 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -2,7 +2,9 @@ config NIOS2
bool
select HAS_KALLSYMS
select HAS_MODULES
+ select HAS_CACHE
select HAVE_CONFIGURABLE_MEMORY_LAYOUT
+ select GENERIC_FIND_NEXT_BIT
default y
config ARCH_TEXT_BASE
diff --git a/arch/nios2/include/asm/bitops.h b/arch/nios2/include/asm/bitops.h
index 07128451c1..e77ab83202 100644
--- a/arch/nios2/include/asm/bitops.h
+++ b/arch/nios2/include/asm/bitops.h
@@ -1,9 +1,35 @@
-#ifndef _ASM_BITOPS_H
-#define _ASM_BITOPS_H
+/*
+ * 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.
+ *
+ *
+ */
+
+#ifndef _ASM_BITOPS_H_
+#define _ASM_BITOPS_H_
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ops.h>
+
+#define set_bit(x, y) __set_bit(x, y)
+#define clear_bit(x, y) __clear_bit(x, y)
+#define change_bit(x, y) __change_bit(x, y)
+#define test_and_set_bit(x, y) __test_and_set_bit(x, y)
+#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y)
+#define test_and_change_bit(x, y) __test_and_change_bit(x, y)
-#endif /* _ASM_BITOPS_H */
+#endif /* _ASM_BITOPS_H_ */
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index d8d4ee9b6d..23c6a71f3a 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -1,7 +1,9 @@
config OPENRISC
bool
+ select HAS_CACHE
select HAVE_CONFIGURABLE_MEMORY_LAYOUT
select HAVE_DEFAULT_ENVIRONMENT_NEW
+ select GENERIC_FIND_NEXT_BIT
default y
# not used
diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
index fa57901476..e77ab83202 100644
--- a/arch/openrisc/include/asm/bitops.h
+++ b/arch/openrisc/include/asm/bitops.h
@@ -1,6 +1,4 @@
/*
- * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
- *
* 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
@@ -11,14 +9,27 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
+ *
*/
-#ifndef __ASM_OPENRISC_BITOPS_H
-#define __ASM_OPENRISC_BITOPS_H
+#ifndef _ASM_BITOPS_H_
+#define _ASM_BITOPS_H_
+
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ops.h>
-#define PLATFORM_FLS
-#include <asm/bitops/fls.h>
-#define PLATFORM_FFS
-#include <asm/bitops/ffs.h>
+#define set_bit(x, y) __set_bit(x, y)
+#define clear_bit(x, y) __clear_bit(x, y)
+#define change_bit(x, y) __change_bit(x, y)
+#define test_and_set_bit(x, y) __test_and_set_bit(x, y)
+#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y)
+#define test_and_change_bit(x, y) __test_and_change_bit(x, y)
-#endif /* __ASM_GENERIC_BITOPS_H */
+#endif /* _ASM_BITOPS_H_ */
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index eaf60e0fe4..97e6c00689 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -3,6 +3,8 @@ config PPC
select HAVE_CONFIGURABLE_TEXT_BASE
select HAS_KALLSYMS
select HAS_MODULES
+ select HAS_CACHE
+ select GENERIC_FIND_NEXT_BIT
select OFTREE
default y
diff --git a/arch/ppc/include/asm/bitops.h b/arch/ppc/include/asm/bitops.h
index eea9e0c430..c4ed2de65f 100644
--- a/arch/ppc/include/asm/bitops.h
+++ b/arch/ppc/include/asm/bitops.h
@@ -153,6 +153,11 @@ extern __inline__ int ffz(unsigned int x)
return __ilog2(x & -x);
}
+static __inline__ int __ffs(unsigned long x)
+{
+ return __ilog2(x & -x);
+}
+
/*
* fls: find last (most-significant) bit set.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
@@ -182,49 +187,7 @@ extern __inline__ int ffs(int x)
#endif /* __KERNEL__ */
-/*
- * This implementation of find_{first,next}_zero_bit was stolen from
- * Linus' asm-alpha/bitops.h.
- */
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-extern __inline__ unsigned long find_next_zero_bit(void * addr,
- unsigned long size, unsigned long offset)
-{
- unsigned int * p = ((unsigned int *) addr) + (offset >> 5);
- unsigned int result = offset & ~31UL;
- unsigned int tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *p++;
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (tmp != ~0U)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size >= 32) {
- if ((tmp = *p++) != ~0U)
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
+#include <asm-generic/bitops/find.h>
#define _EXT2_HAVE_ASM_BITOPS_
diff --git a/arch/sandbox/include/asm/bitops.h b/arch/sandbox/include/asm/bitops.h
index 447023da63..e77ab83202 100644
--- a/arch/sandbox/include/asm/bitops.h
+++ b/arch/sandbox/include/asm/bitops.h
@@ -1,15 +1,28 @@
-#ifndef _SANDBOX_BITOPS_H
-#define _SANDBOX_BITOPS_H
+/*
+ * 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.
+ *
+ *
+ */
+
+#ifndef _ASM_BITOPS_H_
+#define _ASM_BITOPS_H_
-/* nothing but the defaults.. */
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/ffz.h>
-#include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ops.h>
#define set_bit(x, y) __set_bit(x, y)
@@ -19,4 +32,4 @@
#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y)
#define test_and_change_bit(x, y) __test_and_change_bit(x, y)
-#endif
+#endif /* _ASM_BITOPS_H_ */
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index d8d7f0e651..346640dcda 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -20,6 +20,7 @@ config X86
select HAS_MODULES
select HAVE_CONFIGURABLE_MEMORY_LAYOUT
select HAVE_CONFIGURABLE_TEXT_BASE
+ select GENERIC_FIND_NEXT_BIT
default y
config X86_BOOTLOADER
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index d741e44d4a..e77ab83202 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -12,22 +12,24 @@
*
*/
-/**
- * @file
- * @brief x86 bit operations
- *
- * This file is required only to make all sources happy including
- * 'linux/bitops.h'
- */
-
-#ifndef _ASM_X86_BITOPS_H_
-#define _ASM_X86_BITOPS_H_
+#ifndef _ASM_BITOPS_H_
+#define _ASM_BITOPS_H_
-#define BITS_PER_LONG 32
-
-#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/__ffs.h>
-#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ops.h>
+
+#define set_bit(x, y) __set_bit(x, y)
+#define clear_bit(x, y) __clear_bit(x, y)
+#define change_bit(x, y) __change_bit(x, y)
+#define test_and_set_bit(x, y) __test_and_set_bit(x, y)
+#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y)
+#define test_and_change_bit(x, y) __test_and_change_bit(x, y)
-#endif /* _ASM_X86_BITOPS_H_ */
+#endif /* _ASM_BITOPS_H_ */
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
index d473405ff9..b3fd1f644b 100644
--- a/arch/x86/include/asm/types.h
+++ b/arch/x86/include/asm/types.h
@@ -41,6 +41,8 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define BITS_PER_LONG 32
+
#endif /* __ASSEMBLY__ */
#endif /* __ASM_X86_TYPES_H */
diff --git a/common/Kconfig b/common/Kconfig
index d3f9801647..d3d9b884cf 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -25,6 +25,22 @@ config ENV_HANDLING
select CRC32
bool
+config HAS_CACHE
+ bool
+ help
+ This allows you do run "make ARCH=sandbox allyesconfig".
+
+ Drivers that depend on a cache implementation can depend on this
+ config, so that you don't get a compilation error.
+
+config HAS_DMA
+ bool
+ help
+ This allows you do run "make ARCH=sandbox allyesconfig".
+
+ Drivers that depend on a DMA implementation can depend on this
+ config, so that you don't get a compilation error.
+
config GENERIC_GPIO
bool
@@ -657,6 +673,7 @@ config BAREBOXENV_TARGET
config BAREBOXCRC32_TARGET
bool
prompt "build bareboxcrc32 tool for target"
+ depends on !SANDBOX
help
'bareboxcrc32' is a userspacetool to generate the crc32 checksums the same way
barebox does. Say yes here to build it for the target.
@@ -691,6 +708,7 @@ config COMPILE_LOGLEVEL
5 normal but significant condition (notice)
6 informational (info)
7 debug-level messages (debug)
+ 8 verbose debug messages (vdebug)
config DEFAULT_LOGLEVEL
int "default loglevel"
@@ -707,6 +725,7 @@ config DEFAULT_LOGLEVEL
5 normal but significant condition (notice)
6 informational (info)
7 debug-level messages (debug)
+ 8 verbose debug messages (vdebug)
config DEBUG_INFO
bool
diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index d831e90fe3..499ec93c28 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -1712,29 +1712,6 @@ void *memalign(size_t alignment, size_t bytes)
return chunk2mem(p);
}
-#if 0
-/*
- * valloc just invokes memalign with alignment argument equal
- * to the page size of the system (or as near to this as can
- * be figured out from all the includes/defines above.)
- */
-void *valloc(size_t bytes)
-{
- return memalign(malloc_getpagesize, bytes);
-}
-#endif
-
-/*
- * pvalloc just invokes valloc for the nearest pagesize
- * that will accommodate request
- */
-void *pvalloc (size_t bytes)
-{
- size_t pagesize = malloc_getpagesize;
-
- return memalign(pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
-}
-
/*
*
* calloc calls malloc, then zeroes out the allocated chunk.
@@ -1774,115 +1751,6 @@ void *calloc(size_t n, size_t elem_size)
}
}
-/*
- *
- * cfree just calls free. It is needed/defined on some systems
- * that pair it with calloc, presumably for odd historical reasons.
- */
-#if !defined(INTERNAL_LINUX_C_LIB) || !defined(__ELF__)
-void cfree(void *mem)
-{
- free(mem);
-}
-#endif
-
-/*
- Malloc_trim gives memory back to the system (via negative
- arguments to sbrk) if there is unused memory at the `high' end of
- the malloc pool. You can call this after freeing large blocks of
- memory to potentially reduce the system-level memory requirements
- of a program. However, it cannot guarantee to reduce memory. Under
- some allocation patterns, some large free blocks of memory will be
- locked between two used chunks, so they cannot be given back to
- the system.
-
- The `pad' argument to malloc_trim represents the amount of free
- trailing space to leave untrimmed. If this argument is zero,
- only the minimum amount of memory to maintain internal data
- structures will be left (one page or less). Non-zero arguments
- can be supplied to maintain enough trailing space to service
- future expected allocations without having to re-obtain memory
- from the system.
-
- Malloc_trim returns 1 if it actually released any memory, else 0.
-*/
-#ifdef USE_MALLOC_TRIM
-int malloc_trim(size_t pad)
-{
- long top_size; /* Amount of top-most memory */
- long extra; /* Amount to release */
- char *current_brk; /* address returned by pre-check sbrk call */
- char *new_brk; /* address returned by negative sbrk call */
-
- unsigned long pagesz = malloc_getpagesize;
-
- top_size = chunksize(top);
- extra = ((top_size - pad - MINSIZE + (pagesz - 1)) / pagesz -
- 1) * pagesz;
-
- if (extra < (long)pagesz) /* Not enough memory to release */
- return 0;
-
- else {
- /* Test to make sure no one else called sbrk */
- current_brk = (char*)(sbrk(0));
- if (current_brk != (char*)(top) + top_size)
- return 0; /* Apparently we don't own memory; must fail */
-
- else {
- new_brk = (char *) (sbrk(-extra));
-
- if (new_brk == (char*)(NULL)) { /* sbrk failed? */
- /* Try to figure out what we have */
- current_brk = (char*)(sbrk (0));
- top_size = current_brk - (char*) top;
- if (top_size >= (long)MINSIZE) { /* if not, we are very very dead! */
- sbrked_mem = current_brk - sbrk_base;
- set_head(top, top_size | PREV_INUSE);
- }
- return 0;
- }
-
- else {
- /* Success. Adjust top accordingly. */
- set_head(top, (top_size - extra) | PREV_INUSE);
- sbrked_mem -= extra;
- return 1;
- }
- }
- }
-}
-#endif
-
-/*
- * malloc_usable_size:
- *
- * This routine tells you how many bytes you can actually use in an
- * allocated chunk, which may be more than you requested (although
- * often not). You can use this many bytes without worrying about
- * overwriting other allocated objects. Not a particularly great
- * programming practice, but still sometimes useful.
- */
-size_t malloc_usable_size(void *mem)
-{
- mchunkptr p;
-
- if (!mem)
- return 0;
- else {
- p = mem2chunk(mem);
- if (!chunk_is_mmapped(p)) {
- if (!inuse(p))
- return 0;
- return chunksize(p) - SIZE_SZ;
- }
- return chunksize(p) - 2 * SIZE_SZ;
- }
-}
-
-
-
-
/* Utility to update current_mallinfo for malloc_stats and mallinfo() */
#ifdef CONFIG_CMD_MEMINFO
@@ -1956,43 +1824,6 @@ void malloc_stats(void)
#endif /* CONFIG_CMD_MEMINFO */
/*
- mallopt:
-
- mallopt is the general SVID/XPG interface to tunable parameters.
- The format is to provide a (parameter-number, parameter-value) pair.
- mallopt then sets the corresponding parameter to the argument
- value if it can (i.e., so long as the value is meaningful),
- and returns 1 if successful else 0.
-
- See descriptions of tunable parameters above.
-*/
-#ifndef __BAREBOX__
-int mallopt(int param_number, int value)
-{
- switch (param_number) {
- case M_TRIM_THRESHOLD:
- trim_threshold = value;
- return 1;
- case M_TOP_PAD:
- top_pad = value;
- return 1;
- case M_MMAP_THRESHOLD:
- mmap_threshold = value;
- return 1;
- case M_MMAP_MAX:
- if (value != 0)
- return 0;
- else
- n_mmaps_max = value;
- return 1;
-
- default:
- return 0;
- }
-}
-#endif
-
-/*
History:
diff --git a/common/hush.c b/common/hush.c
index 09d9326c85..b23b3f6633 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1725,7 +1725,7 @@ static int parse_stream_outer(struct p_context *ctx, struct in_str *inp, int fla
b_free(&temp);
} while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */
- return (code != 0) ? 1 : 0;
+ return code;
}
static int parse_string_outer(struct p_context *ctx, const char *s, int flag)
diff --git a/common/resource.c b/common/resource.c
index 1ea2a7522a..fe4680e3bd 100644
--- a/common/resource.c
+++ b/common/resource.c
@@ -71,7 +71,7 @@ struct resource *__request_region(struct resource *parent,
goto ok;
if (start > r->end)
continue;
- pr_warn("%s: 0x%08llx:0x%08llx conflicts with 0x%08llx:0x%08llx\n",
+ debug("%s: 0x%08llx:0x%08llx conflicts with 0x%08llx:0x%08llx\n",
__func__,
(unsigned long long)start,
(unsigned long long)end,
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 9830cc07a8..7850e4a9c9 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -34,6 +34,7 @@ config DISK_ATA
config DISK_AHCI
bool "AHCI support"
+ depends on HAS_DMA
select DISK_ATA
config DISK_AHCI_IMX
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 67783daabb..506a9668a9 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -186,7 +186,7 @@ static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
clk_set_rate(clk_get_parent(clk), best_parent_rate);
} else {
- div = parent_rate / rate;
+ div = DIV_ROUND_UP(parent_rate, rate);
}
value = _get_val(divider, div);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index f7108c2605..adc952b043 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1132,7 +1132,7 @@ static struct platform_device_id omap_i2c_ids[] = {
},
};
-static __maybe_unused struct of_device_id omap_spi_dt_ids[] = {
+static __maybe_unused struct of_device_id omap_i2c_dt_ids[] = {
{
.compatible = "ti,omap3-i2c",
.data = (unsigned long)&omap3_data,
@@ -1148,7 +1148,7 @@ static struct driver_d omap_i2c_driver = {
.probe = i2c_omap_probe,
.name = DRIVER_NAME,
.id_table = omap_i2c_ids,
- .of_compatible = DRV_OF_COMPAT(omap_spi_dt_ids),
+ .of_compatible = DRV_OF_COMPAT(omap_i2c_dt_ids),
};
device_platform_driver(omap_i2c_driver);
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 3d9016b3fa..07545ed310 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -32,7 +32,7 @@ config KEYBOARD_IMX_KEYPAD
config KEYBOARD_QT1070
tristate "Atmel AT42QT1070 Touch Sensor Chip"
- depends on I2C
+ depends on I2C && GENERIC_GPIO
select POLLER
help
Say Y here if you want to use Atmel AT42QT1070 QTouch
diff --git a/drivers/led/led-gpio.c b/drivers/led/led-gpio.c
index 7bb3b49953..a1a661724d 100644
--- a/drivers/led/led-gpio.c
+++ b/drivers/led/led-gpio.c
@@ -206,13 +206,17 @@ static int led_gpio_of_probe(struct device_d *dev)
struct gpio_led *gled;
enum of_gpio_flags flags;
int gpio;
+ const char *label;
gpio = of_get_named_gpio_flags(child, "gpios", 0, &flags);
if (gpio < 0)
continue;
gled = xzalloc(sizeof(*gled));
- gled->led.name = xstrdup(child->name);
+ if (of_property_read_string(child, "label", &label))
+ label = child->name;
+ gled->led.name = xstrdup(label);
+
gled->gpio = gpio;
gled->active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index ce6e590aaf..8221632ecb 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -616,6 +616,9 @@ retry_scr:
break;
}
+ if (mci->scr[0] & SD_DATA_4BIT)
+ mci->card_caps |= MMC_CAP_4_BIT_DATA;
+
/* Version 1.0 doesn't support switching */
if (mci->version == SD_VERSION_1_0)
return 0;
@@ -634,9 +637,6 @@ retry_scr:
break;
}
- if (mci->scr[0] & SD_DATA_4BIT)
- mci->card_caps |= MMC_CAP_4_BIT_DATA;
-
/* If high-speed isn't supported, we return */
if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
return 0;
diff --git a/drivers/mfd/mc34704.c b/drivers/mfd/mc34704.c
index 9afab07a2d..3dc85f5474 100644
--- a/drivers/mfd/mc34704.c
+++ b/drivers/mfd/mc34704.c
@@ -123,9 +123,15 @@ static int mc34704_probe(struct device_d *dev)
return 0;
}
+static __maybe_unused struct of_device_id mc34704_dt_ids[] = {
+ { .compatible = "fsl,mc34704", },
+ { }
+};
+
static struct driver_d mc34704_driver = {
.name = DRIVERNAME,
.probe = mc34704_probe,
+ .of_compatible = DRV_OF_COMPAT(mc34704_dt_ids),
};
static int mc34704_init(void)
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 2e9f61f119..337e2256e3 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -796,7 +796,9 @@ static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
switch (mtd->writesize) {
case 2048:
case 4096:
- host->pmecc_degree = PMECC_GF_DIMENSION_13;
+ case 8192:
+ host->pmecc_degree = (sector_size == 512) ?
+ PMECC_GF_DIMENSION_13 : PMECC_GF_DIMENSION_14;
host->pmecc_cw_len = (1 << host->pmecc_degree) - 1;
host->pmecc_sector_number = mtd->writesize / sector_size;
host->pmecc_bytes_per_sector = pmecc_get_ecc_bytes(
@@ -1162,7 +1164,12 @@ static int __init atmel_nand_probe(struct device_d *dev)
nand_chip->ecc.mode = NAND_ECC_HW;
}
- nand_chip->chip_delay = 20; /* 20us command delay time */
+ nand_chip->chip_delay = 40; /* 40us command delay time */
+
+ if (IS_ENABLED(CONFIG_NAND_ECC_BCH) &&
+ pdata->ecc_mode == NAND_ECC_SOFT_BCH) {
+ nand_chip->ecc.mode = NAND_ECC_SOFT_BCH;
+ }
if (host->board->bus_width_16) { /* 16-bit bus width */
nand_chip->options |= NAND_BUSWIDTH_16;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 43409a8f8c..c99fcc8316 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -34,6 +34,7 @@ config DRIVER_NET_AR231X
config DRIVER_NET_ARC_EMAC
bool "ARC Ethernet MAC driver"
+ depends on HAS_DMA
select PHYLIB
help
This option enables support for the ARC EMAC ethernet
@@ -46,6 +47,7 @@ config DRIVER_NET_AT91_ETHER
config DRIVER_NET_CALXEDA_XGMAC
bool "Calxeda xgmac"
+ depends on HAS_DMA
config DRIVER_NET_CS8900
bool "cs8900 ethernet driver"
@@ -63,6 +65,7 @@ config DRIVER_NET_DAVINCI_EMAC
config DRIVER_NET_DESIGNWARE
bool "Designware Universal MAC ethernet driver"
+ depends on HAS_DMA
select PHYLIB
help
This option enables support for the Synopsys
@@ -94,6 +97,7 @@ config DRIVER_NET_EP93XX
config DRIVER_NET_ETHOC
bool "OpenCores ethernet MAC driver"
+ depends on HAS_CACHE
select PHYLIB
help
This option enables support for the OpenCores 10/100 Mbps
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 3370b5cdb3..a308035ff2 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -199,19 +199,19 @@ static int gfar_open(struct eth_device *edev)
/* Initialize the Rx Buffer descriptors */
for (ix = 0; ix < RX_BUF_CNT; ix++) {
- priv->rxbd[ix].status = RXBD_EMPTY;
- priv->rxbd[ix].length = 0;
- priv->rxbd[ix].bufPtr = (uint) NetRxPackets[ix];
+ out_be16(&priv->rxbd[ix].status, RXBD_EMPTY);
+ out_be16(&priv->rxbd[ix].length, 0);
+ out_be32(&priv->rxbd[ix].bufPtr, (uint) NetRxPackets[ix]);
}
- priv->rxbd[RX_BUF_CNT - 1].status |= RXBD_WRAP;
+ out_be16(&priv->rxbd[RX_BUF_CNT - 1].status, RXBD_EMPTY | RXBD_WRAP);
/* Initialize the TX Buffer Descriptors */
for (ix = 0; ix < TX_BUF_CNT; ix++) {
- priv->txbd[ix].status = 0;
- priv->txbd[ix].length = 0;
- priv->txbd[ix].bufPtr = 0;
+ out_be16(&priv->txbd[ix].status, 0);
+ out_be16(&priv->txbd[ix].length, 0);
+ out_be32(&priv->txbd[ix].bufPtr, 0);
}
- priv->txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
+ out_be16(&priv->txbd[TX_BUF_CNT - 1].status, TXBD_WRAP);
/* Enable Transmit and Receive */
setbits_be32(regs + GFAR_MACCFG1_OFFSET, GFAR_MACCFG1_RX_EN |
@@ -366,30 +366,32 @@ static int gfar_send(struct eth_device *edev, void *packet, int length)
struct device_d *dev = edev->parent;
uint64_t start;
uint tidx;
+ uint16_t status;
tidx = priv->txidx;
- priv->txbd[tidx].bufPtr = (uint) packet;
- priv->txbd[tidx].length = length;
- priv->txbd[tidx].status |= (TXBD_READY | TXBD_LAST |
- TXBD_CRC | TXBD_INTERRUPT);
+ out_be32(&priv->txbd[tidx].bufPtr, (u32) packet);
+ out_be16(&priv->txbd[tidx].length, length);
+ out_be16(&priv->txbd[tidx].status,
+ in_be16(&priv->txbd[tidx].status) |
+ (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));
/* Tell the DMA to go */
out_be32(regs + GFAR_TSTAT_OFFSET, GFAR_TSTAT_CLEAR_THALT);
/* Wait for buffer to be transmitted */
start = get_time_ns();
- while (priv->txbd[tidx].status & TXBD_READY) {
+ while (in_be16(&priv->txbd[tidx].status) & TXBD_READY) {
if (is_timeout(start, 5 * MSECOND)) {
break;
}
}
- if (priv->txbd[tidx].status & TXBD_READY) {
- dev_err(dev, "tx timeout: 0x%x\n", priv->txbd[tidx].status);
+ status = in_be16(&priv->txbd[tidx].status);
+ if (status & TXBD_READY) {
+ dev_err(dev, "tx timeout: 0x%x\n", status);
return -EBUSY;
- }
- else if (priv->txbd[tidx].status & TXBD_STATS) {
- dev_err(dev, "TX error: 0x%x\n", priv->txbd[tidx].status);
+ } else if (status & TXBD_STATS) {
+ dev_err(dev, "TX error: 0x%x\n", status);
return -EIO;
}
@@ -403,31 +405,28 @@ static int gfar_recv(struct eth_device *edev)
struct gfar_private *priv = edev->priv;
struct device_d *dev = edev->parent;
void __iomem *regs = priv->regs;
- int length;
+ uint16_t status, length;
- if (priv->rxbd[priv->rxidx].status & RXBD_EMPTY) {
- return 0; /* no data */
- }
+ if (in_be16(&priv->rxbd[priv->rxidx].status) & RXBD_EMPTY)
+ return 0;
- length = priv->rxbd[priv->rxidx].length;
+ length = in_be16(&priv->rxbd[priv->rxidx].length);
/* Send the packet up if there were no errors */
- if (!(priv->rxbd[priv->rxidx].status & RXBD_STATS)) {
+ status = in_be16(&priv->rxbd[priv->rxidx].status);
+ if (!(status & RXBD_STATS))
net_receive(edev, NetRxPackets[priv->rxidx], length - 4);
- } else {
- dev_err(dev, "Got error %x\n",
- (priv->rxbd[priv->rxidx].status & RXBD_STATS));
- }
+ else
+ dev_err(dev, "Got error %x\n", status & RXBD_STATS);
- priv->rxbd[priv->rxidx].length = 0;
+ out_be16(&priv->rxbd[priv->rxidx].length, 0);
+ status = RXBD_EMPTY;
/* Set the wrap bit if this is the last element in the list */
if ((priv->rxidx + 1) == RX_BUF_CNT)
- priv->rxbd[priv->rxidx].status = RXBD_WRAP;
- else
- priv->rxbd[priv->rxidx].status = 0;
+ status |= RXBD_WRAP;
- priv->rxbd[priv->rxidx].status |= RXBD_EMPTY;
+ out_be16(&priv->rxbd[priv->rxidx].status, status);
priv->rxidx = (priv->rxidx + 1) % RX_BUF_CNT;
if (in_be32(regs + GFAR_IEVENT_OFFSET) & GFAR_IEVENT_BSY) {
@@ -517,8 +516,9 @@ static int gfar_probe(struct device_d *dev)
size = ((TX_BUF_CNT * sizeof(struct txbd8)) +
(RX_BUF_CNT * sizeof(struct rxbd8))) + BUF_ALIGN;
p = (char *)xmemalign(BUF_ALIGN, size);
- priv->txbd = (struct txbd8 *)p;
- priv->rxbd = (struct rxbd8 *)(p + (TX_BUF_CNT * sizeof(struct txbd8)));
+ priv->txbd = (struct txbd8 __iomem *)p;
+ priv->rxbd = (struct rxbd8 __iomem *)(p +
+ (TX_BUF_CNT * sizeof(struct txbd8)));
edev->priv = priv;
edev->init = gfar_init;
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 1aac47907a..c0b9763476 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -188,15 +188,15 @@
#define RXBD_STATS 0x003f
struct txbd8 {
- ushort status; /* Status Fields */
- ushort length; /* Buffer length */
- uint bufPtr; /* Buffer Pointer */
+ uint16_t status; /* Status Fields */
+ uint16_t length; /* Buffer length */
+ uint32_t bufPtr; /* Buffer Pointer */
};
struct rxbd8 {
- ushort status; /* Status Fields */
- ushort length; /* Buffer Length */
- uint bufPtr; /* Buffer Pointer */
+ uint16_t status; /* Status Fields */
+ uint16_t length; /* Buffer Length */
+ uint32_t bufPtr; /* Buffer Pointer */
};
/* eTSEC general control and status registers */
@@ -275,8 +275,8 @@ struct gfar_private {
struct gfar_phy *gfar_mdio;
struct gfar_phy *gfar_tbi;
struct phy_info *phyinfo;
- volatile struct txbd8 *txbd;
- volatile struct rxbd8 *rxbd;
+ struct txbd8 __iomem *txbd;
+ struct rxbd8 __iomem *rxbd;
uint txidx;
uint rxidx;
uint phyaddr;
diff --git a/drivers/of/of_mtd.c b/drivers/of/of_mtd.c
index 239f1f9892..97f3095740 100644
--- a/drivers/of/of_mtd.c
+++ b/drivers/of/of_mtd.c
@@ -20,6 +20,8 @@ static const char *nand_ecc_modes[] = {
[NAND_ECC_SOFT] = "soft",
[NAND_ECC_HW] = "hw",
[NAND_ECC_HW_SYNDROME] = "hw_syndrome",
+ [NAND_ECC_HW_OOB_FIRST] = "hw_oob_first",
+ [NAND_ECC_SOFT_BCH] = "soft_bch",
};
/**
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 55f87a45ba..493b18a898 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -6,6 +6,7 @@ if REGULATOR
config REGULATOR_FIXED
bool "fixed/gpio regulator"
+ depends on GENERIC_GPIO
help
This enables a simple fixed regulator. It is used for regulators
which are not software controllable or controllable via gpio.
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 7e649199bf..2515d3e70d 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -27,6 +27,7 @@
struct regulator_fixed {
int gpio;
int active_low;
+ int always_on;
struct regulator_dev rdev;
};
@@ -44,6 +45,9 @@ static int regulator_fixed_disable(struct regulator_dev *rdev)
{
struct regulator_fixed *fix = container_of(rdev, struct regulator_fixed, rdev);
+ if (fix->always_on)
+ return 0;
+
if (!gpio_is_valid(fix->gpio))
return 0;
@@ -79,6 +83,11 @@ static int regulator_fixed_probe(struct device_d *dev)
fix->rdev.ops = &fixed_ops;
+ if (of_find_property(dev->device_node, "regulator-always-on", NULL)) {
+ fix->always_on = 1;
+ regulator_fixed_enable(&fix->rdev);
+ }
+
ret = of_regulator_register(&fix->rdev, dev->device_node);
if (ret)
return ret;
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 375ec65141..2f9353edca 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -109,14 +109,6 @@ static unsigned n_ports;
#define GS_CLOSE_TIMEOUT 15 /* seconds */
-#ifdef VERBOSE_DEBUG
-#define pr_vdebug(fmt, arg...) \
- pr_debug(fmt, ##arg)
-#else
-#define pr_vdebug(fmt, arg...) \
- ({ if (0) pr_debug(fmt, ##arg); })
-#endif
-
static unsigned gs_start_rx(struct gs_port *port)
{
struct list_head *pool = &port->read_pool;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 5a3ce40705..a69e758910 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -1,5 +1,6 @@
config USB_EHCI
bool "EHCI driver"
+ depends on HAS_DMA
config USB_EHCI_OMAP
depends on ARCH_OMAP3
diff --git a/drivers/video/imx-ipu-v3/Kconfig b/drivers/video/imx-ipu-v3/Kconfig
index 3d656e5193..368167bfb6 100644
--- a/drivers/video/imx-ipu-v3/Kconfig
+++ b/drivers/video/imx-ipu-v3/Kconfig
@@ -1,5 +1,6 @@
config DRIVER_VIDEO_IMX_IPUV3
bool "i.MX IPUv3 driver"
+ depends on ARCH_IMX
help
Support the IPUv3 found on Freescale i.MX51/53/6 SoCs
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 2e2900c10f..7f7b02e306 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -21,4 +21,11 @@ config WATCHDOG_IMX
depends on ARCH_IMX
help
Add support for watchdog found on Freescale i.MX SoCs.
+
+config WATCHDOG_JZ4740
+ bool "Ingenic jz4740 SoC hardware watchdog"
+ depends on MACH_MIPS_XBURST
+ help
+ Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
+
endif
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index f522b88708..865fc477b1 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_WATCHDOG) += wd_core.o
obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o
+obj-$(CONFIG_WATCHDOG_JZ4740) += jz4740.o
obj-$(CONFIG_WATCHDOG_IMX_RESET_SOURCE) += imxwd.o
diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index 63c5605c99..31c3d0d853 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -159,6 +159,10 @@ static int imx_wd_probe(struct device_d *dev)
priv = xzalloc(sizeof(struct imx_wd));
priv->base = dev_request_mem_region(dev, 0);
+ if (!priv->base) {
+ dev_err(dev, "could not get memory region\n");
+ return -ENODEV;
+ }
priv->set_timeout = fn;
priv->wd.set_timeout = imx_watchdog_set_timeout;
priv->dev = dev;
diff --git a/drivers/watchdog/jz4740.c b/drivers/watchdog/jz4740.c
new file mode 100644
index 0000000000..8ac51e060a
--- /dev/null
+++ b/drivers/watchdog/jz4740.c
@@ -0,0 +1,102 @@
+/*
+ * JZ4740 Watchdog driver
+ *
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * Based on jz4740_wdt.c from linux-3.15.
+ *
+ * Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net>
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+
+#define JZ_REG_WDT_TIMER_DATA 0x0
+#define JZ_REG_WDT_COUNTER_ENABLE 0x4
+#define JZ_REG_WDT_TIMER_COUNTER 0x8
+#define JZ_REG_WDT_TIMER_CONTROL 0xC
+
+#define JZ_WDT_CLOCK_PCLK 0x1
+#define JZ_WDT_CLOCK_RTC 0x2
+#define JZ_WDT_CLOCK_EXT 0x4
+
+#define JZ_WDT_CLOCK_DIV_SHIFT 3
+
+#define JZ_WDT_CLOCK_DIV_1 (0 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_4 (1 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_16 (2 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_64 (3 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_256 (4 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT)
+
+#define JZ_EXTAL 24000000
+
+struct jz4740_wdt_drvdata {
+ void __iomem *base;
+};
+
+static struct jz4740_wdt_drvdata *reset_wd;
+
+void __noreturn reset_cpu(unsigned long addr)
+{
+ if (reset_wd) {
+ void __iomem *base = reset_wd->base;
+
+ writew(JZ_WDT_CLOCK_DIV_4 | JZ_WDT_CLOCK_EXT,
+ base + JZ_REG_WDT_TIMER_CONTROL);
+ writew(0, base + JZ_REG_WDT_TIMER_COUNTER);
+
+ /* reset after 4ms */
+ writew(JZ_EXTAL / 1000, base + JZ_REG_WDT_TIMER_DATA);
+
+ /* start wdt */
+ writeb(0x1, base + JZ_REG_WDT_COUNTER_ENABLE);
+
+ mdelay(1000);
+ } else
+ pr_err("%s: can't reset cpu\n", __func__);
+
+ hang();
+}
+EXPORT_SYMBOL(reset_cpu);
+
+static int jz4740_wdt_probe(struct device_d *dev)
+{
+ struct jz4740_wdt_drvdata *priv;
+
+ priv = xzalloc(sizeof(struct jz4740_wdt_drvdata));
+ priv->base = dev_request_mem_region(dev, 0);
+ if (!priv->base) {
+ dev_err(dev, "could not get memory region\n");
+ return -ENODEV;
+ }
+
+ if (!reset_wd)
+ reset_wd = priv;
+
+ dev->priv = priv;
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id jz4740_wdt_dt_ids[] = {
+ {
+ .compatible = "ingenic,jz4740-wdt",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d jz4740_wdt_driver = {
+ .name = "jz4740-wdt",
+ .probe = jz4740_wdt_probe,
+ .of_compatible = DRV_OF_COMPAT(jz4740_wdt_dt_ids),
+};
+device_platform_driver(jz4740_wdt_driver);
diff --git a/include/asm-generic/bitops/hweight.h b/include/asm-generic/bitops/hweight.h
index af9770de4e..7268c8b9ab 100644
--- a/include/asm-generic/bitops/hweight.h
+++ b/include/asm-generic/bitops/hweight.h
@@ -32,4 +32,19 @@ static inline unsigned int hweight8(unsigned int w)
return (res & 0x0F) + ((res >> 4) & 0x0F);
}
+static inline unsigned long hweight64(__u64 w)
+{
+#if BITS_PER_LONG == 32
+ return hweight32((unsigned int)(w >> 32)) +
+ hweight32((unsigned int)w);
+#elif BITS_PER_LONG == 64
+ __u64 res = w - ((w >> 1) & 0x5555555555555555ul);
+ res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
+ res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
+ res = res + (res >> 8);
+ res = res + (res >> 16);
+ return (res + (res >> 32)) & 0x00000000000000FFul;
+#endif
+}
+
#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
diff --git a/include/bbu.h b/include/bbu.h
index 095eebcf4a..adb52b0dec 100644
--- a/include/bbu.h
+++ b/include/bbu.h
@@ -1,6 +1,8 @@
#ifndef __INCLUDE_BBU_H
#define __INCLUDE_BBU_H
+#include <asm-generic/errno.h>
+
struct bbu_data {
#define BBU_FLAG_FORCE (1 << 0)
#define BBU_FLAG_YES (1 << 1)
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
new file mode 100644
index 0000000000..4b98521a83
--- /dev/null
+++ b/include/linux/bitmap.h
@@ -0,0 +1,285 @@
+#ifndef __LINUX_BITMAP_H
+#define __LINUX_BITMAP_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+/*
+ * bitmaps provide bit arrays that consume one or more unsigned
+ * longs. The bitmap interface and available operations are listed
+ * here, in bitmap.h
+ *
+ * Function implementations generic to all architectures are in
+ * lib/bitmap.c. Functions implementations that are architecture
+ * specific are in various include/asm-<arch>/bitops.h headers
+ * and other arch/<arch> specific files.
+ *
+ * See lib/bitmap.c for more details.
+ */
+
+/*
+ * The available bitmap operations and their rough meaning in the
+ * case that the bitmap is a single unsigned long are thus:
+ *
+ * Note that nbits should be always a compile time evaluable constant.
+ * Otherwise many inlines will generate horrible code.
+ *
+ * bitmap_zero(dst, nbits) *dst = 0UL
+ * bitmap_fill(dst, nbits) *dst = ~0UL
+ * bitmap_copy(dst, src, nbits) *dst = *src
+ * bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2
+ * bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2
+ * bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2
+ * bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2)
+ * bitmap_complement(dst, src, nbits) *dst = ~(*src)
+ * bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal?
+ * bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap?
+ * bitmap_subset(src1, src2, nbits) Is *src1 a subset of *src2?
+ * bitmap_empty(src, nbits) Are all bits zero in *src?
+ * bitmap_full(src, nbits) Are all bits set in *src?
+ * bitmap_weight(src, nbits) Hamming Weight: number set bits
+ * bitmap_set(dst, pos, nbits) Set specified bit area
+ * bitmap_clear(dst, pos, nbits) Clear specified bit area
+ * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
+ * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
+ * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
+ * bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
+ * bitmap_bitremap(oldbit, old, new, nbits) newbit = map(old, new)(oldbit)
+ * bitmap_onto(dst, orig, relmap, nbits) *dst = orig relative to relmap
+ * bitmap_fold(dst, orig, sz, nbits) dst bits = orig bits mod sz
+ * bitmap_find_free_region(bitmap, bits, order) Find and allocate bit region
+ * bitmap_release_region(bitmap, pos, order) Free specified bit region
+ * bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region
+ */
+
+/*
+ * Also the following operations in asm/bitops.h apply to bitmaps.
+ *
+ * set_bit(bit, addr) *addr |= bit
+ * clear_bit(bit, addr) *addr &= ~bit
+ * change_bit(bit, addr) *addr ^= bit
+ * test_bit(bit, addr) Is bit set in *addr?
+ * test_and_set_bit(bit, addr) Set bit and return old value
+ * test_and_clear_bit(bit, addr) Clear bit and return old value
+ * test_and_change_bit(bit, addr) Change bit and return old value
+ * find_first_zero_bit(addr, nbits) Position first zero bit in *addr
+ * find_first_bit(addr, nbits) Position first set bit in *addr
+ * find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit
+ * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
+ */
+
+/*
+ * The DECLARE_BITMAP(name,bits) macro, in linux/types.h, can be used
+ * to declare an array named 'name' of just enough unsigned longs to
+ * contain all bit positions from 0 to 'bits' - 1.
+ */
+
+/*
+ * lib/bitmap.c provides these functions:
+ */
+
+extern int __bitmap_empty(const unsigned long *bitmap, int bits);
+extern int __bitmap_full(const unsigned long *bitmap, int bits);
+extern int __bitmap_equal(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern void __bitmap_complement(unsigned long *dst, const unsigned long *src,
+ int bits);
+extern void __bitmap_shift_right(unsigned long *dst,
+ const unsigned long *src, int shift, int bits);
+extern void __bitmap_shift_left(unsigned long *dst,
+ const unsigned long *src, int shift, int bits);
+extern int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern int __bitmap_intersects(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern int __bitmap_subset(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern int __bitmap_weight(const unsigned long *bitmap, int bits);
+
+extern void bitmap_set(unsigned long *map, int i, int len);
+extern void bitmap_clear(unsigned long *map, int start, int nr);
+extern unsigned long bitmap_find_next_zero_area(unsigned long *map,
+ unsigned long size,
+ unsigned long start,
+ unsigned int nr,
+ unsigned long align_mask);
+
+extern void bitmap_remap(unsigned long *dst, const unsigned long *src,
+ const unsigned long *old, const unsigned long *new, int bits);
+extern int bitmap_bitremap(int oldbit,
+ const unsigned long *old, const unsigned long *new, int bits);
+extern void bitmap_onto(unsigned long *dst, const unsigned long *orig,
+ const unsigned long *relmap, int bits);
+extern void bitmap_fold(unsigned long *dst, const unsigned long *orig,
+ int sz, int bits);
+extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
+extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
+extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
+extern void bitmap_copy_le(void *dst, const unsigned long *src, int nbits);
+extern int bitmap_ord_to_pos(const unsigned long *bitmap, int n, int bits);
+
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
+#define BITMAP_LAST_WORD_MASK(nbits) \
+( \
+ ((nbits) % BITS_PER_LONG) ? \
+ (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \
+)
+
+#define small_const_nbits(nbits) \
+ (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
+
+static inline void bitmap_zero(unsigned long *dst, int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = 0UL;
+ else {
+ int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+ memset(dst, 0, len);
+ }
+}
+
+static inline void bitmap_fill(unsigned long *dst, int nbits)
+{
+ size_t nlongs = BITS_TO_LONGS(nbits);
+ if (!small_const_nbits(nbits)) {
+ int len = (nlongs - 1) * sizeof(unsigned long);
+ memset(dst, 0xff, len);
+ }
+ dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
+}
+
+static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
+ int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = *src;
+ else {
+ int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+ memcpy(dst, src, len);
+ }
+}
+
+static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return (*dst = *src1 & *src2) != 0;
+ return __bitmap_and(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = *src1 | *src2;
+ else
+ __bitmap_or(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = *src1 ^ *src2;
+ else
+ __bitmap_xor(dst, src1, src2, nbits);
+}
+
+static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return (*dst = *src1 & ~(*src2)) != 0;
+ return __bitmap_andnot(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
+ int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits);
+ else
+ __bitmap_complement(dst, src, nbits);
+}
+
+static inline int bitmap_equal(const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_equal(src1, src2, nbits);
+}
+
+static inline int bitmap_intersects(const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
+ else
+ return __bitmap_intersects(src1, src2, nbits);
+}
+
+static inline int bitmap_subset(const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_subset(src1, src2, nbits);
+}
+
+static inline int bitmap_empty(const unsigned long *src, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_empty(src, nbits);
+}
+
+static inline int bitmap_full(const unsigned long *src, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_full(src, nbits);
+}
+
+static inline int bitmap_weight(const unsigned long *src, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));
+ return __bitmap_weight(src, nbits);
+}
+
+static inline void bitmap_shift_right(unsigned long *dst,
+ const unsigned long *src, int n, int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = *src >> n;
+ else
+ __bitmap_shift_right(dst, src, n, nbits);
+}
+
+static inline void bitmap_shift_left(unsigned long *dst,
+ const unsigned long *src, int n, int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = (*src << n) & BITMAP_LAST_WORD_MASK(nbits);
+ else
+ __bitmap_shift_left(dst, src, n, nbits);
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __LINUX_BITMAP_H */
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 127c1619fe..be5fd38bd5 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -1,15 +1,227 @@
#ifndef _LINUX_BITOPS_H
#define _LINUX_BITOPS_H
+#include <asm/types.h>
-#ifdef __BAREBOX__
+#ifdef __KERNEL__
#define BIT(nr) (1UL << (nr))
+#define BIT_ULL(nr) (1ULL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG))
+#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG)
#define BITS_PER_BYTE 8
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#endif
+/*
+ * Create a contiguous bitmask starting at bit position @l and ending at
+ * position @h. For example
+ * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
+ */
+#define GENMASK(h, l) (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l))
+#define GENMASK_ULL(h, l) (((U64_C(1) << ((h) - (l) + 1)) - 1) << (l))
+
+extern unsigned int __sw_hweight8(unsigned int w);
+extern unsigned int __sw_hweight16(unsigned int w);
+extern unsigned int __sw_hweight32(unsigned int w);
+extern unsigned long __sw_hweight64(__u64 w);
+
+/*
+ * Include this here because some architectures need generic_ffs/fls in
+ * scope
+ */
#include <asm/bitops.h>
+#define for_each_set_bit(bit, addr, size) \
+ for ((bit) = find_first_bit((addr), (size)); \
+ (bit) < (size); \
+ (bit) = find_next_bit((addr), (size), (bit) + 1))
+
+/* same as for_each_set_bit() but use bit as value to start with */
+#define for_each_set_bit_from(bit, addr, size) \
+ for ((bit) = find_next_bit((addr), (size), (bit)); \
+ (bit) < (size); \
+ (bit) = find_next_bit((addr), (size), (bit) + 1))
+
+#define for_each_clear_bit(bit, addr, size) \
+ for ((bit) = find_first_zero_bit((addr), (size)); \
+ (bit) < (size); \
+ (bit) = find_next_zero_bit((addr), (size), (bit) + 1))
+
+/* same as for_each_clear_bit() but use bit as value to start with */
+#define for_each_clear_bit_from(bit, addr, size) \
+ for ((bit) = find_next_zero_bit((addr), (size), (bit)); \
+ (bit) < (size); \
+ (bit) = find_next_zero_bit((addr), (size), (bit) + 1))
+
+static __inline__ int get_bitmask_order(unsigned int count)
+{
+ int order;
+
+ order = fls(count);
+ return order; /* We could be slightly more clever with -1 here... */
+}
+
+static __inline__ int get_count_order(unsigned int count)
+{
+ int order;
+
+ order = fls(count) - 1;
+ if (count & (count - 1))
+ order++;
+ return order;
+}
+
+static inline unsigned long hweight_long(unsigned long w)
+{
+ return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
+}
+
+/**
+ * rol64 - rotate a 64-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 rol64(__u64 word, unsigned int shift)
+{
+ return (word << shift) | (word >> (64 - shift));
+}
+
+/**
+ * ror64 - rotate a 64-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 ror64(__u64 word, unsigned int shift)
+{
+ return (word >> shift) | (word << (64 - shift));
+}
+
+/**
+ * rol32 - rotate a 32-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 rol32(__u32 word, unsigned int shift)
+{
+ return (word << shift) | (word >> (32 - shift));
+}
+
+/**
+ * ror32 - rotate a 32-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 ror32(__u32 word, unsigned int shift)
+{
+ return (word >> shift) | (word << (32 - shift));
+}
+
+/**
+ * rol16 - rotate a 16-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u16 rol16(__u16 word, unsigned int shift)
+{
+ return (word << shift) | (word >> (16 - shift));
+}
+
+/**
+ * ror16 - rotate a 16-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u16 ror16(__u16 word, unsigned int shift)
+{
+ return (word >> shift) | (word << (16 - shift));
+}
+
+/**
+ * rol8 - rotate an 8-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u8 rol8(__u8 word, unsigned int shift)
+{
+ return (word << shift) | (word >> (8 - shift));
+}
+
+/**
+ * ror8 - rotate an 8-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u8 ror8(__u8 word, unsigned int shift)
+{
+ return (word >> shift) | (word << (8 - shift));
+}
+
+/**
+ * sign_extend32 - sign extend a 32-bit value using specified bit as sign-bit
+ * @value: value to sign extend
+ * @index: 0 based bit index (0<=index<32) to sign bit
+ */
+static inline __s32 sign_extend32(__u32 value, int index)
+{
+ __u8 shift = 31 - index;
+ return (__s32)(value << shift) >> shift;
+}
+
+static inline unsigned fls_long(unsigned long l)
+{
+ if (sizeof(l) == 4)
+ return fls(l);
+ return fls64(l);
+}
+
+/**
+ * __ffs64 - find first set bit in a 64 bit word
+ * @word: The 64 bit word
+ *
+ * On 64 bit arches this is a synomyn for __ffs
+ * The result is not defined if no bits are set, so check that @word
+ * is non-zero before calling this.
+ */
+static inline unsigned long __ffs64(u64 word)
+{
+#if BITS_PER_LONG == 32
+ if (((u32)word) == 0UL)
+ return __ffs((u32)(word >> 32)) + 32;
+#elif BITS_PER_LONG != 64
+#error BITS_PER_LONG not 32 or 64
+#endif
+ return __ffs((unsigned long)word);
+}
+
+#ifdef __KERNEL__
+
+#ifndef set_mask_bits
+#define set_mask_bits(ptr, _mask, _bits) \
+({ \
+ const typeof(*ptr) mask = (_mask), bits = (_bits); \
+ typeof(*ptr) old, new; \
+ \
+ do { \
+ old = ACCESS_ONCE(*ptr); \
+ new = (old & ~mask) | bits; \
+ } while (cmpxchg(ptr, old, new) != old); \
+ \
+ new; \
+})
+#endif
+
+#ifndef find_last_bit
+/**
+ * find_last_bit - find the last set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first set bit, or size.
+ */
+extern unsigned long find_last_bit(const unsigned long *addr,
+ unsigned long size);
+#endif
+#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
index 2d68d99fa4..e59ba455e3 100644
--- a/include/linux/byteorder/generic.h
+++ b/include/linux/byteorder/generic.h
@@ -175,5 +175,34 @@ extern unsigned short int htons(unsigned short int);
#endif /* OPTIMIZE */
+static inline void le16_add_cpu(__le16 *var, u16 val)
+{
+ *var = cpu_to_le16(le16_to_cpu(*var) + val);
+}
+
+static inline void le32_add_cpu(__le32 *var, u32 val)
+{
+ *var = cpu_to_le32(le32_to_cpu(*var) + val);
+}
+
+static inline void le64_add_cpu(__le64 *var, u64 val)
+{
+ *var = cpu_to_le64(le64_to_cpu(*var) + val);
+}
+
+static inline void be16_add_cpu(__be16 *var, u16 val)
+{
+ *var = cpu_to_be16(be16_to_cpu(*var) + val);
+}
+
+static inline void be32_add_cpu(__be32 *var, u32 val)
+{
+ *var = cpu_to_be32(be32_to_cpu(*var) + val);
+}
+
+static inline void be64_add_cpu(__be64 *var, u64 val)
+{
+ *var = cpu_to_be64(be64_to_cpu(*var) + val);
+}
#endif /* _LINUX_BYTEORDER_GENERIC_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index c5ba99fe0a..d512adcea1 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -5,6 +5,19 @@
#include <linux/barebox-wrapper.h>
/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ *
+ * NOTE these functions only round to power-of-2 arguments. Use
+ * roundup/rounddown for non power-of-2-arguments.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
+/*
* min()/max()/clamp() macros that also do
* strict type-checking.. See the
* "unnecessary" pointer comparison.
diff --git a/include/linux/types.h b/include/linux/types.h
index 14f8315410..c11e148c90 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -4,6 +4,9 @@
#include <linux/posix_types.h>
#include <asm/types.h>
+#define DECLARE_BITMAP(name,bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+
#ifndef __KERNEL_STRICT_NAMES
typedef __u32 __kernel_dev_t;
diff --git a/include/malloc.h b/include/malloc.h
index 7b9b062ada..a36f3c0de4 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -3,22 +3,12 @@
#include <types.h>
-/* Public routines */
-
-void* malloc(size_t);
-void free(void*);
-void* realloc(void*, size_t);
-void* memalign(size_t, size_t);
-void* vallocc(size_t);
-void* pvalloc(size_t);
-void* calloc(size_t, size_t);
-void cfree(void*);
-int malloc_trim(size_t);
-size_t malloc_usable_size(void*);
+void *malloc(size_t);
+void free(void *);
+void *realloc(void *, size_t);
+void *memalign(size_t, size_t);
+void *calloc(size_t, size_t);
void malloc_stats(void);
-int mallopt(int, int);
-struct mallinfo mallinfo(void);
void *sbrk(ptrdiff_t increment);
-#endif
-
+#endif /* __MALLOC_H */
diff --git a/include/printk.h b/include/printk.h
index f550f07bb8..454315632b 100644
--- a/include/printk.h
+++ b/include/printk.h
@@ -9,8 +9,11 @@
#define MSG_NOTICE 5 /* normal but significant condition */
#define MSG_INFO 6 /* informational */
#define MSG_DEBUG 7 /* debug-level messages */
+#define MSG_VDEBUG 8 /* verbose debug messages */
-#ifdef DEBUG
+#ifdef VERBOSE_DEBUG
+#define LOGLEVEL MSG_VDEBUG
+#elif defined DEBUG
#define LOGLEVEL MSG_DEBUG
#else
#define LOGLEVEL CONFIG_COMPILE_LOGLEVEL
@@ -46,6 +49,8 @@ int dev_printf(int level, const struct device_d *dev, const char *format, ...)
__dev_printf(6, (dev) , format , ## arg)
#define dev_dbg(dev, format, arg...) \
__dev_printf(7, (dev) , format , ## arg)
+#define dev_vdbg(dev, format, arg...) \
+ __dev_printf(8, (dev) , format , ## arg)
#define __pr_printk(level, format, args...) \
({ \
@@ -65,5 +70,6 @@ int dev_printf(int level, const struct device_d *dev, const char *format, ...)
#define pr_info(fmt, arg...) __pr_printk(6, pr_fmt(fmt), ##arg)
#define pr_debug(fmt, arg...) __pr_printk(7, pr_fmt(fmt), ##arg)
#define debug(fmt, arg...) __pr_printk(7, pr_fmt(fmt), ##arg)
+#define pr_vdebug(fmt, arg...) __pr_printk(8, pr_fmt(fmt), ##arg)
#endif
diff --git a/lib/Makefile b/lib/Makefile
index a75653fb48..77207dc773 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -45,3 +45,4 @@ obj-y += unlink-recursive.o
obj-$(CONFIG_STMP_DEVICE) += stmp-device.o
obj-y += wchar.o
obj-y += libfile.o
+obj-y += bitmap.o
diff --git a/lib/bitmap.c b/lib/bitmap.c
new file mode 100644
index 0000000000..5be6651941
--- /dev/null
+++ b/lib/bitmap.c
@@ -0,0 +1,839 @@
+/*
+ * lib/bitmap.c
+ * Helper functions for bitmap.h.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+#include <common.h>
+#include <linux/ctype.h>
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+
+/*
+ * bitmaps provide an array of bits, implemented using an an
+ * array of unsigned longs. The number of valid bits in a
+ * given bitmap does _not_ need to be an exact multiple of
+ * BITS_PER_LONG.
+ *
+ * The possible unused bits in the last, partially used word
+ * of a bitmap are 'don't care'. The implementation makes
+ * no particular effort to keep them zero. It ensures that
+ * their value will not affect the results of any operation.
+ * The bitmap operations that return Boolean (bitmap_empty,
+ * for example) or scalar (bitmap_weight, for example) results
+ * carefully filter out these unused bits from impacting their
+ * results.
+ *
+ * These operations actually hold to a slightly stronger rule:
+ * if you don't input any bitmaps to these ops that have some
+ * unused bits set, then they won't output any set unused bits
+ * in output bitmaps.
+ *
+ * The byte ordering of bitmaps is more natural on little
+ * endian architectures. See the big-endian headers
+ * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
+ * for the best explanations of this ordering.
+ */
+
+int __bitmap_empty(const unsigned long *bitmap, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap[k])
+ return 0;
+
+ if (bits % BITS_PER_LONG)
+ if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
+ return 0;
+
+ return 1;
+}
+EXPORT_SYMBOL(__bitmap_empty);
+
+int __bitmap_full(const unsigned long *bitmap, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (~bitmap[k])
+ return 0;
+
+ if (bits % BITS_PER_LONG)
+ if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
+ return 0;
+
+ return 1;
+}
+EXPORT_SYMBOL(__bitmap_full);
+
+int __bitmap_equal(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap1[k] != bitmap2[k])
+ return 0;
+
+ if (bits % BITS_PER_LONG)
+ if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
+ return 0;
+
+ return 1;
+}
+EXPORT_SYMBOL(__bitmap_equal);
+
+void __bitmap_complement(unsigned long *dst, const unsigned long *src, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ dst[k] = ~src[k];
+
+ if (bits % BITS_PER_LONG)
+ dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
+}
+EXPORT_SYMBOL(__bitmap_complement);
+
+/**
+ * __bitmap_shift_right - logical right shift of the bits in a bitmap
+ * @dst : destination bitmap
+ * @src : source bitmap
+ * @shift : shift by this many bits
+ * @bits : bitmap size, in bits
+ *
+ * Shifting right (dividing) means moving bits in the MS -> LS bit
+ * direction. Zeros are fed into the vacated MS positions and the
+ * LS bits shifted off the bottom are lost.
+ */
+void __bitmap_shift_right(unsigned long *dst,
+ const unsigned long *src, int shift, int bits)
+{
+ int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
+ int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
+ unsigned long mask = (1UL << left) - 1;
+ for (k = 0; off + k < lim; ++k) {
+ unsigned long upper, lower;
+
+ /*
+ * If shift is not word aligned, take lower rem bits of
+ * word above and make them the top rem bits of result.
+ */
+ if (!rem || off + k + 1 >= lim)
+ upper = 0;
+ else {
+ upper = src[off + k + 1];
+ if (off + k + 1 == lim - 1 && left)
+ upper &= mask;
+ }
+ lower = src[off + k];
+ if (left && off + k == lim - 1)
+ lower &= mask;
+ dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
+ if (left && k == lim - 1)
+ dst[k] &= mask;
+ }
+ if (off)
+ memset(&dst[lim - off], 0, off*sizeof(unsigned long));
+}
+EXPORT_SYMBOL(__bitmap_shift_right);
+
+
+/**
+ * __bitmap_shift_left - logical left shift of the bits in a bitmap
+ * @dst : destination bitmap
+ * @src : source bitmap
+ * @shift : shift by this many bits
+ * @bits : bitmap size, in bits
+ *
+ * Shifting left (multiplying) means moving bits in the LS -> MS
+ * direction. Zeros are fed into the vacated LS bit positions
+ * and those MS bits shifted off the top are lost.
+ */
+
+void __bitmap_shift_left(unsigned long *dst,
+ const unsigned long *src, int shift, int bits)
+{
+ int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
+ int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
+ for (k = lim - off - 1; k >= 0; --k) {
+ unsigned long upper, lower;
+
+ /*
+ * If shift is not word aligned, take upper rem bits of
+ * word below and make them the bottom rem bits of result.
+ */
+ if (rem && k > 0)
+ lower = src[k - 1];
+ else
+ lower = 0;
+ upper = src[k];
+ if (left && k == lim - 1)
+ upper &= (1UL << left) - 1;
+ dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem;
+ if (left && k + off == lim - 1)
+ dst[k + off] &= (1UL << left) - 1;
+ }
+ if (off)
+ memset(dst, 0, off*sizeof(unsigned long));
+}
+EXPORT_SYMBOL(__bitmap_shift_left);
+
+int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k;
+ int nr = BITS_TO_LONGS(bits);
+ unsigned long result = 0;
+
+ for (k = 0; k < nr; k++)
+ result |= (dst[k] = bitmap1[k] & bitmap2[k]);
+ return result != 0;
+}
+EXPORT_SYMBOL(__bitmap_and);
+
+void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k;
+ int nr = BITS_TO_LONGS(bits);
+
+ for (k = 0; k < nr; k++)
+ dst[k] = bitmap1[k] | bitmap2[k];
+}
+EXPORT_SYMBOL(__bitmap_or);
+
+void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k;
+ int nr = BITS_TO_LONGS(bits);
+
+ for (k = 0; k < nr; k++)
+ dst[k] = bitmap1[k] ^ bitmap2[k];
+}
+EXPORT_SYMBOL(__bitmap_xor);
+
+int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k;
+ int nr = BITS_TO_LONGS(bits);
+ unsigned long result = 0;
+
+ for (k = 0; k < nr; k++)
+ result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
+ return result != 0;
+}
+EXPORT_SYMBOL(__bitmap_andnot);
+
+int __bitmap_intersects(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap1[k] & bitmap2[k])
+ return 1;
+
+ if (bits % BITS_PER_LONG)
+ if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(__bitmap_intersects);
+
+int __bitmap_subset(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap1[k] & ~bitmap2[k])
+ return 0;
+
+ if (bits % BITS_PER_LONG)
+ if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
+ return 0;
+ return 1;
+}
+EXPORT_SYMBOL(__bitmap_subset);
+
+int __bitmap_weight(const unsigned long *bitmap, int bits)
+{
+ int k, w = 0, lim = bits/BITS_PER_LONG;
+
+ for (k = 0; k < lim; k++)
+ w += hweight_long(bitmap[k]);
+
+ if (bits % BITS_PER_LONG)
+ w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
+
+ return w;
+}
+EXPORT_SYMBOL(__bitmap_weight);
+
+void bitmap_set(unsigned long *map, int start, int nr)
+{
+ unsigned long *p = map + BIT_WORD(start);
+ const int size = start + nr;
+ int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+ while (nr - bits_to_set >= 0) {
+ *p |= mask_to_set;
+ nr -= bits_to_set;
+ bits_to_set = BITS_PER_LONG;
+ mask_to_set = ~0UL;
+ p++;
+ }
+ if (nr) {
+ mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+ *p |= mask_to_set;
+ }
+}
+EXPORT_SYMBOL(bitmap_set);
+
+void bitmap_clear(unsigned long *map, int start, int nr)
+{
+ unsigned long *p = map + BIT_WORD(start);
+ const int size = start + nr;
+ int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+
+ while (nr - bits_to_clear >= 0) {
+ *p &= ~mask_to_clear;
+ nr -= bits_to_clear;
+ bits_to_clear = BITS_PER_LONG;
+ mask_to_clear = ~0UL;
+ p++;
+ }
+ if (nr) {
+ mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+ *p &= ~mask_to_clear;
+ }
+}
+EXPORT_SYMBOL(bitmap_clear);
+
+/*
+ * bitmap_find_next_zero_area - find a contiguous aligned zero area
+ * @map: The address to base the search on
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @align_mask: Alignment mask for zero area
+ *
+ * The @align_mask should be one less than a power of 2; the effect is that
+ * the bit offset of all zero areas this function finds is multiples of that
+ * power of 2. A @align_mask of 0 means no alignment is required.
+ */
+unsigned long bitmap_find_next_zero_area(unsigned long *map,
+ unsigned long size,
+ unsigned long start,
+ unsigned int nr,
+ unsigned long align_mask)
+{
+ unsigned long index, end, i;
+again:
+ index = find_next_zero_bit(map, size, start);
+
+ /* Align allocation */
+ index = __ALIGN_MASK(index, align_mask);
+
+ end = index + nr;
+ if (end > size)
+ return end;
+ i = find_next_bit(map, end, index);
+ if (i < end) {
+ start = i + 1;
+ goto again;
+ }
+ return index;
+}
+EXPORT_SYMBOL(bitmap_find_next_zero_area);
+
+/*
+ * Bitmap printing & parsing functions: first version by Nadia Yvette Chambers,
+ * second version by Paul Jackson, third by Joe Korty.
+ */
+
+#define CHUNKSZ 32
+#define nbits_to_hold_value(val) fls(val)
+#define BASEDEC 10 /* fancier cpuset lists input in decimal */
+
+/**
+ * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
+ * @buf: pointer to a bitmap
+ * @pos: a bit position in @buf (0 <= @pos < @bits)
+ * @bits: number of valid bit positions in @buf
+ *
+ * Map the bit at position @pos in @buf (of length @bits) to the
+ * ordinal of which set bit it is. If it is not set or if @pos
+ * is not a valid bit position, map to -1.
+ *
+ * If for example, just bits 4 through 7 are set in @buf, then @pos
+ * values 4 through 7 will get mapped to 0 through 3, respectively,
+ * and other @pos values will get mapped to 0. When @pos value 7
+ * gets mapped to (returns) @ord value 3 in this example, that means
+ * that bit 7 is the 3rd (starting with 0th) set bit in @buf.
+ *
+ * The bit positions 0 through @bits are valid positions in @buf.
+ */
+static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
+{
+ int i, ord;
+
+ if (pos < 0 || pos >= bits || !test_bit(pos, buf))
+ return -1;
+
+ i = find_first_bit(buf, bits);
+ ord = 0;
+ while (i < pos) {
+ i = find_next_bit(buf, bits, i + 1);
+ ord++;
+ }
+ BUG_ON(i != pos);
+
+ return ord;
+}
+
+/**
+ * bitmap_ord_to_pos - find position of n-th set bit in bitmap
+ * @buf: pointer to bitmap
+ * @ord: ordinal bit position (n-th set bit, n >= 0)
+ * @bits: number of valid bit positions in @buf
+ *
+ * Map the ordinal offset of bit @ord in @buf to its position in @buf.
+ * Value of @ord should be in range 0 <= @ord < weight(buf), else
+ * results are undefined.
+ *
+ * If for example, just bits 4 through 7 are set in @buf, then @ord
+ * values 0 through 3 will get mapped to 4 through 7, respectively,
+ * and all other @ord values return undefined values. When @ord value 3
+ * gets mapped to (returns) @pos value 7 in this example, that means
+ * that the 3rd set bit (starting with 0th) is at position 7 in @buf.
+ *
+ * The bit positions 0 through @bits are valid positions in @buf.
+ */
+int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
+{
+ int pos = 0;
+
+ if (ord >= 0 && ord < bits) {
+ int i;
+
+ for (i = find_first_bit(buf, bits);
+ i < bits && ord > 0;
+ i = find_next_bit(buf, bits, i + 1))
+ ord--;
+ if (i < bits && ord == 0)
+ pos = i;
+ }
+
+ return pos;
+}
+
+/**
+ * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap
+ * @dst: remapped result
+ * @src: subset to be remapped
+ * @old: defines domain of map
+ * @new: defines range of map
+ * @bits: number of bits in each of these bitmaps
+ *
+ * Let @old and @new define a mapping of bit positions, such that
+ * whatever position is held by the n-th set bit in @old is mapped
+ * to the n-th set bit in @new. In the more general case, allowing
+ * for the possibility that the weight 'w' of @new is less than the
+ * weight of @old, map the position of the n-th set bit in @old to
+ * the position of the m-th set bit in @new, where m == n % w.
+ *
+ * If either of the @old and @new bitmaps are empty, or if @src and
+ * @dst point to the same location, then this routine copies @src
+ * to @dst.
+ *
+ * The positions of unset bits in @old are mapped to themselves
+ * (the identify map).
+ *
+ * Apply the above specified mapping to @src, placing the result in
+ * @dst, clearing any bits previously set in @dst.
+ *
+ * For example, lets say that @old has bits 4 through 7 set, and
+ * @new has bits 12 through 15 set. This defines the mapping of bit
+ * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
+ * bit positions unchanged. So if say @src comes into this routine
+ * with bits 1, 5 and 7 set, then @dst should leave with bits 1,
+ * 13 and 15 set.
+ */
+void bitmap_remap(unsigned long *dst, const unsigned long *src,
+ const unsigned long *old, const unsigned long *new,
+ int bits)
+{
+ int oldbit, w;
+
+ if (dst == src) /* following doesn't handle inplace remaps */
+ return;
+ bitmap_zero(dst, bits);
+
+ w = bitmap_weight(new, bits);
+ for_each_set_bit(oldbit, src, bits) {
+ int n = bitmap_pos_to_ord(old, oldbit, bits);
+
+ if (n < 0 || w == 0)
+ set_bit(oldbit, dst); /* identity map */
+ else
+ set_bit(bitmap_ord_to_pos(new, n % w, bits), dst);
+ }
+}
+EXPORT_SYMBOL(bitmap_remap);
+
+/**
+ * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit
+ * @oldbit: bit position to be mapped
+ * @old: defines domain of map
+ * @new: defines range of map
+ * @bits: number of bits in each of these bitmaps
+ *
+ * Let @old and @new define a mapping of bit positions, such that
+ * whatever position is held by the n-th set bit in @old is mapped
+ * to the n-th set bit in @new. In the more general case, allowing
+ * for the possibility that the weight 'w' of @new is less than the
+ * weight of @old, map the position of the n-th set bit in @old to
+ * the position of the m-th set bit in @new, where m == n % w.
+ *
+ * The positions of unset bits in @old are mapped to themselves
+ * (the identify map).
+ *
+ * Apply the above specified mapping to bit position @oldbit, returning
+ * the new bit position.
+ *
+ * For example, lets say that @old has bits 4 through 7 set, and
+ * @new has bits 12 through 15 set. This defines the mapping of bit
+ * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
+ * bit positions unchanged. So if say @oldbit is 5, then this routine
+ * returns 13.
+ */
+int bitmap_bitremap(int oldbit, const unsigned long *old,
+ const unsigned long *new, int bits)
+{
+ int w = bitmap_weight(new, bits);
+ int n = bitmap_pos_to_ord(old, oldbit, bits);
+ if (n < 0 || w == 0)
+ return oldbit;
+ else
+ return bitmap_ord_to_pos(new, n % w, bits);
+}
+EXPORT_SYMBOL(bitmap_bitremap);
+
+/**
+ * bitmap_onto - translate one bitmap relative to another
+ * @dst: resulting translated bitmap
+ * @orig: original untranslated bitmap
+ * @relmap: bitmap relative to which translated
+ * @bits: number of bits in each of these bitmaps
+ *
+ * Set the n-th bit of @dst iff there exists some m such that the
+ * n-th bit of @relmap is set, the m-th bit of @orig is set, and
+ * the n-th bit of @relmap is also the m-th _set_ bit of @relmap.
+ * (If you understood the previous sentence the first time your
+ * read it, you're overqualified for your current job.)
+ *
+ * In other words, @orig is mapped onto (surjectively) @dst,
+ * using the the map { <n, m> | the n-th bit of @relmap is the
+ * m-th set bit of @relmap }.
+ *
+ * Any set bits in @orig above bit number W, where W is the
+ * weight of (number of set bits in) @relmap are mapped nowhere.
+ * In particular, if for all bits m set in @orig, m >= W, then
+ * @dst will end up empty. In situations where the possibility
+ * of such an empty result is not desired, one way to avoid it is
+ * to use the bitmap_fold() operator, below, to first fold the
+ * @orig bitmap over itself so that all its set bits x are in the
+ * range 0 <= x < W. The bitmap_fold() operator does this by
+ * setting the bit (m % W) in @dst, for each bit (m) set in @orig.
+ *
+ * Example [1] for bitmap_onto():
+ * Let's say @relmap has bits 30-39 set, and @orig has bits
+ * 1, 3, 5, 7, 9 and 11 set. Then on return from this routine,
+ * @dst will have bits 31, 33, 35, 37 and 39 set.
+ *
+ * When bit 0 is set in @orig, it means turn on the bit in
+ * @dst corresponding to whatever is the first bit (if any)
+ * that is turned on in @relmap. Since bit 0 was off in the
+ * above example, we leave off that bit (bit 30) in @dst.
+ *
+ * When bit 1 is set in @orig (as in the above example), it
+ * means turn on the bit in @dst corresponding to whatever
+ * is the second bit that is turned on in @relmap. The second
+ * bit in @relmap that was turned on in the above example was
+ * bit 31, so we turned on bit 31 in @dst.
+ *
+ * Similarly, we turned on bits 33, 35, 37 and 39 in @dst,
+ * because they were the 4th, 6th, 8th and 10th set bits
+ * set in @relmap, and the 4th, 6th, 8th and 10th bits of
+ * @orig (i.e. bits 3, 5, 7 and 9) were also set.
+ *
+ * When bit 11 is set in @orig, it means turn on the bit in
+ * @dst corresponding to whatever is the twelfth bit that is
+ * turned on in @relmap. In the above example, there were
+ * only ten bits turned on in @relmap (30..39), so that bit
+ * 11 was set in @orig had no affect on @dst.
+ *
+ * Example [2] for bitmap_fold() + bitmap_onto():
+ * Let's say @relmap has these ten bits set:
+ * 40 41 42 43 45 48 53 61 74 95
+ * (for the curious, that's 40 plus the first ten terms of the
+ * Fibonacci sequence.)
+ *
+ * Further lets say we use the following code, invoking
+ * bitmap_fold() then bitmap_onto, as suggested above to
+ * avoid the possitility of an empty @dst result:
+ *
+ * unsigned long *tmp; // a temporary bitmap's bits
+ *
+ * bitmap_fold(tmp, orig, bitmap_weight(relmap, bits), bits);
+ * bitmap_onto(dst, tmp, relmap, bits);
+ *
+ * Then this table shows what various values of @dst would be, for
+ * various @orig's. I list the zero-based positions of each set bit.
+ * The tmp column shows the intermediate result, as computed by
+ * using bitmap_fold() to fold the @orig bitmap modulo ten
+ * (the weight of @relmap).
+ *
+ * @orig tmp @dst
+ * 0 0 40
+ * 1 1 41
+ * 9 9 95
+ * 10 0 40 (*)
+ * 1 3 5 7 1 3 5 7 41 43 48 61
+ * 0 1 2 3 4 0 1 2 3 4 40 41 42 43 45
+ * 0 9 18 27 0 9 8 7 40 61 74 95
+ * 0 10 20 30 0 40
+ * 0 11 22 33 0 1 2 3 40 41 42 43
+ * 0 12 24 36 0 2 4 6 40 42 45 53
+ * 78 102 211 1 2 8 41 42 74 (*)
+ *
+ * (*) For these marked lines, if we hadn't first done bitmap_fold()
+ * into tmp, then the @dst result would have been empty.
+ *
+ * If either of @orig or @relmap is empty (no set bits), then @dst
+ * will be returned empty.
+ *
+ * If (as explained above) the only set bits in @orig are in positions
+ * m where m >= W, (where W is the weight of @relmap) then @dst will
+ * once again be returned empty.
+ *
+ * All bits in @dst not set by the above rule are cleared.
+ */
+void bitmap_onto(unsigned long *dst, const unsigned long *orig,
+ const unsigned long *relmap, int bits)
+{
+ int n, m; /* same meaning as in above comment */
+
+ if (dst == orig) /* following doesn't handle inplace mappings */
+ return;
+ bitmap_zero(dst, bits);
+
+ /*
+ * The following code is a more efficient, but less
+ * obvious, equivalent to the loop:
+ * for (m = 0; m < bitmap_weight(relmap, bits); m++) {
+ * n = bitmap_ord_to_pos(orig, m, bits);
+ * if (test_bit(m, orig))
+ * set_bit(n, dst);
+ * }
+ */
+
+ m = 0;
+ for_each_set_bit(n, relmap, bits) {
+ /* m == bitmap_pos_to_ord(relmap, n, bits) */
+ if (test_bit(m, orig))
+ set_bit(n, dst);
+ m++;
+ }
+}
+EXPORT_SYMBOL(bitmap_onto);
+
+/**
+ * bitmap_fold - fold larger bitmap into smaller, modulo specified size
+ * @dst: resulting smaller bitmap
+ * @orig: original larger bitmap
+ * @sz: specified size
+ * @bits: number of bits in each of these bitmaps
+ *
+ * For each bit oldbit in @orig, set bit oldbit mod @sz in @dst.
+ * Clear all other bits in @dst. See further the comment and
+ * Example [2] for bitmap_onto() for why and how to use this.
+ */
+void bitmap_fold(unsigned long *dst, const unsigned long *orig,
+ int sz, int bits)
+{
+ int oldbit;
+
+ if (dst == orig) /* following doesn't handle inplace mappings */
+ return;
+ bitmap_zero(dst, bits);
+
+ for_each_set_bit(oldbit, orig, bits)
+ set_bit(oldbit % sz, dst);
+}
+EXPORT_SYMBOL(bitmap_fold);
+
+/*
+ * Common code for bitmap_*_region() routines.
+ * bitmap: array of unsigned longs corresponding to the bitmap
+ * pos: the beginning of the region
+ * order: region size (log base 2 of number of bits)
+ * reg_op: operation(s) to perform on that region of bitmap
+ *
+ * Can set, verify and/or release a region of bits in a bitmap,
+ * depending on which combination of REG_OP_* flag bits is set.
+ *
+ * A region of a bitmap is a sequence of bits in the bitmap, of
+ * some size '1 << order' (a power of two), aligned to that same
+ * '1 << order' power of two.
+ *
+ * Returns 1 if REG_OP_ISFREE succeeds (region is all zero bits).
+ * Returns 0 in all other cases and reg_ops.
+ */
+
+enum {
+ REG_OP_ISFREE, /* true if region is all zero bits */
+ REG_OP_ALLOC, /* set all bits in region */
+ REG_OP_RELEASE, /* clear all bits in region */
+};
+
+static int __reg_op(unsigned long *bitmap, int pos, int order, int reg_op)
+{
+ int nbits_reg; /* number of bits in region */
+ int index; /* index first long of region in bitmap */
+ int offset; /* bit offset region in bitmap[index] */
+ int nlongs_reg; /* num longs spanned by region in bitmap */
+ int nbitsinlong; /* num bits of region in each spanned long */
+ unsigned long mask; /* bitmask for one long of region */
+ int i; /* scans bitmap by longs */
+ int ret = 0; /* return value */
+
+ /*
+ * Either nlongs_reg == 1 (for small orders that fit in one long)
+ * or (offset == 0 && mask == ~0UL) (for larger multiword orders.)
+ */
+ nbits_reg = 1 << order;
+ index = pos / BITS_PER_LONG;
+ offset = pos - (index * BITS_PER_LONG);
+ nlongs_reg = BITS_TO_LONGS(nbits_reg);
+ nbitsinlong = min(nbits_reg, BITS_PER_LONG);
+
+ /*
+ * Can't do "mask = (1UL << nbitsinlong) - 1", as that
+ * overflows if nbitsinlong == BITS_PER_LONG.
+ */
+ mask = (1UL << (nbitsinlong - 1));
+ mask += mask - 1;
+ mask <<= offset;
+
+ switch (reg_op) {
+ case REG_OP_ISFREE:
+ for (i = 0; i < nlongs_reg; i++) {
+ if (bitmap[index + i] & mask)
+ goto done;
+ }
+ ret = 1; /* all bits in region free (zero) */
+ break;
+
+ case REG_OP_ALLOC:
+ for (i = 0; i < nlongs_reg; i++)
+ bitmap[index + i] |= mask;
+ break;
+
+ case REG_OP_RELEASE:
+ for (i = 0; i < nlongs_reg; i++)
+ bitmap[index + i] &= ~mask;
+ break;
+ }
+done:
+ return ret;
+}
+
+/**
+ * bitmap_find_free_region - find a contiguous aligned mem region
+ * @bitmap: array of unsigned longs corresponding to the bitmap
+ * @bits: number of bits in the bitmap
+ * @order: region size (log base 2 of number of bits) to find
+ *
+ * Find a region of free (zero) bits in a @bitmap of @bits bits and
+ * allocate them (set them to one). Only consider regions of length
+ * a power (@order) of two, aligned to that power of two, which
+ * makes the search algorithm much faster.
+ *
+ * Return the bit offset in bitmap of the allocated region,
+ * or -errno on failure.
+ */
+int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
+{
+ int pos, end; /* scans bitmap by regions of size order */
+
+ for (pos = 0 ; (end = pos + (1 << order)) <= bits; pos = end) {
+ if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
+ continue;
+ __reg_op(bitmap, pos, order, REG_OP_ALLOC);
+ return pos;
+ }
+ return -ENOMEM;
+}
+EXPORT_SYMBOL(bitmap_find_free_region);
+
+/**
+ * bitmap_release_region - release allocated bitmap region
+ * @bitmap: array of unsigned longs corresponding to the bitmap
+ * @pos: beginning of bit region to release
+ * @order: region size (log base 2 of number of bits) to release
+ *
+ * This is the complement to __bitmap_find_free_region() and releases
+ * the found region (by clearing it in the bitmap).
+ *
+ * No return value.
+ */
+void bitmap_release_region(unsigned long *bitmap, int pos, int order)
+{
+ __reg_op(bitmap, pos, order, REG_OP_RELEASE);
+}
+EXPORT_SYMBOL(bitmap_release_region);
+
+/**
+ * bitmap_allocate_region - allocate bitmap region
+ * @bitmap: array of unsigned longs corresponding to the bitmap
+ * @pos: beginning of bit region to allocate
+ * @order: region size (log base 2 of number of bits) to allocate
+ *
+ * Allocate (set bits in) a specified region of a bitmap.
+ *
+ * Return 0 on success, or %-EBUSY if specified region wasn't
+ * free (not all bits were zero).
+ */
+int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
+{
+ if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
+ return -EBUSY;
+ __reg_op(bitmap, pos, order, REG_OP_ALLOC);
+ return 0;
+}
+EXPORT_SYMBOL(bitmap_allocate_region);
+
+/**
+ * bitmap_copy_le - copy a bitmap, putting the bits into little-endian order.
+ * @dst: destination buffer
+ * @src: bitmap to copy
+ * @nbits: number of bits in the bitmap
+ *
+ * Require nbits % BITS_PER_LONG == 0.
+ */
+void bitmap_copy_le(void *dst, const unsigned long *src, int nbits)
+{
+ unsigned long *d = dst;
+ int i;
+
+ for (i = 0; i < nbits/BITS_PER_LONG; i++) {
+ if (BITS_PER_LONG == 64)
+ d[i] = cpu_to_le64(src[i]);
+ else
+ d[i] = cpu_to_le32(src[i]);
+ }
+}
+EXPORT_SYMBOL(bitmap_copy_le);
diff --git a/lib/readline.c b/lib/readline.c
index 240a131d96..b70bca8554 100644
--- a/lib/readline.c
+++ b/lib/readline.c
@@ -14,8 +14,6 @@
printf ("%.*s", n, str); \
} while (0)
-#define MAX_CMDBUF_SIZE 256
-
#define CTL_BACKSPACE ('\b')
#define DEL 255
#define DEL7 127
@@ -25,90 +23,82 @@
#define getcmd_getch() getc()
#define getcmd_cbeep() getcmd_putch('\a')
-#define HIST_MAX 20
-#define HIST_SIZE MAX_CMDBUF_SIZE
-
-static int hist_max = 0;
-static int hist_add_idx = 0;
-static int hist_cur = -1;
-static unsigned hist_num = 0;
+struct history {
+ char *line;
+ struct list_head list;
+};
-static char* hist_list[HIST_MAX];
-static char hist_lines[HIST_MAX][HIST_SIZE];
+static LIST_HEAD(history_list);
-#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
+static struct list_head *history_current;
+static int history_num_entries;
-static int hist_init(void)
+static void cread_add_to_hist(char *line)
{
- int i;
+ struct history *history;
+ char *newline;
- hist_max = 0;
- hist_add_idx = 0;
- hist_cur = -1;
- hist_num = 0;
+ if (!list_empty(&history_list)) {
+ history = list_last_entry(&history_list, struct history, list);
- for (i = 0; i < HIST_MAX; i++) {
- hist_list[i] = hist_lines[i];
- hist_list[i][0] = '\0';
+ if (!strcmp(line, history->line))
+ return;
}
- return 0;
-}
-
-postcore_initcall(hist_init);
-static void cread_add_to_hist(char *line)
-{
- strcpy(hist_list[hist_add_idx], line);
+ newline = strdup(line);
+ if (!newline)
+ return;
- if (++hist_add_idx >= HIST_MAX)
- hist_add_idx = 0;
+ if (history_num_entries < 32) {
+ history = xzalloc(sizeof(*history));
+ history_num_entries++;
+ } else {
+ history = list_first_entry(&history_list, struct history, list);
+ free(history->line);
+ list_del(&history->list);
+ }
- if (hist_add_idx > hist_max)
- hist_max = hist_add_idx;
+ history->line = newline;
- hist_num++;
+ list_add_tail(&history->list, &history_list);
}
-static char* hist_prev(void)
+static const char *hist_prev(void)
{
- char *ret;
- int old_cur;
+ struct history *history;
- if (hist_cur < 0)
- return NULL;
+ if (history_current->prev == &history_list) {
+ history = list_entry(history_current, struct history, list);
+ getcmd_cbeep();
+ return history->line;
+ }
- old_cur = hist_cur;
- if (--hist_cur < 0)
- hist_cur = hist_max;
+ history = list_entry(history_current->prev, struct history, list);
- if (hist_cur == hist_add_idx) {
- hist_cur = old_cur;
- ret = NULL;
- } else
- ret = hist_list[hist_cur];
+ history_current = &history->list;
- return (ret);
+ return history->line;
}
-static char* hist_next(void)
+static const char *hist_next(void)
{
- char *ret;
+ struct history *history;
- if (hist_cur < 0)
- return NULL;
+ if (history_current->next == &history_list) {
+ history_current = &history_list;
+ return "";
+ }
- if (hist_cur == hist_add_idx)
- return NULL;
+ if (history_current == &history_list) {
+ getcmd_cbeep();
+ return "";
+ }
- if (++hist_cur > hist_max)
- hist_cur = 0;
+ history = list_entry(history_current->next, struct history, list);
- if (hist_cur == hist_add_idx) {
- ret = "";
- } else
- ret = hist_list[hist_cur];
+ history_current = &history->list;
- return (ret);
+ return history->line;
}
#define BEGINNING_OF_LINE() { \
@@ -198,6 +188,8 @@ int readline(const char *prompt, char *buf, int len)
complete_reset();
#endif
+ history_current = &history_list;
+
puts (prompt);
while (1) {
@@ -302,18 +294,13 @@ int readline(const char *prompt, char *buf, int len)
case BB_KEY_UP:
case BB_KEY_DOWN:
{
- char * hline;
+ const char *hline;
if (ichar == BB_KEY_UP)
hline = hist_prev();
else
hline = hist_next();
- if (!hline) {
- getcmd_cbeep();
- continue;
- }
-
/* nuke the current line */
/* first, go home */
BEGINNING_OF_LINE();
@@ -346,9 +333,8 @@ int readline(const char *prompt, char *buf, int len)
len = eol_num;
buf[eol_num] = '\0'; /* lose the newline */
- if (buf[0] && buf[0] != CREAD_HIST_CHAR)
+ if (buf[0])
cread_add_to_hist(buf);
- hist_cur = hist_add_idx;
return len;
}