~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/arm/kernel/crunch.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * arch/arm/kernel/crunch.c
 
3
 * Cirrus MaverickCrunch context switching and handling
 
4
 *
 
5
 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License version 2 as
 
9
 * published by the Free Software Foundation.
 
10
 */
 
11
 
 
12
#include <linux/module.h>
 
13
#include <linux/types.h>
 
14
#include <linux/kernel.h>
 
15
#include <linux/signal.h>
 
16
#include <linux/sched.h>
 
17
#include <linux/init.h>
 
18
#include <linux/io.h>
 
19
#include <mach/ep93xx-regs.h>
 
20
#include <asm/thread_notify.h>
 
21
 
 
22
struct crunch_state *crunch_owner;
 
23
 
 
24
void crunch_task_release(struct thread_info *thread)
 
25
{
 
26
        local_irq_disable();
 
27
        if (crunch_owner == &thread->crunchstate)
 
28
                crunch_owner = NULL;
 
29
        local_irq_enable();
 
30
}
 
31
 
 
32
static int crunch_enabled(u32 devcfg)
 
33
{
 
34
        return !!(devcfg & EP93XX_SYSCON_DEVCFG_CPENA);
 
35
}
 
36
 
 
37
static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t)
 
38
{
 
39
        struct thread_info *thread = (struct thread_info *)t;
 
40
        struct crunch_state *crunch_state;
 
41
        u32 devcfg;
 
42
 
 
43
        crunch_state = &thread->crunchstate;
 
44
 
 
45
        switch (cmd) {
 
46
        case THREAD_NOTIFY_FLUSH:
 
47
                memset(crunch_state, 0, sizeof(*crunch_state));
 
48
 
 
49
                /*
 
50
                 * FALLTHROUGH: Ensure we don't try to overwrite our newly
 
51
                 * initialised state information on the first fault.
 
52
                 */
 
53
 
 
54
        case THREAD_NOTIFY_EXIT:
 
55
                crunch_task_release(thread);
 
56
                break;
 
57
 
 
58
        case THREAD_NOTIFY_SWITCH:
 
59
                devcfg = __raw_readl(EP93XX_SYSCON_DEVCFG);
 
60
                if (crunch_enabled(devcfg) || crunch_owner == crunch_state) {
 
61
                        /*
 
62
                         * We don't use ep93xx_syscon_swlocked_write() here
 
63
                         * because we are on the context switch path and
 
64
                         * preemption is already disabled.
 
65
                         */
 
66
                        devcfg ^= EP93XX_SYSCON_DEVCFG_CPENA;
 
67
                        __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
 
68
                        __raw_writel(devcfg, EP93XX_SYSCON_DEVCFG);
 
69
                }
 
70
                break;
 
71
        }
 
72
 
 
73
        return NOTIFY_DONE;
 
74
}
 
75
 
 
76
static struct notifier_block crunch_notifier_block = {
 
77
        .notifier_call  = crunch_do,
 
78
};
 
79
 
 
80
static int __init crunch_init(void)
 
81
{
 
82
        thread_register_notifier(&crunch_notifier_block);
 
83
        elf_hwcap |= HWCAP_CRUNCH;
 
84
 
 
85
        return 0;
 
86
}
 
87
 
 
88
late_initcall(crunch_init);