From af04bb8578a47e7a7572cf1c22bb3309ca2380f7 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 29 Jul 2013 15:07:01 -0700 Subject: MIPS: Probe for new OCTEON CPU/SoC types. Add probing for CNF71XX, CN78XX and CN70XX. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5635/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 4c6167a1787..8e8feb851f6 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -852,10 +852,17 @@ platform: case PRID_IMP_CAVIUM_CN63XX: case PRID_IMP_CAVIUM_CN66XX: case PRID_IMP_CAVIUM_CN68XX: + case PRID_IMP_CAVIUM_CNF71XX: c->cputype = CPU_CAVIUM_OCTEON2; __cpu_name[cpu] = "Cavium Octeon II"; set_elf_platform(cpu, "octeon2"); break; + case PRID_IMP_CAVIUM_CN70XX: + case PRID_IMP_CAVIUM_CN78XX: + c->cputype = CPU_CAVIUM_OCTEON3; + __cpu_name[cpu] = "Cavium Octeon III"; + set_elf_platform(cpu, "octeon3"); + break; default: printk(KERN_INFO "Unknown Octeon chip!\n"); c->cputype = CPU_UNKNOWN; -- cgit v1.2.3-70-g09d2 From 4122af0ab02a4b394e4703a3ac557d556701f4d9 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 29 Jul 2013 15:07:02 -0700 Subject: MIPS: Use r4k_wait for OCTEON3 CPUs. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5636/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/idle.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 0c655deeea4..42f8875d244 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -166,6 +166,7 @@ void __init check_wait(void) case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: + case CPU_CAVIUM_OCTEON3: case CPU_JZRISC: case CPU_LOONGSON1: case CPU_XLR: -- cgit v1.2.3-70-g09d2 From b8199546a4121ae3a8dc094e658c5fabc4397925 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 8 Aug 2013 11:40:49 -0700 Subject: MIPS: Discard .eh_frame sections in linker script. Some toolchains (including Cavium OCTEON SDK) are emitting .eh_frame sections by default. Discard them as they are useless in the kernel. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5684/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 05826d20a79..3b46f7ce9ca 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -179,5 +179,6 @@ SECTIONS *(.options) *(.pdr) *(.reginfo) + *(.eh_frame) } } -- cgit v1.2.3-70-g09d2 From afddce0cc9f22c72e6ee7350a0e90b04aaa470b2 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 3 Sep 2013 01:29:58 +0100 Subject: MIPS: R4k clock source initialization bug fix This is a fix for a bug introduced with commit 447cdf2628b59aa513a42785450b348dced26d8a, submitted as archived here: http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20080312235002.c717dde3.yoichi_yuasa%40tripeaks.co.jp regrettably with no further explanation. The issue is with the CP0 Count register read erratum present on R4000 and some R4400 processors. If this erratum is present, then a read from this register that happens around the time it reaches the value stored in the CP0 Compare register causes a CP0 timer interrupt that is supposed to happen when the values in the two registers match to be missed. The implication for the chips affected is the CP0 timer can be used either as a source of a timer interrupt (a clock event) or as a source of a high-resolution counter (a clock source), but not both at a time. The erratum does not affect timer interrupt operation itself, because in this case the CP0 Count register is only read while the timer interrupt has already been raised, while high-resolution counter references happen at random times. Additionally some systems apparently have issues with the timer interrupt line being routed externally and not following the usual CP0 Count/Compare semantics. In this case we don't want to use the R4k clock event. We've meant to address the erratum and the timer interrupt routing issue in time_init, however the commit referred to above broke our solution. What we currently have is we enable the R4k clock source if the R4k clock event initialization has succeeded (the timer is present and has no timer interrupt routing issue) or there is no CP0 Count register read erratum. Which gives the following boolean matrix: clock event | count erratum => clock source ------------+---------------+-------------- 0 | 0 | 1 (OK) 0 | 1 | 0 (bug!) -> no interference, could use 1 | 0 | 1 (OK) 1 | 1 | 1 (bug!) -> can't use, interference What we want instead is to enable the R4k clock source if there is no CP0 Count register read erratum (obviously) or the R4k clock event initialization has *failed* -- because in the latter case we won't be using the timer interrupt anyway, so we don't care about any interference CP0 Count reads might cause with the interrupt. This corresponds to the following boolean matrix: clock event | count erratum => clock source ------------+---------------+-------------- 0 | 0 | 1 0 | 1 | 1 1 | 0 | 1 1 | 1 | 0 This is implemented here, effectively reverting the problematic commit, and a short explanation is given next to code modified so that the rationale is known to future readers and confusion is prevented from happening here again. It is worth noting that mips_clockevent_init returns 0 upon success while cpu_has_mfc0_count_bug returns 0 upon failure. This is because the former function returns an error code while the latter returns a boolean value. To signify the difference I have therefore chosen to compare the result of the former call explicitly against 0. Signed-off-by: Maciej W. Rozycki Signed-off-by: Ralf Baechle Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5799/ --- arch/mips/kernel/time.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 9d686bf97b0..364d26ae421 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -121,6 +121,14 @@ void __init time_init(void) { plat_time_init(); - if (!mips_clockevent_init() || !cpu_has_mfc0_count_bug()) + /* + * The use of the R4k timer as a clock event takes precedence; + * if reading the Count register might interfere with the timer + * interrupt, then we don't use the timer as a clock source. + * We may still use the timer as a clock source though if the + * timer interrupt isn't reliable; the interference doesn't + * matter then, because we don't use the interrupt. + */ + if (mips_clockevent_init() != 0 || !cpu_has_mfc0_count_bug()) init_mips_clocksource(); } -- cgit v1.2.3-70-g09d2 From 05f226391d800b0b7696125eb9a13273ea9018f8 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 15 Jul 2013 15:17:17 -0700 Subject: MIPS: Ftrace: Fix function tracing return address to match Dynamic function tracing was not working on MIPS. When doing dynamic tracing, the tracer attempts to match up the passed in address with the one the compiler creates in the mcount tables. The MIPS code was passing in the return address from the tracing function call, but the compiler tables were the address of the function call. So they wouldn't match. Just subtracting 8 from the return address will give the address of the function call. Easy enough. Signed-off-by: Corey Minyard [david.daney@cavium.com: Adjusted code comment and patch Subject.] Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: Steven Rostedt Signed-off-by: Ralf Baechle Patchwork: https://patchwork.linux-mips.org/patch/5592/ --- arch/mips/kernel/mcount.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index a03e93c4a94..539b6294b61 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -83,7 +83,7 @@ _mcount: PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) #endif - move a0, ra /* arg1: self return address */ + PTR_SUBU a0, ra, 8 /* arg1: self address */ .globl ftrace_call ftrace_call: nop /* a placeholder for the call to a real tracing function */ -- cgit v1.2.3-70-g09d2 From 4ca86a2ff37ce92b6875a184a97a20188704cb6c Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Sun, 11 Aug 2013 14:43:54 +0530 Subject: MIPS: Netlogic: Add support for XLP2XX XLP2XX is first in the series of 28nm XLPII processors. The changes are to: * Add processor ID for XLP2XX to asm/cpu.h and kernel/cpu-probe.c. * Add a cpu_is_xlpii() function to check for XLPII processors. * Update xlp_mmu_init() to use config4 to enable extended TLB. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5698/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/netlogic/xlp-hal/xlp.h | 7 +++++++ arch/mips/kernel/cpu-probe.c | 5 +++++ arch/mips/netlogic/xlp/setup.c | 27 ++++++++++++++++++++------- 4 files changed, 33 insertions(+), 7 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index c19861518c3..71b9f1998be 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -179,6 +179,7 @@ #define PRID_IMP_NETLOGIC_XLP8XX 0x1000 #define PRID_IMP_NETLOGIC_XLP3XX 0x1100 +#define PRID_IMP_NETLOGIC_XLP2XX 0x1200 /* * Definitions for 7:0 on legacy processors diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index d59cdd69496..7a4a5142bbc 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -64,5 +64,12 @@ int xlp_get_dram_map(int n, uint64_t *dram_map); /* Device tree related */ void *xlp_dt_init(void *fdtp); +static inline int cpu_is_xlpii(void) +{ + int chip = read_c0_prid() & 0xff00; + + return chip == PRID_IMP_NETLOGIC_XLP2XX; +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_NLM_XLP_H */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 8e8feb851f6..37663c7862a 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -906,6 +906,11 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) MIPS_CPU_LLSC); switch (c->processor_id & 0xff00) { + case PRID_IMP_NETLOGIC_XLP2XX: + c->cputype = CPU_XLP; + __cpu_name[cpu] = "Broadcom XLPII"; + break; + case PRID_IMP_NETLOGIC_XLP8XX: case PRID_IMP_NETLOGIC_XLP3XX: c->cputype = CPU_XLP; diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 7718368e459..76a7131e486 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -110,7 +110,12 @@ void __init plat_mem_setup(void) const char *get_system_type(void) { - return "Netlogic XLP Series"; + switch (read_c0_prid() & 0xff00) { + case PRID_IMP_NETLOGIC_XLP2XX: + return "Broadcom XLPII Series"; + default: + return "Netlogic XLP Series"; + } } void __init prom_free_prom_memory(void) @@ -120,12 +125,20 @@ void __init prom_free_prom_memory(void) void xlp_mmu_init(void) { - /* enable extended TLB and Large Fixed TLB */ - write_c0_config6(read_c0_config6() | 0x24); - - /* set page mask of Fixed TLB in config7 */ - write_c0_config7(PM_DEFAULT_MASK >> - (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2))); + u32 conf4; + + if (cpu_is_xlpii()) { + /* XLPII series has extended pagesize in config 4 */ + conf4 = read_c0_config4() & ~0x1f00u; + write_c0_config4(conf4 | ((PAGE_SHIFT - 10) / 2 << 8)); + } else { + /* enable extended TLB and Large Fixed TLB */ + write_c0_config6(read_c0_config6() | 0x24); + + /* set page mask of extended Fixed TLB in config7 */ + write_c0_config7(PM_DEFAULT_MASK >> + (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2))); + } } void nlm_percpu_init(int hwcpuid) -- cgit v1.2.3-70-g09d2 From 8533966a6dba09d65a6764accdf44f3e96cddbfb Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Wed, 4 Sep 2013 23:47:45 +0100 Subject: MIPS: DECstation HRT calibration bug fixes This change corrects DECstation HRT calibration, by removing the following bugs: 1. Calibration period selection -- HZ / 10 has been chosen, however on DECstation computers, HZ never divides by 10, as the choice for HZ is among 128, 256 and 1024. The choice therefore results in a systematic calibration error, e.g. 6.25% for the usual choice of 128 for HZ: 128 / 10 * 10 = 120 (128 - 120) / 128 -> 6.25% The change therefore makes calibration use HZ / 8 that is always accurate for the HZ values available, getting rid of the systematic error. 2. Calibration starting point synchronisation -- the duration of a number of intervals between DS1287A periodic interrupt assertions is measured, however code does not ensure at the beginning that the interrupt has not been previously asserted. This results in a variable error of e.g. up to another 6.25% for the period of HZ / 8 (8.(3)% with the original HZ / 10 period) and the usual choice of 128 for HZ: 1 / 16 -> 6.25% 1 / 12 -> 8.(3)% The change therefore adds an initial call to ds1287_timer_state that clears any previous periodic interrupt pending. The same issue applies to both I/O ASIC counter and R4k CP0 timer calibration on DECstation systems as similar code is used in both cases and both pieces of code are covered by this fix. On an R3400 test system used this fix results in a change of the I/O ASIC clock frequency reported from values like: I/O ASIC clock frequency 23185830Hz to: I/O ASIC clock frequency 24999288Hz removing the miscalculation by 6.25% from the systematic error and (for the individual sample provided) a further 1.00% from the variable error, accordingly. The nominal I/O ASIC clock frequency is 25MHz on this system. Here's another result, with the fix applied, from a system that has both HRTs available (using an R4400 at 60MHz nominal): MIPS counter frequency 59999328Hz I/O ASIC clock frequency 24999432Hz Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5807/ Signed-off-by: Ralf Baechle --- arch/mips/dec/time.c | 5 +++-- arch/mips/kernel/csrc-ioasic.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index ea57f39e673..56ebc7f2bed 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -126,12 +126,13 @@ int rtc_mips_set_mmss(unsigned long nowtime) void __init plat_time_init(void) { u32 start, end; - int i = HZ / 10; + int i = HZ / 8; /* Set up the rate of periodic DS1287 interrupts. */ ds1287_set_base_clock(HZ); if (cpu_has_counter) { + ds1287_timer_state(); while (!ds1287_timer_state()) ; @@ -143,7 +144,7 @@ void __init plat_time_init(void) end = read_c0_count(); - mips_hpt_frequency = (end - start) * 10; + mips_hpt_frequency = (end - start) * 8; printk(KERN_INFO "MIPS counter frequency %dHz\n", mips_hpt_frequency); } else if (IOASIC) diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c index 0654bff9b69..87e88feb4a2 100644 --- a/arch/mips/kernel/csrc-ioasic.c +++ b/arch/mips/kernel/csrc-ioasic.c @@ -41,9 +41,9 @@ void __init dec_ioasic_clocksource_init(void) { unsigned int freq; u32 start, end; - int i = HZ / 10; - + int i = HZ / 8; + ds1287_timer_state(); while (!ds1287_timer_state()) ; @@ -55,7 +55,7 @@ void __init dec_ioasic_clocksource_init(void) end = dec_ioasic_hpt_read(&clocksource_dec); - freq = (end - start) * 10; + freq = (end - start) * 8; printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq); clocksource_dec.rating = 200 + freq / 10000000; -- cgit v1.2.3-70-g09d2 From 273463b78237b53936a61046bfb4c8e55150ca24 Mon Sep 17 00:00:00 2001 From: Prem Mallappa Date: Fri, 30 Aug 2013 15:35:10 +0530 Subject: MIPS: kdump: Skip walking indirection page for crashkernels KDUMP: skip indirection page, as crashkernel has already copied to destination [ralf@linux-mips.org: cosmetic changes.] Signed-off-by: Prem Mallappa Cc: linux-mips Patchwork: https://patchwork.linux-mips.org/patch/5786/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/relocate_kernel.S | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S index 43d2d78d328..74bab9ddd0e 100644 --- a/arch/mips/kernel/relocate_kernel.S +++ b/arch/mips/kernel/relocate_kernel.S @@ -26,6 +26,12 @@ process_entry: PTR_L s2, (s0) PTR_ADD s0, s0, SZREG + /* + * In case of a kdump/crash kernel, the indirection page is not + * populated as the kernel is directly copied to a reserved location + */ + beqz s2, done + /* destination page */ and s3, s2, 0x1 beq s3, zero, 1f -- cgit v1.2.3-70-g09d2 From c2882b7fab9251309dc10c980b17e486f848502f Mon Sep 17 00:00:00 2001 From: Prem Mallappa Date: Wed, 4 Sep 2013 23:26:24 +0530 Subject: MIPS: kexec: Fix random crashes while loading crashkernel Fixed compilation errors in case of non-KEXEC kernel Rearranging code so that crashk_res gets updated. - crashk_res is updated after mips_parse_crashkernel(), after resource_init(), which is after arch_mem_init(). - The reserved memory is actually treated as Usable memory, Unless we load the crash kernel, everything works. Signed-off-by: Prem Mallappa Cc: linux-mips Patchwork: http://patchwork.linux-mips.org/patch/5805/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 99 +++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 51 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index c7f90519e58..c538d6e01b7 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -552,6 +552,52 @@ static void __init arch_mem_addpart(phys_t mem, phys_t end, int type) add_memory_region(mem, size, type); } +#ifdef CONFIG_KEXEC +static inline unsigned long long get_total_mem(void) +{ + unsigned long long total; + + total = max_pfn - min_low_pfn; + return total << PAGE_SHIFT; +} + +static void __init mips_parse_crashkernel(void) +{ + unsigned long long total_mem; + unsigned long long crash_size, crash_base; + int ret; + + total_mem = get_total_mem(); + ret = parse_crashkernel(boot_command_line, total_mem, + &crash_size, &crash_base); + if (ret != 0 || crash_size <= 0) + return; + + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size - 1; +} + +static void __init request_crashkernel(struct resource *res) +{ + int ret; + + ret = request_resource(res, &crashk_res); + if (!ret) + pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", + (unsigned long)((crashk_res.end - + crashk_res.start + 1) >> 20), + (unsigned long)(crashk_res.start >> 20)); +} +#else /* !defined(CONFIG_KEXEC) */ +static void __init mips_parse_crashkernel(void) +{ +} + +static void __init request_crashkernel(struct resource *res) +{ +} +#endif /* !defined(CONFIG_KEXEC) */ + static void __init arch_mem_init(char **cmdline_p) { extern void plat_mem_setup(void); @@ -608,6 +654,8 @@ static void __init arch_mem_init(char **cmdline_p) BOOTMEM_DEFAULT); } #endif + + mips_parse_crashkernel(); #ifdef CONFIG_KEXEC if (crashk_res.start != crashk_res.end) reserve_bootmem(crashk_res.start, @@ -620,52 +668,6 @@ static void __init arch_mem_init(char **cmdline_p) paging_init(); } -#ifdef CONFIG_KEXEC -static inline unsigned long long get_total_mem(void) -{ - unsigned long long total; - - total = max_pfn - min_low_pfn; - return total << PAGE_SHIFT; -} - -static void __init mips_parse_crashkernel(void) -{ - unsigned long long total_mem; - unsigned long long crash_size, crash_base; - int ret; - - total_mem = get_total_mem(); - ret = parse_crashkernel(boot_command_line, total_mem, - &crash_size, &crash_base); - if (ret != 0 || crash_size <= 0) - return; - - crashk_res.start = crash_base; - crashk_res.end = crash_base + crash_size - 1; -} - -static void __init request_crashkernel(struct resource *res) -{ - int ret; - - ret = request_resource(res, &crashk_res); - if (!ret) - pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", - (unsigned long)((crashk_res.end - - crashk_res.start + 1) >> 20), - (unsigned long)(crashk_res.start >> 20)); -} -#else /* !defined(CONFIG_KEXEC) */ -static void __init mips_parse_crashkernel(void) -{ -} - -static void __init request_crashkernel(struct resource *res) -{ -} -#endif /* !defined(CONFIG_KEXEC) */ - static void __init resource_init(void) { int i; @@ -678,11 +680,6 @@ static void __init resource_init(void) data_resource.start = __pa_symbol(&_etext); data_resource.end = __pa_symbol(&_edata) - 1; - /* - * Request address space for all standard RAM. - */ - mips_parse_crashkernel(); - for (i = 0; i < boot_mem_map.nr_map; i++) { struct resource *res; unsigned long start, end; -- cgit v1.2.3-70-g09d2