0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/fs.h>
0011 #include <linux/err.h>
0012 #include <linux/wait.h>
0013 #include <linux/sched.h>
0014 #include <linux/smp.h>
0015
0016 #include <asm/mips_mt.h>
0017 #include <asm/vpe.h>
0018 #include <asm/rtlx.h>
0019
0020 static int major;
0021
0022 static void rtlx_interrupt(void)
0023 {
0024 int i;
0025 struct rtlx_info *info;
0026 struct rtlx_info **p = vpe_get_shared(aprp_cpu_index());
0027
0028 if (p == NULL || *p == NULL)
0029 return;
0030
0031 info = *p;
0032
0033 if (info->ap_int_pending == 1 && smp_processor_id() == 0) {
0034 for (i = 0; i < RTLX_CHANNELS; i++) {
0035 wake_up(&channel_wqs[i].lx_queue);
0036 wake_up(&channel_wqs[i].rt_queue);
0037 }
0038 info->ap_int_pending = 0;
0039 }
0040 }
0041
0042 void _interrupt_sp(void)
0043 {
0044 smp_send_reschedule(aprp_cpu_index());
0045 }
0046
0047 int __init rtlx_module_init(void)
0048 {
0049 struct device *dev;
0050 int i, err;
0051
0052 if (!cpu_has_mipsmt) {
0053 pr_warn("VPE loader: not a MIPS MT capable processor\n");
0054 return -ENODEV;
0055 }
0056
0057 if (num_possible_cpus() - aprp_cpu_index() < 1) {
0058 pr_warn("No TCs reserved for AP/SP, not initializing RTLX.\n"
0059 "Pass maxcpus=<n> argument as kernel argument\n");
0060
0061 return -ENODEV;
0062 }
0063
0064 major = register_chrdev(0, RTLX_MODULE_NAME, &rtlx_fops);
0065 if (major < 0) {
0066 pr_err("rtlx_module_init: unable to register device\n");
0067 return major;
0068 }
0069
0070
0071 for (i = 0; i < RTLX_CHANNELS; i++) {
0072 init_waitqueue_head(&channel_wqs[i].rt_queue);
0073 init_waitqueue_head(&channel_wqs[i].lx_queue);
0074 atomic_set(&channel_wqs[i].in_open, 0);
0075 mutex_init(&channel_wqs[i].mutex);
0076
0077 dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
0078 "%s%d", RTLX_MODULE_NAME, i);
0079 if (IS_ERR(dev)) {
0080 while (i--)
0081 device_destroy(mt_class, MKDEV(major, i));
0082
0083 err = PTR_ERR(dev);
0084 goto out_chrdev;
0085 }
0086 }
0087
0088
0089 rtlx_notify.start = rtlx_starting;
0090 rtlx_notify.stop = rtlx_stopping;
0091 vpe_notify(aprp_cpu_index(), &rtlx_notify);
0092
0093 if (cpu_has_vint) {
0094 aprp_hook = rtlx_interrupt;
0095 } else {
0096 pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
0097 err = -ENODEV;
0098 goto out_class;
0099 }
0100
0101 return 0;
0102
0103 out_class:
0104 for (i = 0; i < RTLX_CHANNELS; i++)
0105 device_destroy(mt_class, MKDEV(major, i));
0106 out_chrdev:
0107 unregister_chrdev(major, RTLX_MODULE_NAME);
0108
0109 return err;
0110 }
0111
0112 void __exit rtlx_module_exit(void)
0113 {
0114 int i;
0115
0116 for (i = 0; i < RTLX_CHANNELS; i++)
0117 device_destroy(mt_class, MKDEV(major, i));
0118
0119 unregister_chrdev(major, RTLX_MODULE_NAME);
0120
0121 aprp_hook = NULL;
0122 }