aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-20 08:59:45 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-20 08:59:45 -0400
commitd59bf96cdde5b874a57bfd1425faa45da915d0b7 (patch)
tree351a40b72514d620e5bebea2de38c26f23277ffc /arch/mips/kernel
parent28df955a2ad484d602314b30183ea8496a9aa34a (diff)
parent25f42b6af09e34c3f92107b36b5aa6edc2fdba2f (diff)
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/apm.c605
-rw-r--r--arch/mips/kernel/asm-offsets.c66
-rw-r--r--arch/mips/kernel/branch.c2
-rw-r--r--arch/mips/kernel/i8259.c4
-rw-r--r--arch/mips/kernel/irixsig.c2
-rw-r--r--arch/mips/kernel/ptrace.c26
-rw-r--r--arch/mips/kernel/ptrace32.c16
-rw-r--r--arch/mips/kernel/r4k_switch.S13
-rw-r--r--arch/mips/kernel/setup.c56
-rw-r--r--arch/mips/kernel/traps.c9
11 files changed, 712 insertions, 89 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 34e8a256765c..881c467c6982 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -13,6 +13,8 @@ binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
13 13
14obj-$(CONFIG_MODULES) += mips_ksyms.o module.o 14obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
15 15
16obj-$(CONFIG_APM) += apm.o
17
16obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o 18obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
17obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o 19obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
18obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o 20obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
new file mode 100644
index 000000000000..15f46b4471fd
--- /dev/null
+++ b/arch/mips/kernel/apm.c
@@ -0,0 +1,605 @@
1/*
2 * bios-less APM driver for MIPS Linux
3 * Jamey Hicks <jamey@crl.dec.com>
4 * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
5 *
6 * APM 1.2 Reference:
7 * Intel Corporation, Microsoft Corporation. Advanced Power Management
8 * (APM) BIOS Interface Specification, Revision 1.2, February 1996.
9 *
10 * [This document is available from Microsoft at:
11 * http://www.microsoft.com/hwdev/busbios/amp_12.htm]
12 */
13#include <linux/config.h>
14#include <linux/module.h>
15#include <linux/poll.h>
16#include <linux/timer.h>
17#include <linux/slab.h>
18#include <linux/proc_fs.h>
19#include <linux/miscdevice.h>
20#include <linux/apm_bios.h>
21#include <linux/capability.h>
22#include <linux/sched.h>
23#include <linux/pm.h>
24#include <linux/device.h>
25#include <linux/kernel.h>
26#include <linux/list.h>
27#include <linux/init.h>
28#include <linux/completion.h>
29
30#include <asm/apm.h> /* apm_power_info */
31#include <asm/system.h>
32
33/*
34 * The apm_bios device is one of the misc char devices.
35 * This is its minor number.
36 */
37#define APM_MINOR_DEV 134
38
39/*
40 * See Documentation/Config.help for the configuration options.
41 *
42 * Various options can be changed at boot time as follows:
43 * (We allow underscores for compatibility with the modules code)
44 * apm=on/off enable/disable APM
45 */
46
47/*
48 * Maximum number of events stored
49 */
50#define APM_MAX_EVENTS 16
51
52struct apm_queue {
53 unsigned int event_head;
54 unsigned int event_tail;
55 apm_event_t events[APM_MAX_EVENTS];
56};
57
58/*
59 * The per-file APM data
60 */
61struct apm_user {
62 struct list_head list;
63
64 unsigned int suser: 1;
65 unsigned int writer: 1;
66 unsigned int reader: 1;
67
68 int suspend_result;
69 unsigned int suspend_state;
70#define SUSPEND_NONE 0 /* no suspend pending */
71#define SUSPEND_PENDING 1 /* suspend pending read */
72#define SUSPEND_READ 2 /* suspend read, pending ack */
73#define SUSPEND_ACKED 3 /* suspend acked */
74#define SUSPEND_DONE 4 /* suspend completed */
75
76 struct apm_queue queue;
77};
78
79/*
80 * Local variables
81 */
82static int suspends_pending;
83static int apm_disabled;
84static int mips_apm_active;
85
86static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
87static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
88
89/*
90 * This is a list of everyone who has opened /dev/apm_bios
91 */
92static DECLARE_RWSEM(user_list_lock);
93static LIST_HEAD(apm_user_list);
94
95/*
96 * kapmd info. kapmd provides us a process context to handle
97 * "APM" events within - specifically necessary if we're going
98 * to be suspending the system.
99 */
100static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
101static DECLARE_COMPLETION(kapmd_exit);
102static DEFINE_SPINLOCK(kapmd_queue_lock);
103static struct apm_queue kapmd_queue;
104
105
106static const char driver_version[] = "1.13"; /* no spaces */
107
108
109
110/*
111 * Compatibility cruft until the IPAQ people move over to the new
112 * interface.
113 */
114static void __apm_get_power_status(struct apm_power_info *info)
115{
116}
117
118/*
119 * This allows machines to provide their own "apm get power status" function.
120 */
121void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
122EXPORT_SYMBOL(apm_get_power_status);
123
124
125/*
126 * APM event queue management.
127 */
128static inline int queue_empty(struct apm_queue *q)
129{
130 return q->event_head == q->event_tail;
131}
132
133static inline apm_event_t queue_get_event(struct apm_queue *q)
134{
135 q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
136 return q->events[q->event_tail];
137}
138
139static void queue_add_event(struct apm_queue *q, apm_event_t event)
140{
141 q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
142 if (q->event_head == q->event_tail) {
143 static int notified;
144
145 if (notified++ == 0)
146 printk(KERN_ERR "apm: an event queue overflowed\n");
147 q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
148 }
149 q->events[q->event_head] = event;
150}
151
152static void queue_event_one_user(struct apm_user *as, apm_event_t event)
153{
154 if (as->suser && as->writer) {
155 switch (event) {
156 case APM_SYS_SUSPEND:
157 case APM_USER_SUSPEND:
158 /*
159 * If this user already has a suspend pending,
160 * don't queue another one.
161 */
162 if (as->suspend_state != SUSPEND_NONE)
163 return;
164
165 as->suspend_state = SUSPEND_PENDING;
166 suspends_pending++;
167 break;
168 }
169 }
170 queue_add_event(&as->queue, event);
171}
172
173static void queue_event(apm_event_t event, struct apm_user *sender)
174{
175 struct apm_user *as;
176
177 down_read(&user_list_lock);
178 list_for_each_entry(as, &apm_user_list, list) {
179 if (as != sender && as->reader)
180 queue_event_one_user(as, event);
181 }
182 up_read(&user_list_lock);
183 wake_up_interruptible(&apm_waitqueue);
184}
185
186static void apm_suspend(void)
187{
188 struct apm_user *as;
189 int err = pm_suspend(PM_SUSPEND_MEM);
190
191 /*
192 * Anyone on the APM queues will think we're still suspended.
193 * Send a message so everyone knows we're now awake again.
194 */
195 queue_event(APM_NORMAL_RESUME, NULL);
196
197 /*
198 * Finally, wake up anyone who is sleeping on the suspend.
199 */
200 down_read(&user_list_lock);
201 list_for_each_entry(as, &apm_user_list, list) {
202 as->suspend_result = err;
203 as->suspend_state = SUSPEND_DONE;
204 }
205 up_read(&user_list_lock);
206
207 wake_up(&apm_suspend_waitqueue);
208}
209
210static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
211{
212 struct apm_user *as = fp->private_data;
213 apm_event_t event;
214 int i = count, ret = 0;
215
216 if (count < sizeof(apm_event_t))
217 return -EINVAL;
218
219 if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
220 return -EAGAIN;
221
222 wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
223
224 while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
225 event = queue_get_event(&as->queue);
226
227 ret = -EFAULT;
228 if (copy_to_user(buf, &event, sizeof(event)))
229 break;
230
231 if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
232 as->suspend_state = SUSPEND_READ;
233
234 buf += sizeof(event);
235 i -= sizeof(event);
236 }
237
238 if (i < count)
239 ret = count - i;
240
241 return ret;
242}
243
244static unsigned int apm_poll(struct file *fp, poll_table * wait)
245{
246 struct apm_user *as = fp->private_data;
247
248 poll_wait(fp, &apm_waitqueue, wait);
249 return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
250}
251
252/*
253 * apm_ioctl - handle APM ioctl
254 *
255 * APM_IOC_SUSPEND
256 * This IOCTL is overloaded, and performs two functions. It is used to:
257 * - initiate a suspend
258 * - acknowledge a suspend read from /dev/apm_bios.
259 * Only when everyone who has opened /dev/apm_bios with write permission
260 * has acknowledge does the actual suspend happen.
261 */
262static int
263apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
264{
265 struct apm_user *as = filp->private_data;
266 unsigned long flags;
267 int err = -EINVAL;
268
269 if (!as->suser || !as->writer)
270 return -EPERM;
271
272 switch (cmd) {
273 case APM_IOC_SUSPEND:
274 as->suspend_result = -EINTR;
275
276 if (as->suspend_state == SUSPEND_READ) {
277 /*
278 * If we read a suspend command from /dev/apm_bios,
279 * then the corresponding APM_IOC_SUSPEND ioctl is
280 * interpreted as an acknowledge.
281 */
282 as->suspend_state = SUSPEND_ACKED;
283 suspends_pending--;
284 } else {
285 /*
286 * Otherwise it is a request to suspend the system.
287 * Queue an event for all readers, and expect an
288 * acknowledge from all writers who haven't already
289 * acknowledged.
290 */
291 queue_event(APM_USER_SUSPEND, as);
292 }
293
294 /*
295 * If there are no further acknowledges required, suspend
296 * the system.
297 */
298 if (suspends_pending == 0)
299 apm_suspend();
300
301 /*
302 * Wait for the suspend/resume to complete. If there are
303 * pending acknowledges, we wait here for them.
304 *
305 * Note that we need to ensure that the PM subsystem does
306 * not kick us out of the wait when it suspends the threads.
307 */
308 flags = current->flags;
309 current->flags |= PF_NOFREEZE;
310
311 /*
312 * Note: do not allow a thread which is acking the suspend
313 * to escape until the resume is complete.
314 */
315 if (as->suspend_state == SUSPEND_ACKED)
316 wait_event(apm_suspend_waitqueue,
317 as->suspend_state == SUSPEND_DONE);
318 else
319 wait_event_interruptible(apm_suspend_waitqueue,
320 as->suspend_state == SUSPEND_DONE);
321
322 current->flags = flags;
323 err = as->suspend_result;
324 as->suspend_state = SUSPEND_NONE;
325 break;
326 }
327
328 return err;
329}
330
331static int apm_release(struct inode * inode, struct file * filp)
332{
333 struct apm_user *as = filp->private_data;
334 filp->private_data = NULL;
335
336 down_write(&user_list_lock);
337 list_del(&as->list);
338 up_write(&user_list_lock);
339
340 /*
341 * We are now unhooked from the chain. As far as new
342 * events are concerned, we no longer exist. However, we
343 * need to balance suspends_pending, which means the
344 * possibility of sleeping.
345 */
346 if (as->suspend_state != SUSPEND_NONE) {
347 suspends_pending -= 1;
348 if (suspends_pending == 0)
349 apm_suspend();
350 }
351
352 kfree(as);
353 return 0;
354}
355
356static int apm_open(struct inode * inode, struct file * filp)
357{
358 struct apm_user *as;
359
360 as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
361 if (as) {
362 /*
363 * XXX - this is a tiny bit broken, when we consider BSD
364 * process accounting. If the device is opened by root, we
365 * instantly flag that we used superuser privs. Who knows,
366 * we might close the device immediately without doing a
367 * privileged operation -- cevans
368 */
369 as->suser = capable(CAP_SYS_ADMIN);
370 as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
371 as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
372
373 down_write(&user_list_lock);
374 list_add(&as->list, &apm_user_list);
375 up_write(&user_list_lock);
376
377 filp->private_data = as;
378 }
379
380 return as ? 0 : -ENOMEM;
381}
382
383static struct file_operations apm_bios_fops = {
384 .owner = THIS_MODULE,
385 .read = apm_read,
386 .poll = apm_poll,
387 .ioctl = apm_ioctl,
388 .open = apm_open,
389 .release = apm_release,
390};
391
392static struct miscdevice apm_device = {
393 .minor = APM_MINOR_DEV,
394 .name = "apm_bios",
395 .fops = &apm_bios_fops
396};
397
398
399#ifdef CONFIG_PROC_FS
400/*
401 * Arguments, with symbols from linux/apm_bios.h.
402 *
403 * 0) Linux driver version (this will change if format changes)
404 * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2.
405 * 2) APM flags from APM Installation Check (0x00):
406 * bit 0: APM_16_BIT_SUPPORT
407 * bit 1: APM_32_BIT_SUPPORT
408 * bit 2: APM_IDLE_SLOWS_CLOCK
409 * bit 3: APM_BIOS_DISABLED
410 * bit 4: APM_BIOS_DISENGAGED
411 * 3) AC line status
412 * 0x00: Off-line
413 * 0x01: On-line
414 * 0x02: On backup power (BIOS >= 1.1 only)
415 * 0xff: Unknown
416 * 4) Battery status
417 * 0x00: High
418 * 0x01: Low
419 * 0x02: Critical
420 * 0x03: Charging
421 * 0x04: Selected battery not present (BIOS >= 1.2 only)
422 * 0xff: Unknown
423 * 5) Battery flag
424 * bit 0: High
425 * bit 1: Low
426 * bit 2: Critical
427 * bit 3: Charging
428 * bit 7: No system battery
429 * 0xff: Unknown
430 * 6) Remaining battery life (percentage of charge):
431 * 0-100: valid
432 * -1: Unknown
433 * 7) Remaining battery life (time units):
434 * Number of remaining minutes or seconds
435 * -1: Unknown
436 * 8) min = minutes; sec = seconds
437 */
438static int apm_get_info(char *buf, char **start, off_t fpos, int length)
439{
440 struct apm_power_info info;
441 char *units;
442 int ret;
443
444 info.ac_line_status = 0xff;
445 info.battery_status = 0xff;
446 info.battery_flag = 0xff;
447 info.battery_life = -1;
448 info.time = -1;
449 info.units = -1;
450
451 if (apm_get_power_status)
452 apm_get_power_status(&info);
453
454 switch (info.units) {
455 default: units = "?"; break;
456 case 0: units = "min"; break;
457 case 1: units = "sec"; break;
458 }
459
460 ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
461 driver_version, APM_32_BIT_SUPPORT,
462 info.ac_line_status, info.battery_status,
463 info.battery_flag, info.battery_life,
464 info.time, units);
465
466 return ret;
467}
468#endif
469
470static int kapmd(void *arg)
471{
472 daemonize("kapmd");
473 current->flags |= PF_NOFREEZE;
474
475 do {
476 apm_event_t event;
477
478 wait_event_interruptible(kapmd_wait,
479 !queue_empty(&kapmd_queue) || !mips_apm_active);
480
481 if (!mips_apm_active)
482 break;
483
484 spin_lock_irq(&kapmd_queue_lock);
485 event = 0;
486 if (!queue_empty(&kapmd_queue))
487 event = queue_get_event(&kapmd_queue);
488 spin_unlock_irq(&kapmd_queue_lock);
489
490 switch (event) {
491 case 0:
492 break;
493
494 case APM_LOW_BATTERY:
495 case APM_POWER_STATUS_CHANGE:
496 queue_event(event, NULL);
497 break;
498
499 case APM_USER_SUSPEND:
500 case APM_SYS_SUSPEND:
501 queue_event(event, NULL);
502 if (suspends_pending == 0)
503 apm_suspend();
504 break;
505
506 case APM_CRITICAL_SUSPEND:
507 apm_suspend();
508 break;
509 }
510 } while (1);
511
512 complete_and_exit(&kapmd_exit, 0);
513}
514
515static int __init apm_init(void)
516{
517 int ret;
518
519 if (apm_disabled) {
520 printk(KERN_NOTICE "apm: disabled on user request.\n");
521 return -ENODEV;
522 }
523
524 mips_apm_active = 1;
525
526 ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
527 if (ret < 0) {
528 mips_apm_active = 0;
529 return ret;
530 }
531
532#ifdef CONFIG_PROC_FS
533 create_proc_info_entry("apm", 0, NULL, apm_get_info);
534#endif
535
536 ret = misc_register(&apm_device);
537 if (ret != 0) {
538 remove_proc_entry("apm", NULL);
539
540 mips_apm_active = 0;
541 wake_up(&kapmd_wait);
542 wait_for_completion(&kapmd_exit);
543 }
544
545 return ret;
546}
547
548static void __exit apm_exit(void)
549{
550 misc_deregister(&apm_device);
551 remove_proc_entry("apm", NULL);
552
553 mips_apm_active = 0;
554 wake_up(&kapmd_wait);
555 wait_for_completion(&kapmd_exit);
556}
557
558module_init(apm_init);
559module_exit(apm_exit);
560
561MODULE_AUTHOR("Stephen Rothwell");
562MODULE_DESCRIPTION("Advanced Power Management");
563MODULE_LICENSE("GPL");
564
565#ifndef MODULE
566static int __init apm_setup(char *str)
567{
568 while ((str != NULL) && (*str != '\0')) {
569 if (strncmp(str, "off", 3) == 0)
570 apm_disabled = 1;
571 if (strncmp(str, "on", 2) == 0)
572 apm_disabled = 0;
573 str = strchr(str, ',');
574 if (str != NULL)
575 str += strspn(str, ", \t");
576 }
577 return 1;
578}
579
580__setup("apm=", apm_setup);
581#endif
582
583/**
584 * apm_queue_event - queue an APM event for kapmd
585 * @event: APM event
586 *
587 * Queue an APM event for kapmd to process and ultimately take the
588 * appropriate action. Only a subset of events are handled:
589 * %APM_LOW_BATTERY
590 * %APM_POWER_STATUS_CHANGE
591 * %APM_USER_SUSPEND
592 * %APM_SYS_SUSPEND
593 * %APM_CRITICAL_SUSPEND
594 */
595void apm_queue_event(apm_event_t event)
596{
597 unsigned long flags;
598
599 spin_lock_irqsave(&kapmd_queue_lock, flags);
600 queue_add_event(&kapmd_queue, event);
601 spin_unlock_irqrestore(&kapmd_queue_lock, flags);
602
603 wake_up_interruptible(&kapmd_wait);
604}
605EXPORT_SYMBOL(apm_queue_event);
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 0facfaf4e950..f1bb6a2dc5fc 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -141,72 +141,72 @@ void output_thread_defines(void)
141void output_thread_fpu_defines(void) 141void output_thread_fpu_defines(void)
142{ 142{
143 offset("#define THREAD_FPR0 ", 143 offset("#define THREAD_FPR0 ",
144 struct task_struct, thread.fpu.hard.fpr[0]); 144 struct task_struct, thread.fpu.fpr[0]);
145 offset("#define THREAD_FPR1 ", 145 offset("#define THREAD_FPR1 ",
146 struct task_struct, thread.fpu.hard.fpr[1]); 146 struct task_struct, thread.fpu.fpr[1]);
147 offset("#define THREAD_FPR2 ", 147 offset("#define THREAD_FPR2 ",
148 struct task_struct, thread.fpu.hard.fpr[2]); 148 struct task_struct, thread.fpu.fpr[2]);
149 offset("#define THREAD_FPR3 ", 149 offset("#define THREAD_FPR3 ",
150 struct task_struct, thread.fpu.hard.fpr[3]); 150 struct task_struct, thread.fpu.fpr[3]);
151 offset("#define THREAD_FPR4 ", 151 offset("#define THREAD_FPR4 ",
152 struct task_struct, thread.fpu.hard.fpr[4]); 152 struct task_struct, thread.fpu.fpr[4]);
153 offset("#define THREAD_FPR5 ", 153 offset("#define THREAD_FPR5 ",
154 struct task_struct, thread.fpu.hard.fpr[5]); 154 struct task_struct, thread.fpu.fpr[5]);
155 offset("#define THREAD_FPR6 ", 155 offset("#define THREAD_FPR6 ",
156 struct task_struct, thread.fpu.hard.fpr[6]); 156 struct task_struct, thread.fpu.fpr[6]);
157 offset("#define THREAD_FPR7 ", 157 offset("#define THREAD_FPR7 ",
158 struct task_struct, thread.fpu.hard.fpr[7]); 158 struct task_struct, thread.fpu.fpr[7]);
159 offset("#define THREAD_FPR8 ", 159 offset("#define THREAD_FPR8 ",
160 struct task_struct, thread.fpu.hard.fpr[8]); 160 struct task_struct, thread.fpu.fpr[8]);
161 offset("#define THREAD_FPR9 ", 161 offset("#define THREAD_FPR9 ",
162 struct task_struct, thread.fpu.hard.fpr[9]); 162 struct task_struct, thread.fpu.fpr[9]);
163 offset("#define THREAD_FPR10 ", 163 offset("#define THREAD_FPR10 ",
164 struct task_struct, thread.fpu.hard.fpr[10]); 164 struct task_struct, thread.fpu.fpr[10]);
165 offset("#define THREAD_FPR11 ", 165 offset("#define THREAD_FPR11 ",
166 struct task_struct, thread.fpu.hard.fpr[11]); 166 struct task_struct, thread.fpu.fpr[11]);
167 offset("#define THREAD_FPR12 ", 167 offset("#define THREAD_FPR12 ",
168 struct task_struct, thread.fpu.hard.fpr[12]); 168 struct task_struct, thread.fpu.fpr[12]);
169 offset("#define THREAD_FPR13 ", 169 offset("#define THREAD_FPR13 ",
170 struct task_struct, thread.fpu.hard.fpr[13]); 170 struct task_struct, thread.fpu.fpr[13]);
171 offset("#define THREAD_FPR14 ", 171 offset("#define THREAD_FPR14 ",
172 struct task_struct, thread.fpu.hard.fpr[14]); 172 struct task_struct, thread.fpu.fpr[14]);
173 offset("#define THREAD_FPR15 ", 173 offset("#define THREAD_FPR15 ",
174 struct task_struct, thread.fpu.hard.fpr[15]); 174 struct task_struct, thread.fpu.fpr[15]);
175 offset("#define THREAD_FPR16 ", 175 offset("#define THREAD_FPR16 ",
176 struct task_struct, thread.fpu.hard.fpr[16]); 176 struct task_struct, thread.fpu.fpr[16]);
177 offset("#define THREAD_FPR17 ", 177 offset("#define THREAD_FPR17 ",
178 struct task_struct, thread.fpu.hard.fpr[17]); 178 struct task_struct, thread.fpu.fpr[17]);
179 offset("#define THREAD_FPR18 ", 179 offset("#define THREAD_FPR18 ",
180 struct task_struct, thread.fpu.hard.fpr[18]); 180 struct task_struct, thread.fpu.fpr[18]);
181 offset("#define THREAD_FPR19 ", 181 offset("#define THREAD_FPR19 ",
182 struct task_struct, thread.fpu.hard.fpr[19]); 182 struct task_struct, thread.fpu.fpr[19]);
183 offset("#define THREAD_FPR20 ", 183 offset("#define THREAD_FPR20 ",
184 struct task_struct, thread.fpu.hard.fpr[20]); 184 struct task_struct, thread.fpu.fpr[20]);
185 offset("#define THREAD_FPR21 ", 185 offset("#define THREAD_FPR21 ",
186 struct task_struct, thread.fpu.hard.fpr[21]); 186 struct task_struct, thread.fpu.fpr[21]);
187 offset("#define THREAD_FPR22 ", 187 offset("#define THREAD_FPR22 ",
188 struct task_struct, thread.fpu.hard.fpr[22]); 188 struct task_struct, thread.fpu.fpr[22]);
189 offset("#define THREAD_FPR23 ", 189 offset("#define THREAD_FPR23 ",
190 struct task_struct, thread.fpu.hard.fpr[23]); 190 struct task_struct, thread.fpu.fpr[23]);
191 offset("#define THREAD_FPR24 ", 191 offset("#define THREAD_FPR24 ",
192 struct task_struct, thread.fpu.hard.fpr[24]); 192 struct task_struct, thread.fpu.fpr[24]);
193 offset("#define THREAD_FPR25 ", 193 offset("#define THREAD_FPR25 ",
194 struct task_struct, thread.fpu.hard.fpr[25]); 194 struct task_struct, thread.fpu.fpr[25]);
195 offset("#define THREAD_FPR26 ", 195 offset("#define THREAD_FPR26 ",
196 struct task_struct, thread.fpu.hard.fpr[26]); 196 struct task_struct, thread.fpu.fpr[26]);
197 offset("#define THREAD_FPR27 ", 197 offset("#define THREAD_FPR27 ",
198 struct task_struct, thread.fpu.hard.fpr[27]); 198 struct task_struct, thread.fpu.fpr[27]);
199 offset("#define THREAD_FPR28 ", 199 offset("#define THREAD_FPR28 ",
200 struct task_struct, thread.fpu.hard.fpr[28]); 200 struct task_struct, thread.fpu.fpr[28]);
201 offset("#define THREAD_FPR29 ", 201 offset("#define THREAD_FPR29 ",
202 struct task_struct, thread.fpu.hard.fpr[29]); 202 struct task_struct, thread.fpu.fpr[29]);
203 offset("#define THREAD_FPR30 ", 203 offset("#define THREAD_FPR30 ",
204 struct task_struct, thread.fpu.hard.fpr[30]); 204 struct task_struct, thread.fpu.fpr[30]);
205 offset("#define THREAD_FPR31 ", 205 offset("#define THREAD_FPR31 ",
206 struct task_struct, thread.fpu.hard.fpr[31]); 206 struct task_struct, thread.fpu.fpr[31]);
207 207
208 offset("#define THREAD_FCR31 ", 208 offset("#define THREAD_FCR31 ",
209 struct task_struct, thread.fpu.hard.fcr31); 209 struct task_struct, thread.fpu.fcr31);
210 linefeed; 210 linefeed;
211} 211}
212 212
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index b6232d9033cb..76fd3f22c766 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -178,7 +178,7 @@ int __compute_return_epc(struct pt_regs *regs)
178 if (is_fpu_owner()) 178 if (is_fpu_owner())
179 asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); 179 asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
180 else 180 else
181 fcr31 = current->thread.fpu.hard.fcr31; 181 fcr31 = current->thread.fpu.fcr31;
182 preempt_enable(); 182 preempt_enable();
183 183
184 bit = (insn.i_format.rt >> 2); 184 bit = (insn.i_format.rt >> 2);
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 2125ba5f1d9b..0cb8ed5662f3 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -302,11 +302,11 @@ static struct irqaction irq2 = {
302}; 302};
303 303
304static struct resource pic1_io_resource = { 304static struct resource pic1_io_resource = {
305 "pic1", 0x20, 0x3f, IORESOURCE_BUSY 305 .name = "pic1", .start = 0x20, .end = 0x3f, .flags = IORESOURCE_BUSY
306}; 306};
307 307
308static struct resource pic2_io_resource = { 308static struct resource pic2_io_resource = {
309 "pic2", 0xa0, 0xbf, IORESOURCE_BUSY 309 .name = "pic2", .start = 0xa0, .end = 0xbf, .flags = IORESOURCE_BUSY
310}; 310};
311 311
312/* 312/*
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 8150f071f80a..a9bf6cc3abd1 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -260,7 +260,7 @@ irix_sigreturn(struct pt_regs *regs)
260 260
261 for(i = 0; i < 32; i++) 261 for(i = 0; i < 32; i++)
262 error |= __get_user(fregs[i], &context->fpregs[i]); 262 error |= __get_user(fregs[i], &context->fpregs[i]);
263 error |= __get_user(current->thread.fpu.hard.fcr31, &context->fpcsr); 263 error |= __get_user(current->thread.fpu.fcr31, &context->fpcsr);
264 } 264 }
265 265
266 /* XXX do sigstack crapola here... XXX */ 266 /* XXX do sigstack crapola here... XXX */
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 9b4733c12395..1d44025188d8 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -120,11 +120,11 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
120 __put_user ((__u64) -1, i + (__u64 __user *) data); 120 __put_user ((__u64) -1, i + (__u64 __user *) data);
121 } 121 }
122 122
123 __put_user (child->thread.fpu.fcr31, data + 64);
124
123 if (cpu_has_fpu) { 125 if (cpu_has_fpu) {
124 unsigned int flags, tmp; 126 unsigned int flags, tmp;
125 127
126 __put_user (child->thread.fpu.hard.fcr31, data + 64);
127
128 preempt_disable(); 128 preempt_disable();
129 if (cpu_has_mipsmt) { 129 if (cpu_has_mipsmt) {
130 unsigned int vpflags = dvpe(); 130 unsigned int vpflags = dvpe();
@@ -142,7 +142,6 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
142 preempt_enable(); 142 preempt_enable();
143 __put_user (tmp, data + 65); 143 __put_user (tmp, data + 65);
144 } else { 144 } else {
145 __put_user (child->thread.fpu.soft.fcr31, data + 64);
146 __put_user ((__u32) 0, data + 65); 145 __put_user ((__u32) 0, data + 65);
147 } 146 }
148 147
@@ -162,10 +161,7 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data)
162 for (i = 0; i < 32; i++) 161 for (i = 0; i < 32; i++)
163 __get_user (fregs[i], i + (__u64 __user *) data); 162 __get_user (fregs[i], i + (__u64 __user *) data);
164 163
165 if (cpu_has_fpu) 164 __get_user (child->thread.fpu.fcr31, data + 64);
166 __get_user (child->thread.fpu.hard.fcr31, data + 64);
167 else
168 __get_user (child->thread.fpu.soft.fcr31, data + 64);
169 165
170 /* FIR may not be written. */ 166 /* FIR may not be written. */
171 167
@@ -241,10 +237,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
241 tmp = regs->lo; 237 tmp = regs->lo;
242 break; 238 break;
243 case FPC_CSR: 239 case FPC_CSR:
244 if (cpu_has_fpu) 240 tmp = child->thread.fpu.fcr31;
245 tmp = child->thread.fpu.hard.fcr31;
246 else
247 tmp = child->thread.fpu.soft.fcr31;
248 break; 241 break;
249 case FPC_EIR: { /* implementation / version register */ 242 case FPC_EIR: { /* implementation / version register */
250 unsigned int flags; 243 unsigned int flags;
@@ -336,9 +329,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
336 329
337 if (!tsk_used_math(child)) { 330 if (!tsk_used_math(child)) {
338 /* FP not yet used */ 331 /* FP not yet used */
339 memset(&child->thread.fpu.hard, ~0, 332 memset(&child->thread.fpu, ~0,
340 sizeof(child->thread.fpu.hard)); 333 sizeof(child->thread.fpu));
341 child->thread.fpu.hard.fcr31 = 0; 334 child->thread.fpu.fcr31 = 0;
342 } 335 }
343#ifdef CONFIG_32BIT 336#ifdef CONFIG_32BIT
344 /* 337 /*
@@ -369,10 +362,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
369 regs->lo = data; 362 regs->lo = data;
370 break; 363 break;
371 case FPC_CSR: 364 case FPC_CSR:
372 if (cpu_has_fpu) 365 child->thread.fpu.fcr31 = data;
373 child->thread.fpu.hard.fcr31 = data;
374 else
375 child->thread.fpu.soft.fcr31 = data;
376 break; 366 break;
377 case DSP_BASE ... DSP_BASE + 5: { 367 case DSP_BASE ... DSP_BASE + 5: {
378 dspreg_t *dregs; 368 dspreg_t *dregs;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 8704dc0496ea..f40ecd8be05f 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -166,10 +166,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
166 tmp = regs->lo; 166 tmp = regs->lo;
167 break; 167 break;
168 case FPC_CSR: 168 case FPC_CSR:
169 if (cpu_has_fpu) 169 tmp = child->thread.fpu.fcr31;
170 tmp = child->thread.fpu.hard.fcr31;
171 else
172 tmp = child->thread.fpu.soft.fcr31;
173 break; 170 break;
174 case FPC_EIR: { /* implementation / version register */ 171 case FPC_EIR: { /* implementation / version register */
175 unsigned int flags; 172 unsigned int flags;
@@ -288,9 +285,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
288 285
289 if (!tsk_used_math(child)) { 286 if (!tsk_used_math(child)) {
290 /* FP not yet used */ 287 /* FP not yet used */
291 memset(&child->thread.fpu.hard, ~0, 288 memset(&child->thread.fpu, ~0,
292 sizeof(child->thread.fpu.hard)); 289 sizeof(child->thread.fpu));
293 child->thread.fpu.hard.fcr31 = 0; 290 child->thread.fpu.fcr31 = 0;
294 } 291 }
295 /* 292 /*
296 * The odd registers are actually the high order bits 293 * The odd registers are actually the high order bits
@@ -318,10 +315,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
318 regs->lo = data; 315 regs->lo = data;
319 break; 316 break;
320 case FPC_CSR: 317 case FPC_CSR:
321 if (cpu_has_fpu) 318 child->thread.fpu.fcr31 = data;
322 child->thread.fpu.hard.fcr31 = data;
323 else
324 child->thread.fpu.soft.fcr31 = data;
325 break; 319 break;
326 case DSP_BASE ... DSP_BASE + 5: { 320 case DSP_BASE ... DSP_BASE + 5: {
327 dspreg_t *dregs; 321 dspreg_t *dregs;
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 0b1b54acee9f..db94e556fc97 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -75,8 +75,8 @@
75 and t0, t0, t1 75 and t0, t0, t1
76 LONG_S t0, ST_OFF(t3) 76 LONG_S t0, ST_OFF(t3)
77 77
78 fpu_save_double a0 t1 t0 t2 # c0_status passed in t1 78 fpu_save_double a0 t0 t1 # c0_status passed in t0
79 # clobbers t0 and t2 79 # clobbers t1
801: 801:
81 81
82 /* 82 /*
@@ -129,9 +129,9 @@
129 */ 129 */
130LEAF(_save_fp) 130LEAF(_save_fp)
131#ifdef CONFIG_64BIT 131#ifdef CONFIG_64BIT
132 mfc0 t1, CP0_STATUS 132 mfc0 t0, CP0_STATUS
133#endif 133#endif
134 fpu_save_double a0 t1 t0 t2 # clobbers t1 134 fpu_save_double a0 t0 t1 # clobbers t1
135 jr ra 135 jr ra
136 END(_save_fp) 136 END(_save_fp)
137 137
@@ -139,7 +139,10 @@ LEAF(_save_fp)
139 * Restore a thread's fp context. 139 * Restore a thread's fp context.
140 */ 140 */
141LEAF(_restore_fp) 141LEAF(_restore_fp)
142 fpu_restore_double a0, t1 # clobbers t1 142#ifdef CONFIG_64BIT
143 mfc0 t0, CP0_STATUS
144#endif
145 fpu_restore_double a0 t0 t1 # clobbers t1
143 jr ra 146 jr ra
144 END(_restore_fp) 147 END(_restore_fp)
145 148
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 397a70e651b5..bfcec8d9bfe4 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -442,6 +442,48 @@ static inline void bootmem_init(void)
442#endif /* CONFIG_BLK_DEV_INITRD */ 442#endif /* CONFIG_BLK_DEV_INITRD */
443} 443}
444 444
445/*
446 * arch_mem_init - initialize memory managment subsystem
447 *
448 * o plat_mem_setup() detects the memory configuration and will record detected
449 * memory areas using add_memory_region.
450 * o parse_cmdline_early() parses the command line for mem= options which,
451 * iff detected, will override the results of the automatic detection.
452 *
453 * At this stage the memory configuration of the system is known to the
454 * kernel but generic memory managment system is still entirely uninitialized.
455 *
456 * o bootmem_init()
457 * o sparse_init()
458 * o paging_init()
459 *
460 * At this stage the bootmem allocator is ready to use.
461 *
462 * NOTE: historically plat_mem_setup did the entire platform initialization.
463 * This was rather impractical because it meant plat_mem_setup had to
464 * get away without any kind of memory allocator. To keep old code from
465 * breaking plat_setup was just renamed to plat_setup and a second platform
466 * initialization hook for anything else was introduced.
467 */
468
469extern void plat_mem_setup(void);
470
471static void __init arch_mem_init(char **cmdline_p)
472{
473 /* call board setup routine */
474 plat_mem_setup();
475
476 strlcpy(command_line, arcs_cmdline, sizeof(command_line));
477 strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
478
479 *cmdline_p = command_line;
480
481 parse_cmdline_early();
482 bootmem_init();
483 sparse_init();
484 paging_init();
485}
486
445static inline void resource_init(void) 487static inline void resource_init(void)
446{ 488{
447 int i; 489 int i;
@@ -495,8 +537,6 @@ static inline void resource_init(void)
495#undef MAXMEM 537#undef MAXMEM
496#undef MAXMEM_PFN 538#undef MAXMEM_PFN
497 539
498extern void plat_setup(void);
499
500void __init setup_arch(char **cmdline_p) 540void __init setup_arch(char **cmdline_p)
501{ 541{
502 cpu_probe(); 542 cpu_probe();
@@ -511,18 +551,8 @@ void __init setup_arch(char **cmdline_p)
511#endif 551#endif
512#endif 552#endif
513 553
514 /* call board setup routine */ 554 arch_mem_init(cmdline_p);
515 plat_setup();
516 555
517 strlcpy(command_line, arcs_cmdline, sizeof(command_line));
518 strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
519
520 *cmdline_p = command_line;
521
522 parse_cmdline_early();
523 bootmem_init();
524 sparse_init();
525 paging_init();
526 resource_init(); 556 resource_init();
527#ifdef CONFIG_SMP 557#ifdef CONFIG_SMP
528 plat_smp_setup(); 558 plat_smp_setup();
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index a7564b08eb4d..ad16eceb24dd 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -65,7 +65,7 @@ extern asmlinkage void handle_mcheck(void);
65extern asmlinkage void handle_reserved(void); 65extern asmlinkage void handle_reserved(void);
66 66
67extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, 67extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
68 struct mips_fpu_soft_struct *ctx); 68 struct mips_fpu_struct *ctx);
69 69
70void (*board_be_init)(void); 70void (*board_be_init)(void);
71int (*board_be_handler)(struct pt_regs *regs, int is_fixup); 71int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -600,8 +600,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
600 preempt_enable(); 600 preempt_enable();
601 601
602 /* Run the emulator */ 602 /* Run the emulator */
603 sig = fpu_emulator_cop1Handler (regs, 603 sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu);
604 &current->thread.fpu.soft);
605 604
606 preempt_disable(); 605 preempt_disable();
607 606
@@ -610,7 +609,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
610 * We can't allow the emulated instruction to leave any of 609 * We can't allow the emulated instruction to leave any of
611 * the cause bit set in $fcr31. 610 * the cause bit set in $fcr31.
612 */ 611 */
613 current->thread.fpu.soft.fcr31 &= ~FPU_CSR_ALL_X; 612 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
614 613
615 /* Restore the hardware register state */ 614 /* Restore the hardware register state */
616 restore_fp(current); 615 restore_fp(current);
@@ -755,7 +754,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
755 754
756 if (!cpu_has_fpu) { 755 if (!cpu_has_fpu) {
757 int sig = fpu_emulator_cop1Handler(regs, 756 int sig = fpu_emulator_cop1Handler(regs,
758 &current->thread.fpu.soft); 757 &current->thread.fpu);
759 if (sig) 758 if (sig)
760 force_sig(sig, current); 759 force_sig(sig, current);
761#ifdef CONFIG_MIPS_MT_FPAFF 760#ifdef CONFIG_MIPS_MT_FPAFF