From 2a03cfbd906dc9bbf5e9a97727cf4ba1889d4829 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 22 Mar 2011 21:56:08 +0900 Subject: [PATCH 1/8] sh: wire up sys_syncfs. Signed-off-by: Paul Mundt --- arch/sh/include/asm/unistd_32.h | 3 ++- arch/sh/include/asm/unistd_64.h | 3 ++- arch/sh/kernel/syscalls_32.S | 1 + arch/sh/kernel/syscalls_64.S | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h index b5a74e88028d..ca7765e5f967 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/asm/unistd_32.h @@ -372,8 +372,9 @@ #define __NR_name_to_handle_at 359 #define __NR_open_by_handle_at 360 #define __NR_clock_adjtime 361 +#define __NR_syncfs 362 -#define NR_syscalls 362 +#define NR_syscalls 363 #ifdef __KERNEL__ diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h index 953da4a52199..a694009bb816 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/asm/unistd_64.h @@ -393,10 +393,11 @@ #define __NR_name_to_handle_at 370 #define __NR_open_by_handle_at 371 #define __NR_clock_adjtime 372 +#define __NR_syncfs 373 #ifdef __KERNEL__ -#define NR_syscalls 373 +#define NR_syscalls 374 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 768fb33fdd35..030966a9305c 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -379,3 +379,4 @@ ENTRY(sys_call_table) .long sys_name_to_handle_at .long sys_open_by_handle_at /* 360 */ .long sys_clock_adjtime + .long sys_syncfs diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 44e7b00c8067..ca0a6142ab63 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -399,3 +399,4 @@ sys_call_table: .long sys_name_to_handle_at /* 370 */ .long sys_open_by_handle_at .long sys_clock_adjtime + .long sys_syncfs From f47adbb988aa4436135799fd26710bff2c1b1eb6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 22 Mar 2011 22:43:09 +0900 Subject: [PATCH 2/8] sh: Conver to asm-generic/sizes.h. A trivial conversion for the most part. EDOSK7760 is special, but uses a non-power-of-2-aligned size, so just drop the SZ_xx helper and open-code it for the sake of simplicity. Signed-off-by: Paul Mundt --- arch/sh/boards/board-edosk7760.c | 2 +- arch/sh/include/asm/sizes.h | 63 +------------------------------- 2 files changed, 2 insertions(+), 63 deletions(-) diff --git a/arch/sh/boards/board-edosk7760.c b/arch/sh/boards/board-edosk7760.c index f47ac82da876..e9656a2cc4cc 100644 --- a/arch/sh/boards/board-edosk7760.c +++ b/arch/sh/boards/board-edosk7760.c @@ -56,7 +56,7 @@ static struct mtd_partition edosk7760_nor_flash_partitions[] = { }, { .name = "fs", .offset = MTDPART_OFS_APPEND, - .size = SZ_26M, + .size = (26 << 20), }, { .name = "other", .offset = MTDPART_OFS_APPEND, diff --git a/arch/sh/include/asm/sizes.h b/arch/sh/include/asm/sizes.h index 0b9fe2d5c36d..dd248c2e1085 100644 --- a/arch/sh/include/asm/sizes.h +++ b/arch/sh/include/asm/sizes.h @@ -1,62 +1 @@ -/* - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* DO NOT EDIT!! - this file automatically generated - * from .s file by awk -f s2h.awk - */ -/* Size definitions - * Copyright (C) ARM Limited 1998. All rights reserved. - */ - -#ifndef __sizes_h -#define __sizes_h 1 - -/* handy sizes */ -#define SZ_16 0x00000010 -#define SZ_32 0x00000020 -#define SZ_64 0x00000040 -#define SZ_128 0x00000080 -#define SZ_256 0x00000100 -#define SZ_512 0x00000200 - -#define SZ_1K 0x00000400 -#define SZ_2K 0x00000800 -#define SZ_4K 0x00001000 -#define SZ_8K 0x00002000 -#define SZ_16K 0x00004000 -#define SZ_32K 0x00008000 -#define SZ_64K 0x00010000 -#define SZ_128K 0x00020000 -#define SZ_256K 0x00040000 -#define SZ_512K 0x00080000 - -#define SZ_1M 0x00100000 -#define SZ_2M 0x00200000 -#define SZ_4M 0x00400000 -#define SZ_8M 0x00800000 -#define SZ_16M 0x01000000 -#define SZ_26M 0x01a00000 -#define SZ_32M 0x02000000 -#define SZ_64M 0x04000000 -#define SZ_128M 0x08000000 -#define SZ_256M 0x10000000 -#define SZ_512M 0x20000000 - -#define SZ_1G 0x40000000 -#define SZ_2G 0x80000000 - -#endif - -/* END */ +#include From a696b89c582e3201ef10bfb0d0b3594e29b75e0f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 22 Mar 2011 20:19:28 +0000 Subject: [PATCH 3/8] sh: Use struct syscore_ops instead of sysdevs Convert the SuperH clocks framework and shared interrupt handling code to using struct syscore_ops instead of a sysdev classes and sysdevs for power managment. This reduces the code size significantly and simplifies it. The optimizations causing things not to be restored after creating a hibernation image are removed, but they might lead to undesirable effects during resume from hibernation (e.g. the clocks would be left as the boot kernel set them, which might be not the same way as the hibernated kernel had seen them before the hibernation). This also is necessary for removing sysdevs from the kernel entirely in the future. Signed-off-by: Rafael J. Wysocki Signed-off-by: Paul Mundt --- drivers/sh/clk/core.c | 70 +++++-------------- drivers/sh/intc/core.c | 135 ++++++++++++++++++------------------ drivers/sh/intc/internals.h | 1 - 3 files changed, 86 insertions(+), 120 deletions(-) diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 5f63c3b83828..4f64183b27fa 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -630,68 +630,36 @@ long clk_round_parent(struct clk *clk, unsigned long target, EXPORT_SYMBOL_GPL(clk_round_parent); #ifdef CONFIG_PM -static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) +static void clks_core_resume(void) { - static pm_message_t prev_state; struct clk *clkp; - switch (state.event) { - case PM_EVENT_ON: - /* Resumeing from hibernation */ - if (prev_state.event != PM_EVENT_FREEZE) - break; + list_for_each_entry(clkp, &clock_list, node) { + if (likely(clkp->ops)) { + unsigned long rate = clkp->rate; - list_for_each_entry(clkp, &clock_list, node) { - if (likely(clkp->ops)) { - unsigned long rate = clkp->rate; - - if (likely(clkp->ops->set_parent)) - clkp->ops->set_parent(clkp, - clkp->parent); - if (likely(clkp->ops->set_rate)) - clkp->ops->set_rate(clkp, rate); - else if (likely(clkp->ops->recalc)) - clkp->rate = clkp->ops->recalc(clkp); - } + if (likely(clkp->ops->set_parent)) + clkp->ops->set_parent(clkp, + clkp->parent); + if (likely(clkp->ops->set_rate)) + clkp->ops->set_rate(clkp, rate); + else if (likely(clkp->ops->recalc)) + clkp->rate = clkp->ops->recalc(clkp); } - break; - case PM_EVENT_FREEZE: - break; - case PM_EVENT_SUSPEND: - break; } - - prev_state = state; - return 0; } -static int clks_sysdev_resume(struct sys_device *dev) +static struct syscore_ops clks_syscore_ops = { + .resume = clks_core_resume, +}; + +static int __init clk_syscore_init(void) { - return clks_sysdev_suspend(dev, PMSG_ON); -} - -static struct sysdev_class clks_sysdev_class = { - .name = "clks", -}; - -static struct sysdev_driver clks_sysdev_driver = { - .suspend = clks_sysdev_suspend, - .resume = clks_sysdev_resume, -}; - -static struct sys_device clks_sysdev_dev = { - .cls = &clks_sysdev_class, -}; - -static int __init clk_sysdev_init(void) -{ - sysdev_class_register(&clks_sysdev_class); - sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); - sysdev_register(&clks_sysdev_dev); + register_syscore_ops(&clks_syscore_ops); return 0; } -subsys_initcall(clk_sysdev_init); +subsys_initcall(clk_syscore_init); #endif /* diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index 9739431092d1..5833afbf08d7 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -376,6 +377,70 @@ int __init register_intc_controller(struct intc_desc *desc) return -ENOMEM; } +static int intc_suspend(void) +{ + struct intc_desc_int *d; + + list_for_each_entry(d, &intc_list, list) { + int irq; + + /* enable wakeup irqs belonging to this intc controller */ + for_each_active_irq(irq) { + struct irq_data *data; + struct irq_desc *desc; + struct irq_chip *chip; + + data = irq_get_irq_data(irq); + chip = irq_data_get_irq_chip(data); + if (chip != &d->chip) + continue; + desc = irq_to_desc(irq); + if ((desc->status & IRQ_WAKEUP)) + chip->irq_enable(data); + } + } + + return 0; +} + +static void intc_resume(void) +{ + struct intc_desc_int *d; + + list_for_each_entry(d, &intc_list, list) { + int irq; + + for_each_active_irq(irq) { + struct irq_data *data; + struct irq_desc *desc; + struct irq_chip *chip; + + data = irq_get_irq_data(irq); + chip = irq_data_get_irq_chip(data); + /* + * This will catch the redirect and VIRQ cases + * due to the dummy_irq_chip being inserted. + */ + if (chip != &d->chip) + continue; + desc = irq_to_desc(irq); + if (desc->status & IRQ_DISABLED) + chip->irq_disable(data); + else + chip->irq_enable(data); + } + } +} + +struct syscore_ops intc_syscore_ops = { + .suspend = intc_suspend, + .resume = intc_resume, +}; + +struct sysdev_class intc_sysdev_class = { + .name = "intc", +}; + static ssize_t show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { @@ -388,79 +453,13 @@ show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL); -static int intc_suspend(struct sys_device *dev, pm_message_t state) -{ - struct intc_desc_int *d; - struct irq_data *data; - struct irq_desc *desc; - struct irq_chip *chip; - int irq; - - /* get intc controller associated with this sysdev */ - d = container_of(dev, struct intc_desc_int, sysdev); - - switch (state.event) { - case PM_EVENT_ON: - if (d->state.event != PM_EVENT_FREEZE) - break; - - for_each_active_irq(irq) { - desc = irq_to_desc(irq); - data = irq_get_irq_data(irq); - chip = irq_data_get_irq_chip(data); - - /* - * This will catch the redirect and VIRQ cases - * due to the dummy_irq_chip being inserted. - */ - if (chip != &d->chip) - continue; - if (desc->status & IRQ_DISABLED) - chip->irq_disable(data); - else - chip->irq_enable(data); - } - break; - case PM_EVENT_FREEZE: - /* nothing has to be done */ - break; - case PM_EVENT_SUSPEND: - /* enable wakeup irqs belonging to this intc controller */ - for_each_active_irq(irq) { - desc = irq_to_desc(irq); - data = irq_get_irq_data(irq); - chip = irq_data_get_irq_chip(data); - - if (chip != &d->chip) - continue; - if ((desc->status & IRQ_WAKEUP)) - chip->irq_enable(data); - } - break; - } - - d->state = state; - - return 0; -} - -static int intc_resume(struct sys_device *dev) -{ - return intc_suspend(dev, PMSG_ON); -} - -struct sysdev_class intc_sysdev_class = { - .name = "intc", - .suspend = intc_suspend, - .resume = intc_resume, -}; - -/* register this intc as sysdev to allow suspend/resume */ static int __init register_intc_sysdevs(void) { struct intc_desc_int *d; int error; + register_syscore_ops(&intc_syscore_ops); + error = sysdev_class_register(&intc_sysdev_class); if (!error) { list_for_each_entry(d, &intc_list, list) { diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h index 0cf8260971d4..df36a421e675 100644 --- a/drivers/sh/intc/internals.h +++ b/drivers/sh/intc/internals.h @@ -53,7 +53,6 @@ struct intc_desc_int { struct list_head list; struct sys_device sysdev; struct radix_tree_root tree; - pm_message_t state; raw_spinlock_t lock; unsigned int index; unsigned long *reg; From d4cc183f7b9f639a048291e9cd95f0c255664b98 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 23 Mar 2011 19:05:18 +0900 Subject: [PATCH 4/8] sh: pmb: Use struct syscore_ops instead of sysdevs This converts the PMB code over to use the new syscore_ops and kills off the old sysdev utilization, as per Rafael's example. Signed-off-by: Paul Mundt --- arch/sh/mm/pmb.c | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index b20b1b3eee4b..fad52f1f6812 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -3,7 +3,7 @@ * * Privileged Space Mapping Buffer (PMB) Support. * - * Copyright (C) 2005 - 2010 Paul Mundt + * Copyright (C) 2005 - 2011 Paul Mundt * Copyright (C) 2010 Matt Fleming * * This file is subject to the terms and conditions of the GNU General Public @@ -12,7 +12,7 @@ */ #include #include -#include +#include #include #include #include @@ -874,46 +874,31 @@ static int __init pmb_debugfs_init(void) subsys_initcall(pmb_debugfs_init); #ifdef CONFIG_PM -static int pmb_sysdev_suspend(struct sys_device *dev, pm_message_t state) +static void pmb_syscore_resume(void) { - static pm_message_t prev_state; + struct pmb_entry *pmbe; int i; - /* Restore the PMB after a resume from hibernation */ - if (state.event == PM_EVENT_ON && - prev_state.event == PM_EVENT_FREEZE) { - struct pmb_entry *pmbe; + read_lock(&pmb_rwlock); - read_lock(&pmb_rwlock); - - for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) { - if (test_bit(i, pmb_map)) { - pmbe = &pmb_entry_list[i]; - set_pmb_entry(pmbe); - } + for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) { + if (test_bit(i, pmb_map)) { + pmbe = &pmb_entry_list[i]; + set_pmb_entry(pmbe); } - - read_unlock(&pmb_rwlock); } - prev_state = state; - - return 0; + read_unlock(&pmb_rwlock); } -static int pmb_sysdev_resume(struct sys_device *dev) -{ - return pmb_sysdev_suspend(dev, PMSG_ON); -} - -static struct sysdev_driver pmb_sysdev_driver = { - .suspend = pmb_sysdev_suspend, - .resume = pmb_sysdev_resume, +static struct syscore_ops pmb_syscore_ops = { + .resume = pmb_syscore_resume, }; static int __init pmb_sysdev_init(void) { - return sysdev_driver_register(&cpu_sysdev_class, &pmb_sysdev_driver); + register_syscore_ops(&pmb_syscore_ops); + return 0; } subsys_initcall(pmb_sysdev_init); #endif From 3f4caa8157449b96f8b166c7a98ee40c4bc35a55 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 23 Mar 2011 19:16:34 +0900 Subject: [PATCH 5/8] sh: Re-enable GENERIC_HARDIRQS_NO_DEPRECATED. Now that the in-tree offenders have seemingly all caught up, we can finally unconditionally select this. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 2d264fa84959..e4be5a485d5c 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -23,8 +23,7 @@ config SUPERH select HAVE_SPARSE_IRQ select RTC_LIB select GENERIC_ATOMIC64 - # Support the deprecated APIs until MFD and GPIOLIB catch up. - select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB + select GENERIC_HARDIRQS_NO_DEPRECATED select GENERIC_IRQ_SHOW help The SuperH is a RISC processor targeted for use in embedded systems From c49b6ecf0870e78fa40497cd8b142915c1d5c7c9 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Fri, 18 Mar 2011 14:16:31 +0000 Subject: [PATCH 6/8] sh: Fix ptrace fpu state initialisation Commit 0ea820cf introduced the PTRACE_GETFPREGS/SETFPREGS cmds, but gdb-server still accesses the FPU state using the PTRACE_PEEKUSR/POKEUSR commands. In this case, xstate was not initialised. Signed-off-by: Phil Edworthy Cc: stable@kernel.org Signed-off-by: Paul Mundt --- arch/sh/kernel/ptrace_32.c | 6 ++++++ arch/sh/kernel/ptrace_64.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index 90a15d29feeb..b53664ef53e8 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -392,6 +392,9 @@ long arch_ptrace(struct task_struct *child, long request, tmp = 0; } else { unsigned long index; + ret = init_fpu(child); + if (ret) + break; index = addr - offsetof(struct user, fpu); tmp = ((unsigned long *)child->thread.xstate) [index >> 2]; @@ -423,6 +426,9 @@ long arch_ptrace(struct task_struct *child, long request, else if (addr >= offsetof(struct user, fpu) && addr < offsetof(struct user, u_fpvalid)) { unsigned long index; + ret = init_fpu(child); + if (ret) + break; index = addr - offsetof(struct user, fpu); set_stopped_child_used_math(child); ((unsigned long *)child->thread.xstate) diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 4436eacddb15..c8f97649f354 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -403,6 +403,9 @@ long arch_ptrace(struct task_struct *child, long request, else if ((addr >= offsetof(struct user, fpu)) && (addr < offsetof(struct user, u_fpvalid))) { unsigned long index; + ret = init_fpu(child); + if (ret) + break; index = addr - offsetof(struct user, fpu); tmp = get_fpu_long(child, index); } else if (addr == offsetof(struct user, u_fpvalid)) { @@ -442,6 +445,9 @@ long arch_ptrace(struct task_struct *child, long request, else if ((addr >= offsetof(struct user, fpu)) && (addr < offsetof(struct user, u_fpvalid))) { unsigned long index; + ret = init_fpu(child); + if (ret) + break; index = addr - offsetof(struct user, fpu); ret = put_fpu_long(child, index, data); } From fb7f045ace0624f1e59a7db8497e460bd54b1cbc Mon Sep 17 00:00:00 2001 From: David Engraf Date: Wed, 23 Mar 2011 11:35:42 +0000 Subject: [PATCH 7/8] sh: Fix ptrace hw_breakpoint handling Since commit 34d0b5af50a063cded842716633501b38ff815fb it is no longer possible to debug an application using singlestep. The old commit converted singlestep handling via ptrace to hw_breakpoints. The hw_breakpoint is disabled when an event is triggered and not re-enabled again. This patch re-enables the existing hw_breakpoint before the existing breakpoint is reused. Signed-off-by: David Engraf Cc: stable@kernel.org Signed-off-by: Paul Mundt --- arch/sh/kernel/ptrace_32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index b53664ef53e8..2130ca674e9b 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -101,6 +101,8 @@ static int set_single_step(struct task_struct *tsk, unsigned long addr) attr = bp->attr; attr.bp_addr = addr; + /* reenable breakpoint */ + attr.disabled = false; err = modify_user_hw_breakpoint(bp, &attr); if (unlikely(err)) return err; From b15ed691667f59867c9c130b8d84feda4050be04 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 24 Mar 2011 05:47:40 +0000 Subject: [PATCH 8/8] sh: Fix build alloc_thread_info_node function By commit b6a84016bd2598e35ead635147fa53619982648d, alloc_thread_info was replaced by alloc_thread_info_node. However, the change of the function name and the addition of the argument were incomplete. Signed-off-by: Nobuhiro Iwamatsu CC: Eric Dumazet Signed-off-by: Paul Mundt --- arch/sh/kernel/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index f39ad57296b7..325f98b1736d 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -32,7 +32,7 @@ void free_thread_xstate(struct task_struct *tsk) #if THREAD_SHIFT < PAGE_SHIFT static struct kmem_cache *thread_info_cache; -struct thread_info *alloc_thread_info(struct task_struct *tsk, int node) +struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node) { struct thread_info *ti; #ifdef CONFIG_DEBUG_STACK_USAGE @@ -57,7 +57,7 @@ void thread_info_cache_init(void) THREAD_SIZE, SLAB_PANIC, NULL); } #else -struct thread_info *alloc_thread_info(struct task_struct *tsk) +struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node) { #ifdef CONFIG_DEBUG_STACK_USAGE gfp_t mask = GFP_KERNEL | __GFP_ZERO;