diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/kernel/vpe-cmp.c | 180 |
2 files changed, 181 insertions, 0 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index de28da1a8757..e5a73568aa56 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -56,6 +56,7 @@ obj-$(CONFIG_MIPS_CMP) += smp-cmp.o | |||
56 | obj-$(CONFIG_CPU_MIPSR2) += spram.o | 56 | obj-$(CONFIG_CPU_MIPSR2) += spram.o |
57 | 57 | ||
58 | obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o | 58 | obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o |
59 | obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o | ||
59 | obj-$(CONFIG_MIPS_VPE_LOADER_MT) += vpe-mt.o | 60 | obj-$(CONFIG_MIPS_VPE_LOADER_MT) += vpe-mt.o |
60 | obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o | 61 | obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o |
61 | 62 | ||
diff --git a/arch/mips/kernel/vpe-cmp.c b/arch/mips/kernel/vpe-cmp.c new file mode 100644 index 000000000000..9268ebc0f61e --- /dev/null +++ b/arch/mips/kernel/vpe-cmp.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. | ||
7 | * Copyright (C) 2013 Imagination Technologies Ltd. | ||
8 | */ | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/device.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/export.h> | ||
14 | |||
15 | #include <asm/vpe.h> | ||
16 | |||
17 | static int major; | ||
18 | |||
19 | void cleanup_tc(struct tc *tc) | ||
20 | { | ||
21 | |||
22 | } | ||
23 | |||
24 | static ssize_t store_kill(struct device *dev, struct device_attribute *attr, | ||
25 | const char *buf, size_t len) | ||
26 | { | ||
27 | struct vpe *vpe = get_vpe(aprp_cpu_index()); | ||
28 | struct vpe_notifications *notifier; | ||
29 | |||
30 | list_for_each_entry(notifier, &vpe->notify, list) | ||
31 | notifier->stop(aprp_cpu_index()); | ||
32 | |||
33 | release_progmem(vpe->load_addr); | ||
34 | vpe->state = VPE_STATE_UNUSED; | ||
35 | |||
36 | return len; | ||
37 | } | ||
38 | static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill); | ||
39 | |||
40 | static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr, | ||
41 | char *buf) | ||
42 | { | ||
43 | struct vpe *vpe = get_vpe(aprp_cpu_index()); | ||
44 | |||
45 | return sprintf(buf, "%d\n", vpe->ntcs); | ||
46 | } | ||
47 | |||
48 | static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr, | ||
49 | const char *buf, size_t len) | ||
50 | { | ||
51 | struct vpe *vpe = get_vpe(aprp_cpu_index()); | ||
52 | unsigned long new; | ||
53 | int ret; | ||
54 | |||
55 | ret = kstrtoul(buf, 0, &new); | ||
56 | if (ret < 0) | ||
57 | return ret; | ||
58 | |||
59 | /* APRP can only reserve one TC in a VPE and no more. */ | ||
60 | if (new != 1) | ||
61 | return -EINVAL; | ||
62 | |||
63 | vpe->ntcs = new; | ||
64 | |||
65 | return len; | ||
66 | } | ||
67 | static DEVICE_ATTR_RW(ntcs); | ||
68 | |||
69 | static struct attribute *vpe_attrs[] = { | ||
70 | &dev_attr_kill.attr, | ||
71 | &dev_attr_ntcs.attr, | ||
72 | NULL, | ||
73 | }; | ||
74 | ATTRIBUTE_GROUPS(vpe); | ||
75 | |||
76 | static void vpe_device_release(struct device *cd) | ||
77 | { | ||
78 | kfree(cd); | ||
79 | } | ||
80 | |||
81 | static struct class vpe_class = { | ||
82 | .name = "vpe", | ||
83 | .owner = THIS_MODULE, | ||
84 | .dev_release = vpe_device_release, | ||
85 | .dev_groups = vpe_groups, | ||
86 | }; | ||
87 | |||
88 | static struct device vpe_device; | ||
89 | |||
90 | int __init vpe_module_init(void) | ||
91 | { | ||
92 | struct vpe *v = NULL; | ||
93 | struct tc *t; | ||
94 | int err; | ||
95 | |||
96 | if (!cpu_has_mipsmt) { | ||
97 | pr_warn("VPE loader: not a MIPS MT capable processor\n"); | ||
98 | return -ENODEV; | ||
99 | } | ||
100 | |||
101 | if (num_possible_cpus() - aprp_cpu_index() < 1) { | ||
102 | pr_warn("No VPEs reserved for AP/SP, not initialize VPE loader\n" | ||
103 | "Pass maxcpus=<n> argument as kernel argument\n"); | ||
104 | return -ENODEV; | ||
105 | } | ||
106 | |||
107 | major = register_chrdev(0, VPE_MODULE_NAME, &vpe_fops); | ||
108 | if (major < 0) { | ||
109 | pr_warn("VPE loader: unable to register character device\n"); | ||
110 | return major; | ||
111 | } | ||
112 | |||
113 | err = class_register(&vpe_class); | ||
114 | if (err) { | ||
115 | pr_err("vpe_class registration failed\n"); | ||
116 | goto out_chrdev; | ||
117 | } | ||
118 | |||
119 | device_initialize(&vpe_device); | ||
120 | vpe_device.class = &vpe_class, | ||
121 | vpe_device.parent = NULL, | ||
122 | dev_set_name(&vpe_device, "vpe_sp"); | ||
123 | vpe_device.devt = MKDEV(major, VPE_MODULE_MINOR); | ||
124 | err = device_add(&vpe_device); | ||
125 | if (err) { | ||
126 | pr_err("Adding vpe_device failed\n"); | ||
127 | goto out_class; | ||
128 | } | ||
129 | |||
130 | t = alloc_tc(aprp_cpu_index()); | ||
131 | if (!t) { | ||
132 | pr_warn("VPE: unable to allocate TC\n"); | ||
133 | err = -ENOMEM; | ||
134 | goto out_dev; | ||
135 | } | ||
136 | |||
137 | /* VPE */ | ||
138 | v = alloc_vpe(aprp_cpu_index()); | ||
139 | if (v == NULL) { | ||
140 | pr_warn("VPE: unable to allocate VPE\n"); | ||
141 | kfree(t); | ||
142 | err = -ENOMEM; | ||
143 | goto out_dev; | ||
144 | } | ||
145 | |||
146 | v->ntcs = 1; | ||
147 | |||
148 | /* add the tc to the list of this vpe's tc's. */ | ||
149 | list_add(&t->tc, &v->tc); | ||
150 | |||
151 | /* TC */ | ||
152 | t->pvpe = v; /* set the parent vpe */ | ||
153 | |||
154 | return 0; | ||
155 | |||
156 | out_dev: | ||
157 | device_del(&vpe_device); | ||
158 | |||
159 | out_class: | ||
160 | class_unregister(&vpe_class); | ||
161 | |||
162 | out_chrdev: | ||
163 | unregister_chrdev(major, VPE_MODULE_NAME); | ||
164 | |||
165 | return err; | ||
166 | } | ||
167 | |||
168 | void __exit vpe_module_exit(void) | ||
169 | { | ||
170 | struct vpe *v, *n; | ||
171 | |||
172 | device_del(&vpe_device); | ||
173 | class_unregister(&vpe_class); | ||
174 | unregister_chrdev(major, VPE_MODULE_NAME); | ||
175 | |||
176 | /* No locking needed here */ | ||
177 | list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) | ||
178 | if (v->state != VPE_STATE_UNUSED) | ||
179 | release_vpe(v); | ||
180 | } | ||