0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/device.h>
0011 #include <linux/fs.h>
0012 #include <linux/slab.h>
0013 #include <linux/export.h>
0014
0015 #include <asm/vpe.h>
0016
0017 static int major;
0018
0019 void cleanup_tc(struct tc *tc)
0020 {
0021
0022 }
0023
0024 static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
0025 const char *buf, size_t len)
0026 {
0027 struct vpe *vpe = get_vpe(aprp_cpu_index());
0028 struct vpe_notifications *notifier;
0029
0030 list_for_each_entry(notifier, &vpe->notify, list)
0031 notifier->stop(aprp_cpu_index());
0032
0033 release_progmem(vpe->load_addr);
0034 vpe->state = VPE_STATE_UNUSED;
0035
0036 return len;
0037 }
0038 static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill);
0039
0040 static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr,
0041 char *buf)
0042 {
0043 struct vpe *vpe = get_vpe(aprp_cpu_index());
0044
0045 return sprintf(buf, "%d\n", vpe->ntcs);
0046 }
0047
0048 static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr,
0049 const char *buf, size_t len)
0050 {
0051 struct vpe *vpe = get_vpe(aprp_cpu_index());
0052 unsigned long new;
0053 int ret;
0054
0055 ret = kstrtoul(buf, 0, &new);
0056 if (ret < 0)
0057 return ret;
0058
0059
0060 if (new != 1)
0061 return -EINVAL;
0062
0063 vpe->ntcs = new;
0064
0065 return len;
0066 }
0067 static DEVICE_ATTR_RW(ntcs);
0068
0069 static struct attribute *vpe_attrs[] = {
0070 &dev_attr_kill.attr,
0071 &dev_attr_ntcs.attr,
0072 NULL,
0073 };
0074 ATTRIBUTE_GROUPS(vpe);
0075
0076 static void vpe_device_release(struct device *cd)
0077 {
0078 kfree(cd);
0079 }
0080
0081 static struct class vpe_class = {
0082 .name = "vpe",
0083 .owner = THIS_MODULE,
0084 .dev_release = vpe_device_release,
0085 .dev_groups = vpe_groups,
0086 };
0087
0088 static struct device vpe_device;
0089
0090 int __init vpe_module_init(void)
0091 {
0092 struct vpe *v = NULL;
0093 struct tc *t;
0094 int err;
0095
0096 if (!cpu_has_mipsmt) {
0097 pr_warn("VPE loader: not a MIPS MT capable processor\n");
0098 return -ENODEV;
0099 }
0100
0101 if (num_possible_cpus() - aprp_cpu_index() < 1) {
0102 pr_warn("No VPEs reserved for AP/SP, not initialize VPE loader\n"
0103 "Pass maxcpus=<n> argument as kernel argument\n");
0104 return -ENODEV;
0105 }
0106
0107 major = register_chrdev(0, VPE_MODULE_NAME, &vpe_fops);
0108 if (major < 0) {
0109 pr_warn("VPE loader: unable to register character device\n");
0110 return major;
0111 }
0112
0113 err = class_register(&vpe_class);
0114 if (err) {
0115 pr_err("vpe_class registration failed\n");
0116 goto out_chrdev;
0117 }
0118
0119 device_initialize(&vpe_device);
0120 vpe_device.class = &vpe_class;
0121 vpe_device.parent = NULL;
0122 dev_set_name(&vpe_device, "vpe_sp");
0123 vpe_device.devt = MKDEV(major, VPE_MODULE_MINOR);
0124 err = device_add(&vpe_device);
0125 if (err) {
0126 pr_err("Adding vpe_device failed\n");
0127 goto out_class;
0128 }
0129
0130 t = alloc_tc(aprp_cpu_index());
0131 if (!t) {
0132 pr_warn("VPE: unable to allocate TC\n");
0133 err = -ENOMEM;
0134 goto out_dev;
0135 }
0136
0137
0138 v = alloc_vpe(aprp_cpu_index());
0139 if (v == NULL) {
0140 pr_warn("VPE: unable to allocate VPE\n");
0141 kfree(t);
0142 err = -ENOMEM;
0143 goto out_dev;
0144 }
0145
0146 v->ntcs = 1;
0147
0148
0149 list_add(&t->tc, &v->tc);
0150
0151
0152 t->pvpe = v;
0153
0154 return 0;
0155
0156 out_dev:
0157 device_del(&vpe_device);
0158
0159 out_class:
0160 class_unregister(&vpe_class);
0161
0162 out_chrdev:
0163 unregister_chrdev(major, VPE_MODULE_NAME);
0164
0165 return err;
0166 }
0167
0168 void __exit vpe_module_exit(void)
0169 {
0170 struct vpe *v, *n;
0171
0172 device_del(&vpe_device);
0173 class_unregister(&vpe_class);
0174 unregister_chrdev(major, VPE_MODULE_NAME);
0175
0176
0177 list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list)
0178 if (v->state != VPE_STATE_UNUSED)
0179 release_vpe(v);
0180 }