summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kconfig49
-rw-r--r--arch/mips/au1000/common/power.c46
-rw-r--r--arch/mips/configs/ip27_defconfig2
-rw-r--r--arch/mips/dec/Makefile1
-rw-r--r--arch/mips/dec/int-handler.S4
-rw-r--r--arch/mips/dec/prom/identify.c3
-rw-r--r--arch/mips/dec/setup.c2
-rw-r--r--arch/mips/dec/tc.c95
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/apm.c604
-rw-r--r--arch/mips/kernel/asm-offsets.c1
-rw-r--r--arch/mips/kernel/entry.S19
-rw-r--r--arch/mips/kernel/linux32.c91
-rw-r--r--arch/mips/kernel/mips-mt.c19
-rw-r--r--arch/mips/kernel/rtlx.c25
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S4
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/setup.c2
-rw-r--r--arch/mips/kernel/signal-common.h174
-rw-r--r--arch/mips/kernel/signal.c248
-rw-r--r--arch/mips/kernel/signal32.c380
-rw-r--r--arch/mips/kernel/signal_n32.c43
-rw-r--r--arch/mips/kernel/time.c7
-rw-r--r--arch/mips/kernel/vmlinux.lds.S2
-rw-r--r--arch/mips/kernel/vpe.c24
-rw-r--r--arch/mips/lasat/sysctl.c147
-rw-r--r--arch/mips/mm/Makefile14
-rw-r--r--arch/mips/mm/c-sb1.c6
-rw-r--r--arch/mips/mm/cache.c2
-rw-r--r--arch/mips/mm/dma-coherent.c254
-rw-r--r--arch/mips/mm/dma-default.c (renamed from arch/mips/mm/dma-noncoherent.c)209
-rw-r--r--arch/mips/mm/dma-ip27.c257
-rw-r--r--arch/mips/mm/dma-ip32.c383
-rw-r--r--arch/mips/momentum/jaguar_atx/platform.c2
-rw-r--r--arch/mips/momentum/ocelot_3/platform.c2
-rw-r--r--arch/mips/pci/Makefile2
-rw-r--r--arch/mips/pci/pci-dac.c79
-rw-r--r--arch/mips/philips/pnx8550/common/proc.c7
-rw-r--r--arch/mips/sibyte/sb1250/bcm1250_tbprof.c2
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c2
41 files changed, 978 insertions, 2241 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 44a0224c32dd..a92ce6bd7cf1 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -8,6 +8,10 @@ mainmenu "Linux/MIPS Kernel Configuration"
menu "Machine selection"
+config ZONE_DMA
+ bool
+ default y
+
choice
prompt "System type"
default SGI_IP22
@@ -594,8 +598,6 @@ config SGI_IP32
select ARC
select ARC32
select BOOT_ELF32
- select OWN_DMA
- select DMA_IP32
select DMA_NONCOHERENT
select HW_HAS_PCI
select R5000_CPU_SCACHE
@@ -753,6 +755,7 @@ config TOSHIBA_JMR3927
select SWAP_IO_SPACE
select SYS_HAS_CPU_TX39XX
select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_BIG_ENDIAN
select TOSHIBA_BOARDS
@@ -767,6 +770,7 @@ config TOSHIBA_RBTX4927
select SYS_HAS_CPU_TX49XX
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_BIG_ENDIAN
select TOSHIBA_BOARDS
select GENERIC_HARDIRQS_NO__DO_IRQ
@@ -877,9 +881,6 @@ config DMA_NONCOHERENT
config DMA_NEED_PCI_MAP_STATE
bool
-config OWN_DMA
- bool
-
config EARLY_PRINTK
bool
@@ -934,6 +935,9 @@ config CPU_LITTLE_ENDIAN
endchoice
+config SYS_SUPPORTS_APM_EMULATION
+ bool
+
config SYS_SUPPORTS_BIG_ENDIAN
bool
@@ -1001,6 +1005,7 @@ config SOC_AU1X00
bool
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_APM_EMULATION
config PNX8550
bool
@@ -2071,35 +2076,11 @@ config BINFMT_ELF32
bool
default y if MIPS32_O32 || MIPS32_N32
-config PM
- bool "Power Management support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && SOC_AU1X00
-
-config APM
- tristate "Advanced Power Management Emulation"
- depends on PM
- ---help---
- APM is a BIOS specification for saving power using several different
- techniques. This is mostly useful for battery powered systems with
- APM compliant BIOSes. If you say Y here, the system time will be
- reset after a RESUME operation, the /proc/apm device will provide
- battery status information, and user-space programs will receive
- notification of APM "events" (e.g. battery status change).
-
- In order to use APM, you will need supporting software. For location
- and more information, read <file:Documentation/pm.txt> and the
- Battery Powered Linux mini-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- This driver does not spin down disk drives (see the hdparm(8)
- manpage ("man 8 hdparm") for that), and it doesn't turn off
- VESA-compliant "green" monitors.
-
- Generally, if you don't have a battery in your machine, there isn't
- much point in using this driver and you should say N. If you get
- random kernel OOPSes or reboots that don't seem to be related to
- anything, try disabling/enabling this option (or disabling/enabling
- APM in your BIOS).
+endmenu
+
+menu "Power management options"
+
+source "kernel/power/Kconfig"
endmenu
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
index 7504a6364616..3901e8e04755 100644
--- a/arch/mips/au1000/common/power.c
+++ b/arch/mips/au1000/common/power.c
@@ -62,12 +62,6 @@ extern unsigned long save_local_and_disable(int controller);
extern void restore_local_and_enable(int controller, unsigned long mask);
extern void local_enable_irq(unsigned int irq_nr);
-/* Quick acpi hack. This will have to change! */
-#define CTL_ACPI 9999
-#define ACPI_S1_SLP_TYP 19
-#define ACPI_SLEEP 21
-
-
static DEFINE_SPINLOCK(pm_lock);
/* We need to save/restore a bunch of core registers that are
@@ -425,15 +419,41 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
static struct ctl_table pm_table[] = {
- {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},
- {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},
- {CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},
- {0}
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "suspend",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0600,
+ .proc_handler = &pm_do_suspend
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sleep",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0600,
+ .proc_handler = &pm_do_sleep
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "freq",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0600,
+ .proc_handler = &pm_do_freq
+ },
+ {}
};
static struct ctl_table pm_dir_table[] = {
- {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
- {0}
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "pm",
+ .mode = 0555,
+ .child = pm_table
+ },
+ {}
};
/*
@@ -441,7 +461,7 @@ static struct ctl_table pm_dir_table[] = {
*/
static int __init pm_init(void)
{
- register_sysctl_table(pm_dir_table, 1);
+ register_sysctl_table(pm_dir_table);
return 0;
}
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 96090f28373b..f21186c12d81 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -264,7 +264,7 @@ CONFIG_BINFMT_ELF=y
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
-# CONFIG_MIPS32_N32 is not set
+CONFIG_MIPS32_N32=y
CONFIG_BINFMT_ELF32=y
#
diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile
index ed181fdc3ac9..8b790c2900d5 100644
--- a/arch/mips/dec/Makefile
+++ b/arch/mips/dec/Makefile
@@ -6,6 +6,7 @@ obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \
kn02-irq.o kn02xa-berr.o reset.o setup.o time.o
obj-$(CONFIG_PROM_CONSOLE) += promcon.o
+obj-$(CONFIG_TC) += tc.o
obj-$(CONFIG_CPU_HAS_WB) += wbflush.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index b251ef864c33..00cecdcc75f2 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -264,9 +264,6 @@
srlv t3,t1,t2
handle_it:
- LONG_L s0, TI_REGS($28)
- LONG_S sp, TI_REGS($28)
- PTR_LA ra, ret_from_irq
j dec_irq_dispatch
nop
@@ -277,7 +274,6 @@ fpu:
#endif
spurious:
- PTR_LA ra, _ret_from_irq
j spurious_interrupt
nop
END(plat_irq_dispatch)
diff --git a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c
index 81d5e878ddce..c4e3c1ea0d48 100644
--- a/arch/mips/dec/prom/identify.c
+++ b/arch/mips/dec/prom/identify.c
@@ -88,6 +88,7 @@ static inline void prom_init_kn02(void)
{
dec_kn_slot_base = KN02_SLOT_BASE;
dec_kn_slot_size = KN02_SLOT_SIZE;
+ dec_tc_bus = 1;
dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN02_RTC);
}
@@ -96,6 +97,7 @@ static inline void prom_init_kn02xa(void)
{
dec_kn_slot_base = KN02XA_SLOT_BASE;
dec_kn_slot_size = IOASIC_SLOT_SIZE;
+ dec_tc_bus = 1;
ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
@@ -105,6 +107,7 @@ static inline void prom_init_kn03(void)
{
dec_kn_slot_base = KN03_SLOT_BASE;
dec_kn_slot_size = IOASIC_SLOT_SIZE;
+ dec_tc_bus = 1;
ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 1058e2f409bb..b8a5e75ba0ab 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -53,6 +53,8 @@ unsigned long dec_kn_slot_base, dec_kn_slot_size;
EXPORT_SYMBOL(dec_kn_slot_base);
EXPORT_SYMBOL(dec_kn_slot_size);
+int dec_tc_bus;
+
spinlock_t ioasic_ssr_lock;
volatile u32 *ioasic_base;
diff --git a/arch/mips/dec/tc.c b/arch/mips/dec/tc.c
new file mode 100644
index 000000000000..732027c79834
--- /dev/null
+++ b/arch/mips/dec/tc.c
@@ -0,0 +1,95 @@
+/*
+ * TURBOchannel architecture calls.
+ *
+ * Copyright (c) Harald Koerfgen, 1998
+ * Copyright (c) 2001, 2003, 2005, 2006 Maciej W. Rozycki
+ * Copyright (c) 2005 James Simmons
+ *
+ * This file is subject to the terms and conditions of the GNU
+ * General Public License. See the file "COPYING" in the main
+ * directory of this archive for more details.
+ */
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/tc.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/paccess.h>
+
+#include <asm/dec/interrupts.h>
+#include <asm/dec/prom.h>
+#include <asm/dec/system.h>
+
+/*
+ * Protected read byte from TURBOchannel slot space.
+ */
+int tc_preadb(u8 *valp, void __iomem *addr)
+{
+ return get_dbe(*valp, (u8 *)addr);
+}
+
+/*
+ * Get TURBOchannel bus information as specified by the spec, plus
+ * the slot space base address and the number of slots.
+ */
+int __init tc_bus_get_info(struct tc_bus *tbus)
+{
+ if (!dec_tc_bus)
+ return -ENXIO;
+
+ memcpy(&tbus->info, rex_gettcinfo(), sizeof(tbus->info));
+ tbus->slot_base = CPHYSADDR((long)rex_slot_address(0));
+
+ switch (mips_machtype) {
+ case MACH_DS5000_200:
+ tbus->num_tcslots = 7;
+ break;
+ case MACH_DS5000_2X0:
+ case MACH_DS5900:
+ tbus->ext_slot_base = 0x20000000;
+ tbus->ext_slot_size = 0x20000000;
+ /* fall through */
+ case MACH_DS5000_1XX:
+ tbus->num_tcslots = 3;
+ break;
+ case MACH_DS5000_XX:
+ tbus->num_tcslots = 2;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Get the IRQ for the specified slot.
+ */
+void __init tc_device_get_irq(struct tc_dev *tdev)
+{
+ switch (tdev->slot) {
+ case 0:
+ tdev->interrupt = dec_interrupt[DEC_IRQ_TC0];
+ break;
+ case 1:
+ tdev->interrupt = dec_interrupt[DEC_IRQ_TC1];
+ break;
+ case 2:
+ tdev->interrupt = dec_interrupt[DEC_IRQ_TC2];
+ break;
+ /*
+ * Yuck! DS5000/200 onboard devices
+ */
+ case 5:
+ tdev->interrupt = dec_interrupt[DEC_IRQ_TC5];
+ break;
+ case 6:
+ tdev->interrupt = dec_interrupt[DEC_IRQ_TC6];
+ break;
+ default:
+ tdev->interrupt = -1;
+ break;
+ }
+}
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index bbbb8d7cb89b..1bf2c8448912 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -14,8 +14,6 @@ binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
-obj-$(CONFIG_APM) += apm.o
-
obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
deleted file mode 100644
index ba16d07588cb..000000000000
--- a/arch/mips/kernel/apm.c
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * bios-less APM driver for MIPS Linux
- * Jamey Hicks <jamey@crl.dec.com>
- * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
- *
- * APM 1.2 Reference:
- * Intel Corporation, Microsoft Corporation. Advanced Power Management
- * (APM) BIOS Interface Specification, Revision 1.2, February 1996.
- *
- * [This document is available from Microsoft at:
- * http://www.microsoft.com/hwdev/busbios/amp_12.htm]
- */
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-#include <linux/capability.h>
-#include <linux/sched.h>
-#include <linux/pm.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/completion.h>
-
-#include <asm/apm.h> /* apm_power_info */
-#include <asm/system.h>
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define APM_MINOR_DEV 134
-
-/*
- * See Documentation/Config.help for the configuration options.
- *
- * Various options can be changed at boot time as follows:
- * (We allow underscores for compatibility with the modules code)
- * apm=on/off enable/disable APM
- */
-
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS 16
-
-struct apm_queue {
- unsigned int event_head;
- unsigned int event_tail;
- apm_event_t events[APM_MAX_EVENTS];
-};
-
-/*
- * The per-file APM data
- */
-struct apm_user {
- struct list_head list;
-
- unsigned int suser: 1;
- unsigned int writer: 1;
- unsigned int reader: 1;
-
- int suspend_result;
- unsigned int suspend_state;
-#define SUSPEND_NONE 0 /* no suspend pending */
-#define SUSPEND_PENDING 1 /* suspend pending read */
-#define SUSPEND_READ 2 /* suspend read, pending ack */
-#define SUSPEND_ACKED 3 /* suspend acked */
-#define SUSPEND_DONE 4 /* suspend completed */
-
- struct apm_queue queue;
-};
-
-/*
- * Local variables
- */
-static int suspends_pending;
-static int apm_disabled;
-static int mips_apm_active;
-
-static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-
-/*
- * This is a list of everyone who has opened /dev/apm_bios
- */
-static DECLARE_RWSEM(user_list_lock);
-static LIST_HEAD(apm_user_list);
-
-/*
- * kapmd info. kapmd provides us a process context to handle
- * "APM" events within - specifically necessary if we're going
- * to be suspending the system.
- */
-static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
-static DECLARE_COMPLETION(kapmd_exit);
-static DEFINE_SPINLOCK(kapmd_queue_lock);
-static struct apm_queue kapmd_queue;
-
-
-static const char driver_version[] = "1.13"; /* no spaces */
-
-
-
-/*
- * Compatibility cruft until the IPAQ people move over to the new
- * interface.
- */
-static void __apm_get_power_status(struct apm_power_info *info)
-{
-}
-
-/*
- * This allows machines to provide their own "apm get power status" function.
- */
-void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
-EXPORT_SYMBOL(apm_get_power_status);
-
-
-/*
- * APM event queue management.
- */
-static inline int queue_empty(struct apm_queue *q)
-{
- return q->event_head == q->event_tail;
-}
-
-static inline apm_event_t queue_get_event(struct apm_queue *q)
-{
- q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
- return q->events[q->event_tail];
-}
-
-static void queue_add_event(struct apm_queue *q, apm_event_t event)
-{
- q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
- if (q->event_head == q->event_tail) {
- static int notified;
-
- if (notified++ == 0)
- printk(KERN_ERR "apm: an event queue overflowed\n");
- q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
- }
- q->events[q->event_head] = event;
-}
-
-static void queue_event_one_user(struct apm_user *as, apm_event_t event)
-{
- if (as->suser && as->writer) {
- switch (event) {
- case APM_SYS_SUSPEND:
- case APM_USER_SUSPEND:
- /*
- * If this user already has a suspend pending,
- * don't queue another one.
- */
- if (as->suspend_state != SUSPEND_NONE)
- return;
-
- as->suspend_state = SUSPEND_PENDING;
- suspends_pending++;
- break;
- }
- }
- queue_add_event(&as->queue, event);
-}
-
-static void queue_event(apm_event_t event, struct apm_user *sender)
-{
- struct apm_user *as;
-
- down_read(&user_list_lock);
- list_for_each_entry(as, &apm_user_list, list) {
- if (as != sender && as->reader)
- queue_event_one_user(as, event);
- }
- up_read(&user_list_lock);
- wake_up_interruptible(&apm_waitqueue);
-}
-
-static void apm_suspend(void)
-{
- struct apm_user *as;
- int err = pm_suspend(PM_SUSPEND_MEM);
-
- /*
- * Anyone on the APM queues will think we're still suspended.
- * Send a message so everyone knows we're now awake again.
- */
- queue_event(APM_NORMAL_RESUME, NULL);
-
- /*
- * Finally, wake up anyone who is sleeping on the suspend.
- */
- down_read(&user_list_lock);
- list_for_each_entry(as, &apm_user_list, list) {
- as->suspend_result = err;
- as->suspend_state = SUSPEND_DONE;
- }
- up_read(&user_list_lock);
-
- wake_up(&apm_suspend_waitqueue);
-}
-
-static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
-{
- struct apm_user *as = fp->private_data;
- apm_event_t event;
- int i = count, ret = 0;
-
- if (count < sizeof(apm_event_t))
- return -EINVAL;
-
- if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
- return -EAGAIN;
-
- wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
-
- while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
- event = queue_get_event(&as->queue);
-
- ret = -EFAULT;
- if (copy_to_user(buf, &event, sizeof(event)))
- break;
-
- if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
- as->suspend_state = SUSPEND_READ;
-
- buf += sizeof(event);
- i -= sizeof(event);
- }
-
- if (i < count)
- ret = count - i;
-
- return ret;
-}
-
-static unsigned int apm_poll(struct file *fp, poll_table * wait)
-{
- struct apm_user *as = fp->private_data;
-
- poll_wait(fp, &apm_waitqueue, wait);
- return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
-}
-
-/*
- * apm_ioctl - handle APM ioctl
- *
- * APM_IOC_SUSPEND
- * This IOCTL is overloaded, and performs two functions. It is used to:
- * - initiate a suspend
- * - acknowledge a suspend read from /dev/apm_bios.
- * Only when everyone who has opened /dev/apm_bios with write permission
- * has acknowledge does the actual suspend happen.
- */
-static int
-apm_ioctl(struct inode * inode, struct file *filp, unsigned int cmd, unsigned long arg)
-{
- struct apm_user *as = filp->private_data;
- unsigned long flags;
- int err = -EINVAL;
-
- if (!as->suser || !as->writer)
- return -EPERM;
-
- switch (cmd) {
- case APM_IOC_SUSPEND:
- as->suspend_result = -EINTR;
-
- if (as->suspend_state == SUSPEND_READ) {
- /*
- * If we read a suspend command from /dev/apm_bios,
- * then the corresponding APM_IOC_SUSPEND ioctl is
- * interpreted as an acknowledge.
- */
- as->suspend_state = SUSPEND_ACKED;
- suspends_pending--;
- } else {
- /*
- * Otherwise it is a request to suspend the system.
- * Queue an event for all readers, and expect an
- * acknowledge from all writers who haven't already
- * acknowledged.
- */
- queue_event(APM_USER_SUSPEND, as);
- }
-
- /*
- * If there are no further acknowledges required, suspend
- * the system.
- */
- if (suspends_pending == 0)
- apm_suspend();
-
- /*
- * Wait for the suspend/resume to complete. If there are
- * pending acknowledges, we wait here for them.
- *
- * Note that we need to ensure that the PM subsystem does
- * not kick us out of the wait when it suspends the threads.
- */
- flags = current->flags;
- current->flags |= PF_NOFREEZE;
-
- /*
- * Note: do not allow a thread which is acking the suspend
- * to escape until the resume is complete.
- */
- if (as->suspend_state == SUSPEND_ACKED)
- wait_event(apm_suspend_waitqueue,
- as->suspend_state == SUSPEND_DONE);
- else
- wait_event_interruptible(apm_suspend_waitqueue,
- as->suspend_state == SUSPEND_DONE);
-
- current->flags = flags;
- err = as->suspend_result;
- as->suspend_state = SUSPEND_NONE;
- break;
- }
-
- return err;
-}
-
-static int apm_release(struct inode * inode, struct file * filp)
-{
- struct apm_user *as = filp->private_data;
- filp->private_data = NULL;
-
- down_write(&user_list_lock);
- list_del(&as->list);
- up_write(&user_list_lock);
-
- /*
- * We are now unhooked from the chain. As far as new
- * events are concerned, we no longer exist. However, we
- * need to balance suspends_pending, which means the
- * possibility of sleeping.
- */
- if (as->suspend_state != SUSPEND_NONE) {
- suspends_pending -= 1;
- if (suspends_pending == 0)
- apm_suspend();
- }
-
- kfree(as);
- return 0;
-}
-
-static int apm_open(struct inode * inode, struct file * filp)
-{
- struct apm_user *as;
-
- as = kzalloc(sizeof(*as), GFP_KERNEL);
- if (as) {
- /*
- * XXX - this is a tiny bit broken, when we consider BSD
- * process accounting. If the device is opened by root, we
- * instantly flag that we used superuser privs. Who knows,
- * we might close the device immediately without doing a
- * privileged operation -- cevans
- */
- as->suser = capable(CAP_SYS_ADMIN);
- as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
- as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
-
- down_write(&user_list_lock);
- list_add(&as->list, &apm_user_list);
- up_write(&user_list_lock);
-
- filp->private_data = as;
- }
-
- return as ? 0 : -ENOMEM;
-}
-
-static struct file_operations apm_bios_fops = {
- .owner = THIS_MODULE,
- .read = apm_read,
- .poll = apm_poll,
- .ioctl = apm_ioctl,
- .open = apm_open,
- .release = apm_release,
-};
-
-static struct miscdevice apm_device = {
- .minor = APM_MINOR_DEV,
- .name = "apm_bios",
- .fops = &apm_bios_fops
-};
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * Arguments, with symbols from linux/apm_bios.h.
- *
- * 0) Linux driver version (this will change if format changes)
- * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2.
- * 2) APM flags from APM Installation Check (0x00):
- * bit 0: APM_16_BIT_SUPPORT
- * bit 1: APM_32_BIT_SUPPORT
- * bit 2: APM_IDLE_SLOWS_CLOCK
- * bit 3: APM_BIOS_DISABLED
- * bit 4: APM_BIOS_DISENGAGED
- * 3) AC line status
- * 0x00: Off-line
- * 0x01: On-line
- * 0x02: On backup power (BIOS >= 1.1 only)
- * 0xff: Unknown
- * 4) Battery status
- * 0x00: High
- * 0x01: Low
- * 0x02: Critical
- * 0x03: Charging
- * 0x04: Selected battery not present (BIOS >= 1.2 only)
- * 0xff: Unknown
- * 5) Battery flag
- * bit 0: High
- * bit 1: Low
- * bit 2: Critical
- * bit 3: Charging
- * bit 7: No system battery
- * 0xff: Unknown
- * 6) Remaining battery life (percentage of charge):
- * 0-100: valid
- * -1: Unknown
- * 7) Remaining battery life (time units):
- * Number of remaining minutes or seconds
- * -1: Unknown
- * 8) min = minutes; sec = seconds
- */
-static int apm_get_info(char *buf, char **start, off_t fpos, int length)
-{
- struct apm_power_info info;
- char *units;
- int ret;
-
- info.ac_line_status = 0xff;
- info.battery_status = 0xff;
- info.battery_flag = 0xff;
- info.battery_life = -1;
- info.time = -1;
- info.units = -1;
-
- if (apm_get_power_status)
- apm_get_power_status(&info);
-
- switch (info.units) {
- default: units = "?"; break;
- case 0: units = "min"; break;
- case 1: units = "sec"; break;
- }
-
- ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
- driver_version, APM_32_BIT_SUPPORT,
- info.ac_line_status, info.battery_status,
- info.battery_flag, info.battery_life,
- info.time, units);
-
- return ret;
-}
-#endif
-
-static int kapmd(void *arg)
-{
- daemonize("kapmd");
- current->flags |= PF_NOFREEZE;
-
- do {
- apm_event_t event;
-
- wait_event_interruptible(kapmd_wait,
- !queue_empty(&kapmd_queue) || !mips_apm_active);
-
- if (!mips_apm_active)
- break;
-
- spin_lock_irq(&kapmd_queue_lock);
- event = 0;
- if (!queue_empty(&kapmd_queue))
- event = queue_get_event(&kapmd_queue);
- spin_unlock_irq(&kapmd_queue_lock);
-
- switch (event) {
- case 0:
- break;
-
- case APM_LOW_BATTERY:
- case APM_POWER_STATUS_CHANGE:
- queue_event(event, NULL);
- break;
-
- case APM_USER_SUSPEND:
- case APM_SYS_SUSPEND:
- queue_event(event, NULL);
- if (suspends_pending == 0)
- apm_suspend();
- break;
-
- case APM_CRITICAL_SUSPEND:
- apm_suspend();
- break;
- }
- } while (1);
-
- complete_and_exit(&kapmd_exit, 0);
-}
-
-static int __init apm_init(void)
-{
- int ret;
-
- if (apm_disabled) {
- printk(KERN_NOTICE "apm: disabled on user request.\n");
- return -ENODEV;
- }
-
- mips_apm_active = 1;
-
- ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
- if (ret < 0) {
- mips_apm_active = 0;
- return ret;
- }
-
-#ifdef CONFIG_PROC_FS
- create_proc_info_entry("apm", 0, NULL, apm_get_info);
-#endif
-
- ret = misc_register(&apm_device);
- if (ret != 0) {
- remove_proc_entry("apm", NULL);
-
- mips_apm_active = 0;
- wake_up(&kapmd_wait);
- wait_for_completion(&kapmd_exit);
- }
-
- return ret;
-}
-
-static void __exit apm_exit(void)
-{
- misc_deregister(&apm_device);
- remove_proc_entry("apm", NULL);
-
- mips_apm_active = 0;
- wake_up(&kapmd_wait);
- wait_for_completion(&kapmd_exit);
-}
-
-module_init(apm_init);
-module_exit(apm_exit);
-
-MODULE_AUTHOR("Stephen Rothwell");
-MODULE_DESCRIPTION("Advanced Power Management");
-MODULE_LICENSE("GPL");
-
-#ifndef MODULE
-static int __init apm_setup(char *str)
-{
- while ((str != NULL) && (*str != '\0')) {
- if (strncmp(str, "off", 3) == 0)
- apm_disabled = 1;
- if (strncmp(str, "on", 2) == 0)
- apm_disabled = 0;
- str = strchr(str, ',');
- if (str != NULL)
- str += strspn(str, ", \t");
- }
- return 1;
-}
-
-__setup("apm=", apm_setup);
-#endif
-
-/**
- * apm_queue_event - queue an APM event for kapmd
- * @event: APM event
- *
- * Queue an APM event for kapmd to process and ultimately take the
- * appropriate action. Only a subset of events are handled:
- * %APM_LOW_BATTERY
- * %APM_POWER_STATUS_CHANGE
- * %APM_USER_SUSPEND
- * %APM_SYS_SUSPEND
- * %APM_CRITICAL_SUSPEND
- */
-void apm_queue_event(apm_event_t event)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&kapmd_queue_lock, flags);
- queue_add_event(&kapmd_queue, event);
- spin_unlock_irqrestore(&kapmd_queue_lock, flags);
-
- wake_up_interruptible(&kapmd_wait);
-}
-EXPORT_SYMBOL(apm_queue_event);
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ea7df4b8da33..c0b089d47181 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -249,7 +249,6 @@ void output_sc_defines(void)
offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
offset("#define SC_PC ", struct sigcontext, sc_pc);
- offset("#define SC_STATUS ", struct sigcontext, sc_status);
offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
offset("#define SC_HI1 ", struct sigcontext, sc_hi1);
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index f10b6a19f8bf..0b78fcbf044a 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -21,24 +21,21 @@
#endif
#ifndef CONFIG_PREEMPT
- .macro preempt_stop
- local_irq_disable
- .endm
#define resume_kernel restore_all
+#else
+#define __ret_from_irq ret_from_exception
#endif
.text
.align 5
-FEXPORT(ret_from_irq)
- LONG_S s0, TI_REGS($28)
-#ifdef CONFIG_PREEMPT
-FEXPORT(ret_from_exception)
-#else
- b _ret_from_irq
+#ifndef CONFIG_PREEMPT
FEXPORT(ret_from_exception)
- preempt_stop
+ local_irq_disable # preempt stop
+ b __ret_from_irq
#endif
-FEXPORT(_ret_from_irq)
+FEXPORT(ret_from_irq)
+ LONG_S s0, TI_REGS($28)
+FEXPORT(__ret_from_irq)
LONG_L t0, PT_STATUS(sp) # returning to kernel mode?
andi t0, t0, KU_USER
beqz t0, resume_kernel
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 0b8ce59429a8..fc4dd6c9dd80 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -39,6 +39,7 @@
#include <net/sock.h>
#include <net/scm.h>
+#include <asm/compat-signal.h>
#include <asm/ipc.h>
#include <asm/sim.h>
#include <asm/uaccess.h>
@@ -193,50 +194,6 @@ sysn32_waitid(int which, compat_pid_t pid,
return ret;
}
-struct sysinfo32 {
- s32 uptime;
- u32 loads[3];
- u32 totalram;
- u32 freeram;
- u32 sharedram;
- u32 bufferram;
- u32 totalswap;
- u32 freeswap;
- u16 procs;
- u32 totalhigh;
- u32 freehigh;
- u32 mem_unit;
- char _f[8];
-};
-
-asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
-{
- struct sysinfo s;
- int ret, err;
- mm_segment_t old_fs = get_fs ();
-
- set_fs (KERNEL_DS);
- ret = sys_sysinfo((struct sysinfo __user *)&s);
- set_fs (old_fs);
- err = put_user (s.uptime, &info->uptime);
- err |= __put_user (s.loads[0], &info->loads[0]);
- err |= __put_user (s.loads[1], &info->loads[1]);
- err |= __put_user (s.loads[2], &info->loads[2]);
- err |= __put_user (s.totalram, &info->totalram);
- err |= __put_user (s.freeram, &info->freeram);
- err |= __put_user (s.sharedram, &info->sharedram);
- err |= __put_user (s.bufferram, &info->bufferram);
- err |= __put_user (s.totalswap, &info->totalswap);
- err |= __put_user (s.freeswap, &info->freeswap);
- err |= __put_user (s.procs, &info->procs);
- err |= __put_user (s.totalhigh, &info->totalhigh);
- err |= __put_user (s.freehigh, &info->freehigh);
- err |= __put_user (s.mem_unit, &info->mem_unit);
- if (err)
- return -EFAULT;
- return ret;
-}
-
#define RLIM_INFINITY32 0x7fffffff
#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
@@ -780,3 +737,49 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
return do_fork(clone_flags, newsp, &regs, 0,
parent_tidptr, child_tidptr);
}
+
+/*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+ * part of the user space epoll_pwait(2).
+ */
+asmlinkage long compat_sys_epoll_pwait(int epfd,
+ struct epoll_event __user *events, int maxevents, int timeout,
+ const compat_sigset_t __user *sigmask, size_t sigsetsize)
+{
+ int error;
+ sigset_t ksigmask, sigsaved;
+
+ /*
+ * If the caller wants a certain signal mask to be set during the wait,
+ * we apply it here.
+ */
+ if (sigmask) {
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (!access_ok(VERIFY_READ, sigmask, sizeof(ksigmask)))
+ return -EFAULT;
+ if (__copy_conv_sigset_from_user(&ksigmask, sigmask))
+ return -EFAULT;
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ error = sys_epoll_wait(epfd, events, maxevents, timeout);
+
+ /*
+ * If we changed the signal mask, we need to restore the original one.
+ * In case we've got a signal while waiting, we do not restore the
+ * signal mask yet, and we allow do_signal() to deliver the signal on
+ * the way back to userspace, before the signal mask is restored.
+ */
+ if (sigmask) {
+ if (error == -EINTR) {
+ memcpy(&current->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ } else
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+ }
+
+ return error;
+}
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index a32f6797353a..ba01800b6018 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -3,9 +3,11 @@
* Copyright (C) 2005 Mips Technologies, Inc
*/
+#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/cpumask.h>
+#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/security.h>
@@ -453,3 +455,20 @@ void mt_cflush_release(void)
#endif /* CONFIG_MIPS_MT_SMTC */
/* FILL IN VSMP and AP/SP VERSIONS HERE */
}
+
+struct class *mt_class;
+
+static int __init mt_init(void)
+{
+ struct class *mtc;
+
+ mtc = class_create(THIS_MODULE, "mt");
+ if (IS_ERR(mtc))
+ return PTR_ERR(mtc);
+
+ mt_class = mtc;
+
+ return 0;
+}
+
+subsys_initcall(mt_init);
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 8610f4a925e9..d92c48e0d7a6 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -17,6 +17,7 @@
*
*/
+#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
@@ -34,6 +35,7 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <asm/mipsmtregs.h>
+#include <asm/mips_mt.h>
#include <asm/cacheflush.h>
#include <asm/atomic.h>
#include <asm/cpu.h>
@@ -476,7 +478,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
return rtlx_write(minor, (void *)buffer, count, 1);
}
-static struct file_operations rtlx_fops = {
+static const struct file_operations rtlx_fops = {
.owner = THIS_MODULE,
.open = file_open,
.release = file_release,
@@ -498,7 +500,8 @@ static char register_chrdev_failed[] __initdata =
static int rtlx_module_init(void)
{
- int i;
+ struct device *dev;
+ int i, err;
major = register_chrdev(0, module_name, &rtlx_fops);
if (major < 0) {
@@ -511,6 +514,13 @@ static int rtlx_module_init(void)
init_waitqueue_head(&channel_wqs[i].rt_queue);
init_waitqueue_head(&channel_wqs[i].lx_queue);
channel_wqs[i].in_open = 0;
+
+ dev = device_create(mt_class, NULL, MKDEV(major, i),
+ "%s%d", module_name, i);
+ if (IS_ERR(dev)) {
+ err = PTR_ERR(dev);
+ goto out_chrdev;
+ }
}
/* set up notifiers */
@@ -525,10 +535,21 @@ static int rtlx_module_init(void)
setup_irq(rtlx_irq_num, &rtlx_irq);
return 0;
+
+out_chrdev:
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ device_destroy(mt_class, MKDEV(major, i));
+
+ return err;
}
static void __exit rtlx_module_exit(void)
{
+ int i;
+
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ device_destroy(mt_class, MKDEV(major, i));
+
unregister_chrdev(major, module_name);
}
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index e569b846e9a3..10e9a18630aa 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -470,4 +470,4 @@ sys_call_table:
PTR sys_get_robust_list
PTR sys_kexec_load /* 5270 */
PTR sys_getcpu
- PTR sys_epoll_pwait
+ PTR compat_sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 39add2341aa2..2ceda4644a4d 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -217,7 +217,7 @@ EXPORT(sysn32_call_table)
PTR sys32_gettimeofday
PTR compat_sys_getrlimit /* 6095 */
PTR compat_sys_getrusage
- PTR sys32_sysinfo
+ PTR compat_sys_sysinfo
PTR compat_sys_times
PTR sys32_ptrace
PTR sys_getuid /* 6100 */
@@ -396,4 +396,4 @@ EXPORT(sysn32_call_table)
PTR compat_sys_get_robust_list
PTR compat_sys_kexec_load
PTR sys_getcpu
- PTR sys_epoll_pwait
+ PTR compat_sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index c58b8e0105ea..c5f590ca99b0 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -321,7 +321,7 @@ sys_call_table:
PTR sys_ni_syscall /* sys_vm86 */
PTR compat_sys_wait4
PTR sys_swapoff /* 4115 */
- PTR sys32_sysinfo
+ PTR compat_sys_sysinfo
PTR sys32_ipc
PTR sys_fsync
PTR sys32_sigreturn
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index d2e01e7167b8..394540fad769 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -452,7 +452,7 @@ static void __init arch_mem_init(char **cmdline_p)
print_memory_map();
strlcpy(command_line, arcs_cmdline, sizeof(command_line));
- strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+ strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index b1f09d54ebe6..fdbdbdc65b54 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -8,169 +8,27 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
+#ifndef __SIGNAL_COMMON_H
+#define __SIGNAL_COMMON_H
-static inline int
-setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
-{
- int err = 0;
+/* #define DEBUG_SIG */
- err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+#ifdef DEBUG_SIG
+# define DEBUGP(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#else
+# define DEBUGP(fmt, args...)
+#endif
-#define save_gp_reg(i) do { \
- err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
-} while(0)
- __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
- save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
- save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
- save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
- save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
- save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
- save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
- save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
- save_gp_reg(31);
-#undef save_gp_reg
-
- err |= __put_user(regs->hi, &sc->sc_mdhi);
- err |= __put_user(regs->lo, &sc->sc_mdlo);
- if (cpu_has_dsp) {
- err |= __put_user(mfhi1(), &sc->sc_hi1);
- err |= __put_user(mflo1(), &sc->sc_lo1);
- err |= __put_user(mfhi2(), &sc->sc_hi2);
- err |= __put_user(mflo2(), &sc->sc_lo2);
- err |= __put_user(mfhi3(), &sc->sc_hi3);
- err |= __put_user(mflo3(), &sc->sc_lo3);
- err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
- }
-
- err |= __put_user(!!used_math(), &sc->sc_used_math);
-
- if (!used_math())
- goto out;
-
- /*
- * Save FPU state to signal context. Signal handler will "inherit"
- * current FPU state.
- */
- preempt_disable();
-
- if (!is_fpu_owner()) {
- own_fpu();
- restore_fp(current);
- }
- err |= save_fp_context(sc);
-
- preempt_enable();
-
-out:
- return err;
-}
-
-static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
-{
- unsigned int used_math;
- unsigned long treg;
- int err = 0;
-
- /* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
- err |= __get_user(regs->cp0_epc, &sc->sc_pc);
- err |= __get_user(regs->hi, &sc->sc_mdhi);
- err |= __get_user(regs->lo, &sc->sc_mdlo);
- if (cpu_has_dsp) {
- err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
- err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
- err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
- err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
- err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
- err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
- err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
- }
-
-#define restore_gp_reg(i) do { \
- err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
-} while(0)
- restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
- restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
- restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
- restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
- restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
- restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
- restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
- restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
- restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
- restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
- restore_gp_reg(31);
-#undef restore_gp_reg
-
- err |= __get_user(used_math, &sc->sc_used_math);
- conditional_used_math(used_math);
-
- preempt_disable();
-
- if (used_math()) {
- /* restore fpu context if we have used it before */
- own_fpu();
- err |= restore_fp_context(sc);
- } else {
- /* signal handler may have used FPU. Give it up. */
- lose_fpu();
- }
-
- preempt_enable();
-
- return err;
-}
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/*
* Determine which stack to use..
*/
-static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
- unsigned long sp;
-
- /* Default to using normal stack */
- sp = regs->regs[29];
-
- /*
- * FPU emulator may have it's own trampoline active just
- * above the user stack, 16-bytes before the next lowest
- * 16 byte boundary. Try to avoid trashing it.
- */
- sp -= 32;
-
- /* This is the X/Open sanctioned signal stack switching. */
- if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
- sp = current->sas_ss_sp + current->sas_ss_size;
-
- return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
-}
-
-static inline int install_sigtramp(unsigned int __user *tramp,
- unsigned int syscall)
-{
- int err;
-
- /*
- * Set up the return code ...
- *
- * li v0, __NR__foo_sigreturn
- * syscall
- */
-
- err = __put_user(0x24020000 + syscall, tramp + 0);
- err |= __put_user(0x0000000c , tramp + 1);
- if (ICACHE_REFILLS_WORKAROUND_WAR) {
- err |= __put_user(0, tramp + 2);
- err |= __put_user(0, tramp + 3);
- err |= __put_user(0, tramp + 4);
- err |= __put_user(0, tramp + 5);
- err |= __put_user(0, tramp + 6);
- err |= __put_user(0, tramp + 7);
- }
- flush_cache_sigtramp((unsigned long) tramp);
+extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size);
+/*
+ * install trampoline code to get back from the sig handler
+ */
+extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall);
- return err;
-}
+#endif /* __SIGNAL_COMMON_H */
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 9a44053cd9f1..b2e9ab1bb101 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -34,18 +34,192 @@
#include "signal-common.h"
-#define DEBUG_SIG 0
+/*
+ * Horribly complicated - with the bloody RM9000 workarounds enabled
+ * the signal trampolines is moving to the end of the structure so we can
+ * increase the alignment without breaking software compatibility.
+ */
+#if ICACHE_REFILLS_WORKAROUND_WAR == 0
+
+struct sigframe {
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_code[2]; /* signal trampoline */
+ struct sigcontext sf_sc;
+ sigset_t sf_mask;
+};
+
+struct rt_sigframe {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_code[2]; /* signal trampoline */
+ struct siginfo rs_info;
+ struct ucontext rs_uc;
+};
+
+#else
+
+struct sigframe {
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_pad[2];
+ struct sigcontext sf_sc; /* hw context */
+ sigset_t sf_mask;
+ u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
+};
+
+struct rt_sigframe {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_pad[2];
+ struct siginfo rs_info;
+ struct ucontext rs_uc;
+ u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
+};
+
+#endif
+
+/*
+ * Helper routines
+ */
+int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+ int err = 0;
+ int i;
+
+ err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+
+ err |= __put_user(0, &sc->sc_regs[0]);
+ for (i = 1; i < 32; i++)
+ err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
+
+ err |= __put_user(regs->hi, &sc->sc_mdhi);
+ err |= __put_user(regs->lo, &sc->sc_mdlo);
+ if (cpu_has_dsp) {
+ err |= __put_user(mfhi1(), &sc->sc_hi1);
+ err |= __put_user(mflo1(), &sc->sc_lo1);
+ err |= __put_user(mfhi2(), &sc->sc_hi2);
+ err |= __put_user(mflo2(), &sc->sc_lo2);
+ err |= __put_user(mfhi3(), &sc->sc_hi3);
+ err |= __put_user(mflo3(), &sc->sc_lo3);
+ err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+ }
+
+ err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+ if (used_math()) {
+ /*
+ * Save FPU state to signal context. Signal handler
+ * will "inherit" current FPU state.
+ */
+ preempt_disable();
+
+ if (!is_fpu_owner()) {
+ own_fpu();
+ restore_fp(current);
+ }
+ err |= save_fp_context(sc);
+
+ preempt_enable();
+ }
+ return err;
+}
+
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+ unsigned int used_math;
+ unsigned long treg;
+ int err = 0;
+ int i;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __get_user(regs->hi, &sc->sc_mdhi);
+ err |= __get_user(regs->lo, &sc->sc_mdlo);
+ if (cpu_has_dsp) {
+ err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+ err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+ err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+ err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+ err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+ err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+ err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+ }
+
+ for (i = 1; i < 32; i++)
+ err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
+
+ err |= __get_user(used_math, &sc->sc_used_math);
+ conditional_used_math(used_math);
+
+ preempt_disable();
+
+ if (used_math()) {
+ /* restore fpu context if we have used it before */
+ own_fpu();
+ err |= restore_fp_context(sc);
+ } else {
+ /* signal handler may have used FPU. Give it up. */
+ lose_fpu();
+ }
+
+ preempt_enable();
+
+ return err;
+}
+
+void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size)
+{
+ unsigned long sp;
+
+ /* Default to using normal stack */
+ sp = regs->regs[29];
+
+ /*
+ * FPU emulator may have it's own trampoline active just
+ * above the user stack, 16-bytes before the next lowest
+ * 16 byte boundary. Try to avoid trashing it.
+ */
+ sp -= 32;
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
+}
+
+int install_sigtramp(unsigned int __user *tramp, unsigned int syscall)
+{
+ int err;
+
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR__foo_sigreturn
+ * syscall
+ */
+
+ err = __put_user(0x24020000 + syscall, tramp + 0);
+ err |= __put_user(0x0000000c , tramp + 1);
+ if (ICACHE_REFILLS_WORKAROUND_WAR) {
+ err |= __put_user(0, tramp + 2);
+ err |= __put_user(0, tramp + 3);
+ err |= __put_user(0, tramp + 4);
+ err |= __put_user(0, tramp + 5);
+ err |= __put_user(0, tramp + 6);
+ err |= __put_user(0, tramp + 7);
+ }
+ flush_cache_sigtramp((unsigned long) tramp);
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+ return err;
+}
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
#ifdef CONFIG_TRAD_SIGNALS
-save_static_function(sys_sigsuspend);
-__attribute_used__ noinline static int
-_sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
sigset_t newset;
sigset_t __user *uset;
@@ -68,9 +242,7 @@ _sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
}
#endif
-save_static_function(sys_rt_sigsuspend);
-__attribute_used__ noinline static int
-_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
sigset_t newset;
sigset_t __user *unewset;
@@ -148,45 +320,8 @@ asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
return do_sigaltstack(uss, uoss, usp);
}
-/*
- * Horribly complicated - with the bloody RM9000 workarounds enabled
- * the signal trampolines is moving to the end of the structure so we can
- * increase the alignment without breaking software compatibility.
- */
#ifdef CONFIG_TRAD_SIGNALS
-struct sigframe {
- u32 sf_ass[4]; /* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 sf_pad[2];
-#else
- u32 sf_code[2]; /* signal trampoline */
-#endif
- struct sigcontext sf_sc;
- sigset_t sf_mask;
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
-#endif
-};
-#endif
-
-struct rt_sigframe {
- u32 rs_ass[4]; /* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 rs_pad[2];
-#else
- u32 rs_code[2]; /* signal trampoline */
-#endif
- struct siginfo rs_info;
- struct ucontext rs_uc;
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
-#endif
-};
-
-#ifdef CONFIG_TRAD_SIGNALS
-save_static_function(sys_sigreturn);
-__attribute_used__ noinline static void
-_sys_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs)
{
struct sigframe __user *frame;
sigset_t blocked;
@@ -221,9 +356,7 @@ badframe:
}
#endif /* CONFIG_TRAD_SIGNALS */
-save_static_function(sys_rt_sigreturn);
-__attribute_used__ noinline static void
-_sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
{
struct rt_sigframe __user *frame;
sigset_t set;
@@ -275,7 +408,7 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv;
- install_sigtramp(frame->sf_code, __NR_sigreturn);
+ err |= install_sigtramp(frame->sf_code, __NR_sigreturn);
err |= setup_sigcontext(regs, &frame->sf_sc);
err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
@@ -299,11 +432,9 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[31] = (unsigned long) frame->sf_code;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
- frame, regs->cp0_epc, frame->regs[31]);
-#endif
+ frame, regs->cp0_epc, regs->regs[31]);
return 0;
give_sigsegv:
@@ -322,7 +453,7 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv;
- install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
+ err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
/* Create siginfo. */
err |= copy_siginfo_to_user(&frame->rs_info, info);
@@ -359,11 +490,10 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[31] = (unsigned long) frame->rs_code;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]);
-#endif
+
return 0;
give_sigsegv:
@@ -371,7 +501,7 @@ give_sigsegv:
return -EFAULT;
}
-static inline int handle_signal(unsigned long sig, siginfo_t *info,
+static int handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
{
int ret;
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index c86a5ddff050..c28cb21514c8 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -8,6 +8,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/cache.h>
+#include <linux/compat.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -24,6 +25,7 @@
#include <asm/abi.h>
#include <asm/asm.h>
+#include <asm/compat-signal.h>
#include <linux/bitops.h>
#include <asm/cacheflush.h>
#include <asm/sim.h>
@@ -33,6 +35,8 @@
#include <asm/fpu.h>
#include <asm/war.h>
+#include "signal-common.h"
+
#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
typedef struct compat_siginfo {
@@ -102,10 +106,6 @@ typedef struct compat_siginfo {
#define __NR_O32_rt_sigreturn 4193
#define __NR_O32_restart_syscall 4253
-#define DEBUG_SIG 0
-
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
/* 32-bit compatibility types */
#define _NSIG_BPW32 32
@@ -139,6 +139,143 @@ struct ucontext32 {
sigset_t32 uc_sigmask; /* mask last for extensibility */
};
+/*
+ * Horribly complicated - with the bloody RM9000 workarounds enabled
+ * the signal trampolines is moving to the end of the structure so we can
+ * increase the alignment without breaking software compatibility.
+ */
+#if ICACHE_REFILLS_WORKAROUND_WAR == 0
+
+struct sigframe32 {
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_code[2]; /* signal trampoline */
+ struct sigcontext32 sf_sc;
+ sigset_t sf_mask;
+};
+
+struct rt_sigframe32 {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_code[2]; /* signal trampoline */
+ compat_siginfo_t rs_info;
+ struct ucontext32 rs_uc;
+};
+
+#else /* ICACHE_REFILLS_WORKAROUND_WAR */
+
+struct sigframe32 {
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_pad[2];
+ struct sigcontext32 sf_sc; /* hw context */
+ sigset_t sf_mask;
+ u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
+};
+
+struct rt_sigframe32 {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_pad[2];
+ compat_siginfo_t rs_info;
+ struct ucontext32 rs_uc;
+ u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
+};
+
+#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
+
+/*
+ * sigcontext handlers
+ */
+static int setup_sigcontext32(struct pt_regs *regs,
+ struct sigcontext32 __user *sc)
+{
+ int err = 0;
+ int i;
+
+ err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+
+ err |= __put_user(0, &sc->sc_regs[0]);
+ for (i = 1; i < 32; i++)
+ err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
+
+ err |= __put_user(regs->hi, &sc->sc_mdhi);
+ err |= __put_user(regs->lo, &sc->sc_mdlo);
+ if (cpu_has_dsp) {
+ err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+ err |= __put_user(mfhi1(), &sc->sc_hi1);
+ err |= __put_user(mflo1(), &sc->sc_lo1);
+ err |= __put_user(mfhi2(), &sc->sc_hi2);
+ err |= __put_user(mflo2(), &sc->sc_lo2);
+ err |= __put_user(mfhi3(), &sc->sc_hi3);
+ err |= __put_user(mflo3(), &sc->sc_lo3);
+ }
+
+ err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+ if (used_math()) {
+ /*
+ * Save FPU state to signal context. Signal handler
+ * will "inherit" current FPU state.
+ */
+ preempt_disable();
+
+ if (!is_fpu_owner()) {
+ own_fpu();
+ restore_fp(current);
+ }
+ err |= save_fp_context32(sc);
+
+ preempt_enable();
+ }
+ return err;
+}
+
+static int restore_sigcontext32(struct pt_regs *regs,
+ struct sigcontext32 __user *sc)
+{
+ u32 used_math;
+ int err = 0;
+ s32 treg;
+ int i;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __get_user(regs->hi, &sc->sc_mdhi);
+ err |= __get_user(regs->lo, &sc->sc_mdlo);
+ if (cpu_has_dsp) {
+ err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+ err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+ err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+ err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+ err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+ err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+ err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+ }
+
+ for (i = 1; i < 32; i++)
+ err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
+
+ err |= __get_user(used_math, &sc->sc_used_math);
+ conditional_used_math(used_math);
+
+ preempt_disable();
+
+ if (used_math()) {
+ /* restore fpu context if we have used it before */
+ own_fpu();
+ err |= restore_fp_context32(sc);
+ } else {
+ /* signal handler may have used FPU. Give it up. */
+ lose_fpu();
+ }
+
+ preempt_enable();
+
+ return err;
+}
+
+/*
+ *
+ */
extern void __put_sigset_unknown_nsig(void);
extern void __get_sigset_unknown_nsig(void);
@@ -191,9 +328,7 @@ static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
* Atomically swap in the new signal mask, and wait for a signal.
*/
-save_static_function(sys32_sigsuspend);
-__attribute_used__ noinline static int
-_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
compat_sigset_t __user *uset;
sigset_t newset;
@@ -215,9 +350,7 @@ _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
return -ERESTARTNOHAND;
}
-save_static_function(sys32_rt_sigsuspend);
-__attribute_used__ noinline static int
-_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
compat_sigset_t __user *uset;
sigset_t newset;
@@ -326,91 +459,6 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
return ret;
}
-static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc)
-{
- u32 used_math;
- int err = 0;
- s32 treg;
-
- /* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
- err |= __get_user(regs->cp0_epc, &sc->sc_pc);
- err |= __get_user(regs->hi, &sc->sc_mdhi);
- err |= __get_user(regs->lo, &sc->sc_mdlo);
- if (cpu_has_dsp) {
- err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
- err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
- err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
- err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
- err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
- err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
- err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
- }
-
-#define restore_gp_reg(i) do { \
- err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
-} while(0)
- restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
- restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
- restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
- restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
- restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
- restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
- restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
- restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
- restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
- restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
- restore_gp_reg(31);
-#undef restore_gp_reg
-
- err |= __get_user(used_math, &sc->sc_used_math);
- conditional_used_math(used_math);
-
- preempt_disable();
-
- if (used_math()) {
- /* restore fpu context if we have used it before */
- own_fpu();
- err |= restore_fp_context32(sc);
- } else {
- /* signal handler may have used FPU. Give it up. */
- lose_fpu();
- }
-
- preempt_enable();
-
- return err;
-}
-
-struct sigframe {
- u32 sf_ass[4]; /* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 sf_pad[2];
-#else
- u32 sf_code[2]; /* signal trampoline */
-#endif
- struct sigcontext32 sf_sc;
- sigset_t sf_mask;
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
-#endif
-};
-
-struct rt_sigframe32 {
- u32 rs_ass[4]; /* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 rs_pad[2];
-#else
- u32 rs_code[2]; /* signal trampoline */
-#endif
- compat_siginfo_t rs_info;
- struct ucontext32 rs_uc;
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
-#endif
-};
-
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
{
int err;
@@ -463,17 +511,15 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
return err;
}
-save_static_function(sys32_sigreturn);
-__attribute_used__ noinline static void
-_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
{
- struct sigframe __user *frame;
+ struct sigframe32 __user *frame;
sigset_t blocked;
- frame = (struct sigframe __user *) regs.regs[29];
+ frame = (struct sigframe32 __user *) regs.regs[29];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
- if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
+ if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
@@ -499,9 +545,7 @@ badframe:
force_sig(SIGSEGV, current);
}
-save_static_function(sys32_rt_sigreturn);
-__attribute_used__ noinline static void
-_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
{
struct rt_sigframe32 __user *frame;
mm_segment_t old_fs;
@@ -512,7 +556,7 @@ _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
frame = (struct rt_sigframe32 __user *) regs.regs[29];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
- if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+ if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
@@ -554,111 +598,21 @@ badframe:
force_sig(SIGSEGV, current);
}
-static inline int setup_sigcontext32(struct pt_regs *regs,
- struct sigcontext32 __user *sc)
-{
- int err = 0;
-
- err |= __put_user(regs->cp0_epc, &sc->sc_pc);
- err |= __put_user(regs->cp0_status, &sc->sc_status);
-
-#define save_gp_reg(i) { \
- err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
-} while(0)
- __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
- save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
- save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
- save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
- save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
- save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
- save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
- save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
- save_gp_reg(31);
-#undef save_gp_reg
-
- err |= __put_user(regs->hi, &sc->sc_mdhi);
- err |= __put_user(regs->lo, &sc->sc_mdlo);
- if (cpu_has_dsp) {
- err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
- err |= __put_user(mfhi1(), &sc->sc_hi1);
- err |= __put_user(mflo1(), &sc->sc_lo1);
- err |= __put_user(mfhi2(), &sc->sc_hi2);
- err |= __put_user(mflo2(), &sc->sc_lo2);
- err |= __put_user(mfhi3(), &sc->sc_hi3);
- err |= __put_user(mflo3(), &sc->sc_lo3);
- }
-
- err |= __put_user(!!used_math(), &sc->sc_used_math);
-
- if (!used_math())
- goto out;
-
- /*
- * Save FPU state to signal context. Signal handler will "inherit"
- * current FPU state.
- */
- preempt_disable();
-
- if (!is_fpu_owner()) {
- own_fpu();
- restore_fp(current);
- }
- err |= save_fp_context32(sc);
-
- preempt_enable();
-
-out:
- return err;
-}
-
-/*
- * Determine which stack to use..
- */
-static inline void __user *get_sigframe(struct k_sigaction *ka,
- struct pt_regs *regs,
- size_t frame_size)
-{
- unsigned long sp;
-
- /* Default to using normal stack */
- sp = regs->regs[29];
-
- /*
- * FPU emulator may have it's own trampoline active just
- * above the user stack, 16-bytes before the next lowest
- * 16 byte boundary. Try to avoid trashing it.
- */
- sp -= 32;
-
- /* This is the X/Open sanctioned signal stack switching. */
- if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
- sp = current->sas_ss_sp + current->sas_ss_size;
-
- return (void __user *)((sp - frame_size) & ALMASK);
-}
-
int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set)
{
- struct sigframe __user *frame;
+ struct sigframe32 __user *frame;
int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv;
- /*
- * Set up the return code ...
- *
- * li v0, __NR_O32_sigreturn
- * syscall
- */
- err |= __put_user(0x24020000 + __NR_O32_sigreturn, frame->sf_code + 0);
- err |= __put_user(0x0000000c , frame->sf_code + 1);
- flush_cache_sigtramp((unsigned long) frame->sf_code);
+ err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
err |= setup_sigcontext32(regs, &frame->sf_sc);
- err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
+ err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
+
if (err)
goto give_sigsegv;
@@ -679,11 +633,10 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[31] = (unsigned long) frame->sf_code;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
- frame, regs->cp0_epc, frame->sf_code);
-#endif
+ frame, regs->cp0_epc, regs->regs[31]);
+
return 0;
give_sigsegv:
@@ -702,17 +655,7 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv;
- /* Set up to return from userspace. If provided, use a stub already
- in userspace. */
- /*
- * Set up the return code ...
- *
- * li v0, __NR_O32_rt_sigreturn
- * syscall
- */
- err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0);
- err |= __put_user(0x0000000c , frame->rs_code + 1);
- flush_cache_sigtramp((unsigned long) frame->rs_code);
+ err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
err |= copy_siginfo_to_user32(&frame->rs_info, info);
@@ -728,7 +671,7 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
err |= __put_user(current->sas_ss_size,
&frame->rs_uc.uc_stack.ss_size);
err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
- err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+ err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
if (err)
goto give_sigsegv;
@@ -750,11 +693,10 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[31] = (unsigned long) frame->rs_code;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
- frame, regs->cp0_epc, frame->rs_code);
-#endif
+ frame, regs->cp0_epc, regs->regs[31]);
+
return 0;
give_sigsegv:
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index b28646b3ceae..7ca2a078841f 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -31,6 +31,7 @@
#include <asm/asm.h>
#include <asm/cacheflush.h>
+#include <asm/compat-signal.h>
#include <asm/sim.h>
#include <asm/uaccess.h>
#include <asm/ucontext.h>
@@ -47,9 +48,9 @@
#define __NR_N32_rt_sigreturn 6211
#define __NR_N32_restart_syscall 6214
-#define DEBUG_SIG 0
+extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
+extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* IRIX compatible stack_t */
typedef struct sigaltstack32 {
@@ -63,28 +64,33 @@ struct ucontextn32 {
s32 uc_link;
stack32_t uc_stack;
struct sigcontext uc_mcontext;
- sigset_t uc_sigmask; /* mask last for extensibility */
+ compat_sigset_t uc_sigmask; /* mask last for extensibility */
};
+#if ICACHE_REFILLS_WORKAROUND_WAR == 0
+
struct rt_sigframe_n32 {
u32 rs_ass[4]; /* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
- u32 rs_pad[2];
-#else
u32 rs_code[2]; /* signal trampoline */
-#endif
struct siginfo rs_info;
struct ucontextn32 rs_uc;
-#if ICACHE_REFILLS_WORKAROUND_WAR
+};
+
+#else /* ICACHE_REFILLS_WORKAROUND_WAR */
+
+struct rt_sigframe_n32 {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_pad[2];
+ struct siginfo rs_info;
+ struct ucontextn32 rs_uc;
u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
-#endif
};
+#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
+
extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat);
-save_static_function(sysn32_rt_sigsuspend);
-__attribute_used__ noinline static int
-_sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
compat_sigset_t __user *unewset;
compat_sigset_t uset;
@@ -114,9 +120,7 @@ _sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
return -ERESTARTNOHAND;
}
-save_static_function(sysn32_rt_sigreturn);
-__attribute_used__ noinline static void
-_sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
{
struct rt_sigframe_n32 __user *frame;
sigset_t set;
@@ -126,7 +130,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
frame = (struct rt_sigframe_n32 __user *) regs.regs[29];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
- if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+ if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
@@ -192,7 +196,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
err |= __put_user(current->sas_ss_size,
&frame->rs_uc.uc_stack.ss_size);
err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
- err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+ err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
if (err)
goto give_sigsegv;
@@ -214,11 +218,10 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
regs->regs[31] = (unsigned long) frame->rs_code;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]);
-#endif
+
return 0;
give_sigsegv:
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 8aa544f73a5e..e5e56bd498db 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -307,7 +307,7 @@ static unsigned int __init calibrate_hpt(void)
struct clocksource clocksource_mips = {
.name = "MIPS",
.mask = 0xffffffff,
- .is_continuous = 1,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static void __init init_mips_clocksource(void)
@@ -455,8 +455,3 @@ EXPORT_SYMBOL(rtc_lock);
EXPORT_SYMBOL(to_tm);
EXPORT_SYMBOL(rtc_mips_set_time);
EXPORT_SYMBOL(rtc_mips_get_time);
-
-unsigned long long sched_clock(void)
-{
- return (unsigned long long)jiffies*(1000000000/HZ);
-}
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index cecff24cc972..c76b793310c2 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -113,10 +113,12 @@ SECTIONS
references from .rodata */
.exit.text : { *(.exit.text) }
.exit.data : { *(.exit.data) }
+#if defined(CONFIG_BLK_DEV_INITRD)
. = ALIGN(_PAGE_SIZE);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
+#endif
. = ALIGN(32);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 459624969c99..9aca871a307f 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -29,6 +29,7 @@
*/
#include <linux/kernel.h>
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
@@ -48,6 +49,7 @@
#include <asm/cacheflush.h>
#include <asm/atomic.h>
#include <asm/cpu.h>
+#include <asm/mips_mt.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/vpe.h>
@@ -64,6 +66,7 @@ typedef void *vpe_handle;
static char module_name[] = "vpe";
static int major;
+static const int minor = 1; /* fixed for now */
#ifdef CONFIG_MIPS_APSP_KSPD
static struct kspd_notifications kspd_events;
@@ -1205,7 +1208,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
return ret;
}
-static struct file_operations vpe_fops = {
+static const struct file_operations vpe_fops = {
.owner = THIS_MODULE,
.open = vpe_open,
.release = vpe_release,
@@ -1365,12 +1368,15 @@ static void kspd_sp_exit( int sp_id)
}
#endif
+static struct device *vpe_dev;
+
static int __init vpe_module_init(void)
{
struct vpe *v = NULL;
+ struct device *dev;
struct tc *t;
unsigned long val;
- int i;
+ int i, err;
if (!cpu_has_mipsmt) {
printk("VPE loader: not a MIPS MT capable processor\n");
@@ -1383,6 +1389,14 @@ static int __init vpe_module_init(void)
return major;
}
+ dev = device_create(mt_class, NULL, MKDEV(major, minor),
+ "tc%d", minor);
+ if (IS_ERR(dev)) {
+ err = PTR_ERR(dev);
+ goto out_chrdev;
+ }
+ vpe_dev = dev;
+
dmt();
dvpe();
@@ -1478,6 +1492,11 @@ static int __init vpe_module_init(void)
kspd_events.kspd_sp_exit = kspd_sp_exit;
#endif
return 0;
+
+out_chrdev:
+ unregister_chrdev(major, module_name);
+
+ return err;
}
static void __exit vpe_module_exit(void)
@@ -1490,6 +1509,7 @@ static void __exit vpe_module_exit(void)
}
}
+ device_destroy(mt_class, MKDEV(major, minor));
unregister_chrdev(major, module_name);
}
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 12878359f2c8..699ab1886ceb 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -302,42 +302,129 @@ extern int lasat_boot_to_service;
#ifdef CONFIG_SYSCTL
static ctl_table lasat_table[] = {
- {LASAT_CPU_HZ, "cpu-hz", &lasat_board_info.li_cpu_hz, sizeof(int),
- 0444, NULL, &proc_dointvec, &sysctl_intvec},
- {LASAT_BUS_HZ, "bus-hz", &lasat_board_info.li_bus_hz, sizeof(int),
- 0444, NULL, &proc_dointvec, &sysctl_intvec},
- {LASAT_MODEL, "bmid", &lasat_board_info.li_bmid, sizeof(int),
- 0444, NULL, &proc_dointvec, &sysctl_intvec},
- {LASAT_PRID, "prid", &lasat_board_info.li_prid, sizeof(int),
- 0644, NULL, &proc_lasat_eeprom_value, &sysctl_lasat_eeprom_value},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "cpu-hz",
+ .data = &lasat_board_info.li_cpu_hz,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ .strategy = &sysctl_intvec
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "bus-hz",
+ .data = &lasat_board_info.li_bus_hz,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ .strategy = &sysctl_intvec
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "bmid",
+ .data = &lasat_board_info.li_bmid,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ .strategy = &sysctl_intvec
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "prid",
+ .data = &lasat_board_info.li_prid,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_lasat_eeprom_value,
+ .strategy = &sysctl_lasat_eeprom_value
+ },
#ifdef CONFIG_INET
- {LASAT_IPADDR, "ipaddr", &lasat_board_info.li_eeprom_info.ipaddr, sizeof(int),
- 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
- {LASAT_NETMASK, "netmask", &lasat_board_info.li_eeprom_info.netmask, sizeof(int),
- 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
- {LASAT_BCAST, "bcastaddr", &lasat_bcastaddr,
- sizeof(lasat_bcastaddr), 0600, NULL,
- &proc_dostring, &sysctl_string},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "ipaddr",
+ .data = &lasat_board_info.li_eeprom_info.ipaddr,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_lasat_ip,
+ .strategy = &sysctl_lasat_intvec
+ },
+ {
+ .ctl_name = LASAT_NETMASK,
+ .procname = "netmask",
+ .data = &lasat_board_info.li_eeprom_info.netmask,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_lasat_ip,
+ .strategy = &sysctl_lasat_intvec
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "bcastaddr",
+ .data = &lasat_bcastaddr,
+ .maxlen = sizeof(lasat_bcastaddr),
+ .mode = 0600,
+ .proc_handler = &proc_dostring,
+ .strategy = &sysctl_string
+ },
#endif
- {LASAT_PASSWORD, "passwd_hash", &lasat_board_info.li_eeprom_info.passwd_hash, sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
- 0600, NULL, &proc_dolasatstring, &sysctl_lasatstring},
- {LASAT_SBOOT, "boot-service", &lasat_boot_to_service, sizeof(int),
- 0644, NULL, &proc_dointvec, &sysctl_intvec},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "passwd_hash",
+ .data = &lasat_board_info.li_eeprom_info.passwd_hash,
+ .maxlen = sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
+ .mode = 0600,
+ .proc_handler = &proc_dolasatstring,
+ .strategy = &sysctl_lasatstring
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "boot-service",
+ .data = &lasat_boot_to_service,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ .strategy = &sysctl_intvec
+ },
#ifdef CONFIG_DS1603
- {LASAT_RTC, "rtc", &rtctmp, sizeof(int),
- 0644, NULL, &proc_dolasatrtc, &sysctl_lasat_rtc},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "rtc",
+ .data = &rtctmp,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dolasatrtc,
+ .strategy = &sysctl_lasat_rtc
+ },
#endif
- {LASAT_NAMESTR, "namestr", &lasat_board_info.li_namestr, sizeof(lasat_board_info.li_namestr),
- 0444, NULL, &proc_dostring, &sysctl_string},
- {LASAT_TYPESTR, "typestr", &lasat_board_info.li_typestr, sizeof(lasat_board_info.li_typestr),
- 0444, NULL, &proc_dostring, &sysctl_string},
- {0}
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "namestr",
+ .data = &lasat_board_info.li_namestr,
+ .maxlen = sizeof(lasat_board_info.li_namestr),
+ .mode = 0444,
+ .proc_handler = &proc_dostring,
+ .strategy = &sysctl_string
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "typestr",
+ .data = &lasat_board_info.li_typestr,
+ .maxlen = sizeof(lasat_board_info.li_typestr),
+ .mode = 0444,
+ .proc_handler = &proc_dostring,
+ .strategy = &sysctl_string
+ },
+ {}
};
-#define CTL_LASAT 1 // CTL_ANY ???
static ctl_table lasat_root_table[] = {
- { CTL_LASAT, "lasat", NULL, 0, 0555, lasat_table },
- { 0 }
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "lasat",
+ .mode = 0555,
+ .child = lasat_table
+ },
+ {}
};
static int __init lasat_register_sysctl(void)
@@ -345,7 +432,7 @@ static int __init lasat_register_sysctl(void)
struct ctl_table_header *lasat_table_header;
lasat_table_header =
- register_sysctl_table(lasat_root_table, 0);
+ register_sysctl_table(lasat_root_table);
return 0;
}
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 19e41fd186c4..de5727385bc6 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -2,8 +2,8 @@
# Makefile for the Linux/MIPS-specific parts of the memory manager.
#
-obj-y += cache.o extable.o fault.o init.o pgtable.o \
- tlbex.o tlbex-fault.o
+obj-y += cache.o dma-default.o extable.o fault.o \
+ init.o pgtable.o tlbex.o tlbex-fault.o
obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
obj-$(CONFIG_64BIT) += pgtable-64.o
@@ -32,14 +32,4 @@ obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
-#
-# Choose one DMA coherency model
-#
-ifndef CONFIG_OWN_DMA
-obj-$(CONFIG_DMA_COHERENT) += dma-coherent.o
-obj-$(CONFIG_DMA_NONCOHERENT) += dma-noncoherent.o
-endif
-obj-$(CONFIG_DMA_IP27) += dma-ip27.o
-obj-$(CONFIG_DMA_IP32) += dma-ip32.o
-
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 3a8afd47feaa..9ea460b16bda 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -259,6 +259,12 @@ static void sb1_flush_cache_data_page(unsigned long addr)
on_each_cpu(sb1_flush_cache_data_page_ipi, (void *) addr, 1, 1);
}
#else
+
+static void local_sb1_flush_cache_data_page(unsigned long addr)
+{
+ __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE);
+}
+
void sb1_flush_cache_data_page(unsigned long)
__attribute__((alias("local_sb1_flush_cache_data_page")));
#endif
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 1f954a238a63..31819c58bffa 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -107,8 +107,6 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
}
}
-#define __weak __attribute__((weak))
-
static char cache_panic[] __initdata = "Yeee, unsupported cache architecture.";
void __init cpu_cache_init(void)
diff --git a/arch/mips/mm/dma-coherent.c b/arch/mips/mm/dma-coherent.c
deleted file mode 100644
index 5697c6e250a3..000000000000
--- a/arch/mips/mm/dma-coherent.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
-{
- void *ret;
- /* ignore region specifiers */
- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
- gfp |= GFP_DMA;
- ret = (void *) __get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- memset(ret, 0, size);
- *dma_handle = virt_to_phys(ret);
- }
-
- return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
- __attribute__((alias("dma_alloc_noncoherent")));
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
-{
- unsigned long addr = (unsigned long) vaddr;
-
- free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-
- return __pa(ptr);
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
-{
- int i;
-
- BUG_ON(direction == DMA_NONE);
-
- for (i = 0; i < nents; i++, sg++) {
- sg->dma_address = (dma_addr_t)page_to_phys(sg->page) + sg->offset;
- }
-
- return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size, enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-
- return page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
- return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
- /*
- * we fall back to GFP_DMA when the mask isn't all 1s,
- * so we can't guarantee allocations that must be
- * within a tighter range than GFP_DMA..
- */
- if (mask < 0x00ffffff)
- return 0;
-
- return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
- return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
-/* The DAC routines are a PCIism.. */
-
-#ifdef CONFIG_PCI
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
- struct page *page, unsigned long offset, int direction)
-{
- return (dma64_addr_t)page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
- dma64_addr_t dma_addr)
-{
- return mem_map + (dma_addr >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
- dma64_addr_t dma_addr)
-{
- return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
-
-#endif /* CONFIG_PCI */
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-default.c
index 8cecef0957c3..4a32e939698f 100644
--- a/arch/mips/mm/dma-noncoherent.c
+++ b/arch/mips/mm/dma-default.c
@@ -4,28 +4,39 @@
* for more details.
*
* Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
+ * Copyright (C) 2000, 2001, 06 Ralf Baechle <ralf@linux-mips.org>
* swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
*/
+
#include <linux/types.h>
+#include <linux/dma-mapping.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/string.h>
-#include <linux/dma-mapping.h>
#include <asm/cache.h>
#include <asm/io.h>
+#include <dma-coherence.h>
+
/*
* Warning on the terminology - Linux calls an uncached area coherent;
* MIPS terminology calls memory areas with hardware maintained coherency
* coherent.
*/
+static inline int cpu_is_noncoherent_r10000(struct device *dev)
+{
+ return !plat_device_is_coherent(dev) &&
+ (current_cpu_data.cputype == CPU_R10000 &&
+ current_cpu_data.cputype == CPU_R12000);
+}
+
void *dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t * dma_handle, gfp_t gfp)
{
void *ret;
+
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
@@ -35,7 +46,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
if (ret != NULL) {
memset(ret, 0, size);
- *dma_handle = virt_to_phys(ret);
+ *dma_handle = plat_map_dma_mem(dev, ret, size);
}
return ret;
@@ -48,10 +59,21 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
{
void *ret;
- ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+ gfp |= GFP_DMA;
+ ret = (void *) __get_free_pages(gfp, get_order(size));
+
if (ret) {
- dma_cache_wback_inv((unsigned long) ret, size);
- ret = UNCAC_ADDR(ret);
+ memset(ret, 0, size);
+ *dma_handle = plat_map_dma_mem(dev, ret, size);
+
+ if (!plat_device_is_coherent(dev)) {
+ dma_cache_wback_inv((unsigned long) ret, size);
+ ret = UNCAC_ADDR(ret);
+ }
}
return ret;
@@ -72,7 +94,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
{
unsigned long addr = (unsigned long) vaddr;
- addr = CAC_ADDR(addr);
+ if (!plat_device_is_coherent(dev))
+ addr = CAC_ADDR(addr);
+
free_pages(addr, get_order(size));
}
@@ -104,9 +128,10 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
{
unsigned long addr = (unsigned long) ptr;
- __dma_sync(addr, size, direction);
+ if (!plat_device_is_coherent(dev))
+ __dma_sync(addr, size, direction);
- return virt_to_phys(ptr);
+ return plat_map_dma_mem(dev, ptr, size);
}
EXPORT_SYMBOL(dma_map_single);
@@ -114,10 +139,11 @@ EXPORT_SYMBOL(dma_map_single);
void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
{
- unsigned long addr;
- addr = dma_addr + PAGE_OFFSET;
+ if (cpu_is_noncoherent_r10000(dev))
+ __dma_sync(plat_dma_addr_to_phys(dma_addr) + PAGE_OFFSET, size,
+ direction);
- //__dma_sync(addr, size, direction);
+ plat_unmap_dma_mem(dma_addr);
}
EXPORT_SYMBOL(dma_unmap_single);
@@ -133,11 +159,10 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
unsigned long addr;
addr = (unsigned long) page_address(sg->page);
- if (addr) {
+ if (!plat_device_is_coherent(dev) && addr)
__dma_sync(addr + sg->offset, sg->length, direction);
- sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
- + sg->offset;
- }
+ sg->dma_address = plat_map_dma_mem_page(dev, sg->page) +
+ sg->offset;
}
return nents;
@@ -148,14 +173,16 @@ EXPORT_SYMBOL(dma_map_sg);
dma_addr_t dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction direction)
{
- unsigned long addr;
-
BUG_ON(direction == DMA_NONE);
- addr = (unsigned long) page_address(page) + offset;
- dma_cache_wback_inv(addr, size);
+ if (!plat_device_is_coherent(dev)) {
+ unsigned long addr;
+
+ addr = (unsigned long) page_address(page) + offset;
+ dma_cache_wback_inv(addr, size);
+ }
- return page_to_phys(page) + offset;
+ return plat_map_dma_mem_page(dev, page) + offset;
}
EXPORT_SYMBOL(dma_map_page);
@@ -165,12 +192,14 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
{
BUG_ON(direction == DMA_NONE);
- if (direction != DMA_TO_DEVICE) {
+ if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) {
unsigned long addr;
- addr = dma_address + PAGE_OFFSET;
+ addr = plat_dma_addr_to_phys(dma_address);
dma_cache_wback_inv(addr, size);
}
+
+ plat_unmap_dma_mem(dma_address);
}
EXPORT_SYMBOL(dma_unmap_page);
@@ -183,13 +212,15 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
BUG_ON(direction == DMA_NONE);
- if (direction == DMA_TO_DEVICE)
- return;
-
for (i = 0; i < nhwentries; i++, sg++) {
- addr = (unsigned long) page_address(sg->page);
- if (addr)
- __dma_sync(addr + sg->offset, sg->length, direction);
+ if (!plat_device_is_coherent(dev) &&
+ direction != DMA_TO_DEVICE) {
+ addr = (unsigned long) page_address(sg->page);
+ if (addr)
+ __dma_sync(addr + sg->offset, sg->length,
+ direction);
+ }
+ plat_unmap_dma_mem(sg->dma_address);
}
}
@@ -198,12 +229,14 @@ EXPORT_SYMBOL(dma_unmap_sg);
void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
- unsigned long addr;
-
BUG_ON(direction == DMA_NONE);
- addr = dma_handle + PAGE_OFFSET;
- __dma_sync(addr, size, direction);
+ if (cpu_is_noncoherent_r10000(dev)) {
+ unsigned long addr;
+
+ addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+ __dma_sync(addr, size, direction);
+ }
}
EXPORT_SYMBOL(dma_sync_single_for_cpu);
@@ -211,12 +244,14 @@ EXPORT_SYMBOL(dma_sync_single_for_cpu);
void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
- unsigned long addr;
-
BUG_ON(direction == DMA_NONE);
- addr = dma_handle + PAGE_OFFSET;
- __dma_sync(addr, size, direction);
+ if (cpu_is_noncoherent_r10000(dev)) {
+ unsigned long addr;
+
+ addr = plat_dma_addr_to_phys(dma_handle);
+ __dma_sync(addr, size, direction);
+ }
}
EXPORT_SYMBOL(dma_sync_single_for_device);
@@ -224,12 +259,14 @@ EXPORT_SYMBOL(dma_sync_single_for_device);
void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
unsigned long offset, size_t size, enum dma_data_direction direction)
{
- unsigned long addr;
-
BUG_ON(direction == DMA_NONE);
- addr = dma_handle + offset + PAGE_OFFSET;
- __dma_sync(addr, size, direction);
+ if (cpu_is_noncoherent_r10000(dev)) {
+ unsigned long addr;
+
+ addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+ __dma_sync(addr + offset, size, direction);
+ }
}
EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
@@ -237,12 +274,14 @@ EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
unsigned long offset, size_t size, enum dma_data_direction direction)
{
- unsigned long addr;
-
BUG_ON(direction == DMA_NONE);
- addr = dma_handle + offset + PAGE_OFFSET;
- __dma_sync(addr, size, direction);
+ if (cpu_is_noncoherent_r10000(dev)) {
+ unsigned long addr;
+
+ addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+ __dma_sync(addr + offset, size, direction);
+ }
}
EXPORT_SYMBOL(dma_sync_single_range_for_device);
@@ -255,9 +294,12 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
BUG_ON(direction == DMA_NONE);
/* Make sure that gcc doesn't leave the empty loop body. */
- for (i = 0; i < nelems; i++, sg++)
- __dma_sync((unsigned long)page_address(sg->page),
- sg->length, direction);
+ for (i = 0; i < nelems; i++, sg++) {
+ if (!plat_device_is_coherent(dev))
+ __dma_sync((unsigned long)page_address(sg->page),
+ sg->length, direction);
+ plat_unmap_dma_mem(sg->dma_address);
+ }
}
EXPORT_SYMBOL(dma_sync_sg_for_cpu);
@@ -270,9 +312,12 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele
BUG_ON(direction == DMA_NONE);
/* Make sure that gcc doesn't leave the empty loop body. */
- for (i = 0; i < nelems; i++, sg++)
- __dma_sync((unsigned long)page_address(sg->page),
- sg->length, direction);
+ for (i = 0; i < nelems; i++, sg++) {
+ if (!plat_device_is_coherent(dev))
+ __dma_sync((unsigned long)page_address(sg->page),
+ sg->length, direction);
+ plat_unmap_dma_mem(sg->dma_address);
+ }
}
EXPORT_SYMBOL(dma_sync_sg_for_device);
@@ -301,70 +346,18 @@ EXPORT_SYMBOL(dma_supported);
int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
{
- return 1;
+ return plat_device_is_coherent(dev);
}
EXPORT_SYMBOL(dma_is_consistent);
void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction)
{
- if (direction == DMA_NONE)
- return;
+ BUG_ON(direction == DMA_NONE);
- dma_cache_wback_inv((unsigned long)vaddr, size);
+ if (!plat_device_is_coherent(dev))
+ dma_cache_wback_inv((unsigned long)vaddr, size);
}
EXPORT_SYMBOL(dma_cache_sync);
-
-/* The DAC routines are a PCIism.. */
-
-#ifdef CONFIG_PCI
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
- struct page *page, unsigned long offset, int direction)
-{
- return (dma64_addr_t)page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
- dma64_addr_t dma_addr)
-{
- return mem_map + (dma_addr >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
- dma64_addr_t dma_addr)
-{
- return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-
- dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-
- dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
-
-#endif /* CONFIG_PCI */
diff --git a/arch/mips/mm/dma-ip27.c b/arch/mips/mm/dma-ip27.c
deleted file mode 100644
index f088344db465..000000000000
--- a/arch/mips/mm/dma-ip27.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-#include <asm/cache.h>
-#include <asm/pci/bridge.h>
-
-#define pdev_to_baddr(pdev, addr) \
- (BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr))
-#define dev_to_baddr(dev, addr) \
- pdev_to_baddr(to_pci_dev(dev), (addr))
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
-{
- void *ret;
-
- /* ignore region specifiers */
- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
- gfp |= GFP_DMA;
- ret = (void *) __get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- memset(ret, 0, size);
- *dma_handle = dev_to_baddr(dev, virt_to_phys(ret));
- }
-
- return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
- __attribute__((alias("dma_alloc_noncoherent")));
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
-{
- unsigned long addr = (unsigned long) vaddr;
-
- free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-
- return dev_to_baddr(dev, __pa(ptr));
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
-{
- int i;
-
- BUG_ON(direction == DMA_NONE);
-
- for (i = 0; i < nents; i++, sg++) {
- sg->dma_address = (dma_addr_t) dev_to_baddr(dev,
- page_to_phys(sg->page) + sg->offset);
- }
-
- return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size, enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-
- return dev_to_baddr(dev, page_to_phys(page) + offset);
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
- return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
- /*
- * we fall back to GFP_DMA when the mask isn't all 1s,
- * so we can't guarantee allocations that must be
- * within a tighter range than GFP_DMA..
- */
- if (mask < 0x00ffffff)
- return 0;
-
- return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
- return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
- struct page *page, unsigned long offset, int direction)
-{
- dma64_addr_t addr = page_to_phys(page) + offset;
-
- return (dma64_addr_t) pdev_to_baddr(pdev, addr);
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
- dma64_addr_t dma_addr)
-{
- struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus);
-
- return pfn_to_page((dma_addr - bc->baddr) >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
- dma64_addr_t dma_addr)
-{
- return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c
deleted file mode 100644
index b42b6f7456e6..000000000000
--- a/arch/mips/mm/dma-ip32.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
- * Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- * IP32 changes by Ilya.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-#include <asm/ip32/crime.h>
-
-/*
- * Warning on the terminology - Linux calls an uncached area coherent;
- * MIPS terminology calls memory areas with hardware maintained coherency
- * coherent.
- */
-
-/*
- * Few notes.
- * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M
- * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for native-endian)
- * 3. All other devices see memory as one big chunk at 0x40000000
- * 4. Non-PCI devices will pass NULL as struct device*
- * Thus we translate differently, depending on device.
- */
-
-#define RAM_OFFSET_MASK 0x3fffffff
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
-{
- void *ret;
- /* ignore region specifiers */
- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
- gfp |= GFP_DMA;
- ret = (void *) __get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- unsigned long addr = virt_to_phys(ret)&RAM_OFFSET_MASK;
- memset(ret, 0, size);
- if(dev==NULL)
- addr+= CRIME_HI_MEM_BASE;
- *dma_handle = addr;
- }
-
- return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
-{
- void *ret;
-
- ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
- if (ret) {
- dma_cache_wback_inv((unsigned long) ret, size);
- ret = UNCAC_ADDR(ret);
- }
-
- return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
-{
- free_pages((unsigned long) vaddr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
-{
- unsigned long addr = (unsigned long) vaddr;
-
- addr = CAC_ADDR(addr);
- free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-static inline void __dma_sync(unsigned long addr, size_t size,
- enum dma_data_direction direction)
-{
- switch (direction) {
- case DMA_TO_DEVICE:
- dma_cache_wback(addr, size);
- break;
-
- case DMA_FROM_DEVICE:
- dma_cache_inv(addr, size);
- break;
-
- case DMA_BIDIRECTIONAL:
- dma_cache_wback_inv(addr, size);
- break;
-
- default:
- BUG();
- }
-}
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction direction)
-{
- unsigned long addr = (unsigned long) ptr;
-
- switch (direction) {
- case DMA_TO_DEVICE:
- dma_cache_wback(addr, size);
- break;
-
- case DMA_FROM_DEVICE:
- dma_cache_inv(addr, size);
- break;
-
- case DMA_BIDIRECTIONAL:
- dma_cache_wback_inv(addr, size);
- break;
-
- default:
- BUG();
- }
-
- addr = virt_to_phys(ptr)&RAM_OFFSET_MASK;
- if(dev == NULL)
- addr+=CRIME_HI_MEM_BASE;
- return (dma_addr_t)addr;
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction direction)
-{
- switch (direction) {
- case DMA_TO_DEVICE:
- break;
-
- case DMA_FROM_DEVICE:
- break;
-
- case DMA_BIDIRECTIONAL:
- break;
-
- default:
- BUG();
- }
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
-{
- int i;
-
- BUG_ON(direction == DMA_NONE);
-
- for (i = 0; i < nents; i++, sg++) {
- unsigned long addr;
-
- addr = (unsigned long) page_address(sg->page)+sg->offset;
- if (addr)
- __dma_sync(addr, sg->length, direction);
- addr = __pa(addr)&RAM_OFFSET_MASK;
- if(dev == NULL)
- addr += CRIME_HI_MEM_BASE;
- sg->dma_address = (dma_addr_t)addr;
- }
-
- return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size, enum dma_data_direction direction)
-{
- unsigned long addr;
-
- BUG_ON(direction == DMA_NONE);
-
- addr = (unsigned long) page_address(page) + offset;
- dma_cache_wback_inv(addr, size);
- addr = __pa(addr)&RAM_OFFSET_MASK;
- if(dev == NULL)
- addr += CRIME_HI_MEM_BASE;
-
- return (dma_addr_t)addr;
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-
- if (direction != DMA_TO_DEVICE) {
- unsigned long addr;
-
- dma_address&=RAM_OFFSET_MASK;
- addr = dma_address + PAGE_OFFSET;
- if(dma_address>=256*1024*1024)
- addr+=CRIME_HI_MEM_BASE;
- dma_cache_wback_inv(addr, size);
- }
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
- enum dma_data_direction direction)
-{
- unsigned long addr;
- int i;
-
- BUG_ON(direction == DMA_NONE);
-
- if (direction == DMA_TO_DEVICE)
- return;
-
- for (i = 0; i < nhwentries; i++, sg++) {
- addr = (unsigned long) page_address(sg->page);
- if (!addr)
- continue;
- dma_cache_wback_inv(addr + sg->offset, sg->length);
- }
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
-{
- unsigned long addr;
-
- BUG_ON(direction == DMA_NONE);
-
- dma_handle&=RAM_OFFSET_MASK;
- addr = dma_handle + PAGE_OFFSET;
- if(dma_handle>=256*1024*1024)
- addr+=CRIME_HI_MEM_BASE;
- __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
-{
- unsigned long addr;
-
- BUG_ON(direction == DMA_NONE);
-
- dma_handle&=RAM_OFFSET_MASK;
- addr = dma_handle + PAGE_OFFSET;
- if(dma_handle>=256*1024*1024)
- addr+=CRIME_HI_MEM_BASE;
- __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size, enum dma_data_direction direction)
-{
- unsigned long addr;
-
- BUG_ON(direction == DMA_NONE);
-
- dma_handle&=RAM_OFFSET_MASK;
- addr = dma_handle + offset + PAGE_OFFSET;
- if(dma_handle>=256*1024*1024)
- addr+=CRIME_HI_MEM_BASE;
- __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size, enum dma_data_direction direction)
-{
- unsigned long addr;
-
- BUG_ON(direction == DMA_NONE);
-
- dma_handle&=RAM_OFFSET_MASK;
- addr = dma_handle + offset + PAGE_OFFSET;
- if(dma_handle>=256*1024*1024)
- addr+=CRIME_HI_MEM_BASE;
- __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
- int i;
-
- BUG_ON(direction == DMA_NONE);
-
- /* Make sure that gcc doesn't leave the empty loop body. */
- for (i = 0; i < nelems; i++, sg++)
- __dma_sync((unsigned long)page_address(sg->page),
- sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
- int i;
-
- BUG_ON(direction == DMA_NONE);
-
- /* Make sure that gcc doesn't leave the empty loop body. */
- for (i = 0; i < nelems; i++, sg++)
- __dma_sync((unsigned long)page_address(sg->page),
- sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
- return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
- /*
- * we fall back to GFP_DMA when the mask isn't all 1s,
- * so we can't guarantee allocations that must be
- * within a tighter range than GFP_DMA..
- */
- if (mask < 0x00ffffff)
- return 0;
-
- return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
- return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
- enum dma_data_direction direction)
-{
- if (direction == DMA_NONE)
- return;
-
- dma_cache_wback_inv((unsigned long)vaddr, size);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
diff --git a/arch/mips/momentum/jaguar_atx/platform.c b/arch/mips/momentum/jaguar_atx/platform.c
index 035ea5137c71..81037709ba0d 100644
--- a/arch/mips/momentum/jaguar_atx/platform.c
+++ b/arch/mips/momentum/jaguar_atx/platform.c
@@ -129,7 +129,7 @@ static struct mv643xx_eth_platform_data eth2_pd = {
static struct platform_device eth2_device = {
.name = MV643XX_ETH_NAME,
- .id = 1,
+ .id = 2,
.num_resources = ARRAY_SIZE(mv64x60_eth2_resources),
.resource = mv64x60_eth2_resources,
.dev = {
diff --git a/arch/mips/momentum/ocelot_3/platform.c b/arch/mips/momentum/ocelot_3/platform.c
index eefe5841fbb2..57cfe5c6e4a8 100644
--- a/arch/mips/momentum/ocelot_3/platform.c
+++ b/arch/mips/momentum/ocelot_3/platform.c
@@ -129,7 +129,7 @@ static struct mv643xx_eth_platform_data eth2_pd = {
static struct platform_device eth2_device = {
.name = MV643XX_ETH_NAME,
- .id = 1,
+ .id = 2,
.num_resources = ARRAY_SIZE(mv64x60_eth2_resources),
.resource = mv64x60_eth2_resources,
.dev = {
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 82b20c28bef8..bf85995ca042 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -2,7 +2,7 @@
# Makefile for the PCI specific kernel interface routines under Linux.
#
-obj-y += pci.o
+obj-y += pci.o pci-dac.o
#
# PCI bus host bridge specific code
diff --git a/arch/mips/pci/pci-dac.c b/arch/mips/pci/pci-dac.c
new file mode 100644
index 000000000000..0f0ea1b7d4dd
--- /dev/null
+++ b/arch/mips/pci/pci-dac.c
@@ -0,0 +1,79 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001, 06 Ralf Baechle <ralf@linux-mips.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+#include <dma-coherence.h>
+
+#include <linux/pci.h>
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+ struct page *page, unsigned long offset, int direction)
+{
+ struct device *dev = &pdev->dev;
+
+ BUG_ON(direction == DMA_NONE);
+
+ if (!plat_device_is_coherent(dev)) {
+ unsigned long addr;
+
+ addr = (unsigned long) page_address(page) + offset;
+ dma_cache_wback_inv(addr, PAGE_SIZE);
+ }
+
+ return plat_map_dma_mem_page(dev, page) + offset;
+}
+
+EXPORT_SYMBOL(pci_dac_page_to_dma);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+ dma64_addr_t dma_addr)
+{
+ return pfn_to_page(plat_dma_addr_to_phys(dma_addr) >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+ dma64_addr_t dma_addr)
+{
+ return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
+ dma64_addr_t dma_addr, size_t len, int direction)
+{
+ BUG_ON(direction == PCI_DMA_NONE);
+
+ if (!plat_device_is_coherent(&pdev->dev))
+ dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
+
+void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
+ dma64_addr_t dma_addr, size_t len, int direction)
+{
+ BUG_ON(direction == PCI_DMA_NONE);
+
+ if (!plat_device_is_coherent(&pdev->dev))
+ dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
diff --git a/arch/mips/philips/pnx8550/common/proc.c b/arch/mips/philips/pnx8550/common/proc.c
index 72a016767e09..3f097558ef13 100644
--- a/arch/mips/philips/pnx8550/common/proc.c
+++ b/arch/mips/philips/pnx8550/common/proc.c
@@ -79,10 +79,7 @@ static int pnx8550_proc_init( void )
// Create /proc/pnx8550
pnx8550_dir = create_proc_entry("pnx8550", S_IFDIR|S_IRUGO, NULL);
- if (pnx8550_dir){
- pnx8550_dir->nlink = 1;
- }
- else {
+ if (!pnx8550_dir) {
printk(KERN_ERR "Can't create pnx8550 proc dir\n");
return -1;
}
@@ -90,7 +87,6 @@ static int pnx8550_proc_init( void )
// Create /proc/pnx8550/timers
pnx8550_timers = create_proc_entry("timers", S_IFREG|S_IRUGO, pnx8550_dir );
if (pnx8550_timers){
- pnx8550_timers->nlink = 1;
pnx8550_timers->read_proc = pnx8550_timers_read;
}
else {
@@ -100,7 +96,6 @@ static int pnx8550_proc_init( void )
// Create /proc/pnx8550/registers
pnx8550_registers = create_proc_entry("registers", S_IFREG|S_IRUGO, pnx8550_dir );
if (pnx8550_registers){
- pnx8550_registers->nlink = 1;
pnx8550_registers->read_proc = pnx8550_registers_read;
}
else {
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
index d1a906e683b2..212547c57310 100644
--- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
+++ b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
@@ -374,7 +374,7 @@ static long sbprof_tb_ioctl(struct file *filp,
return error;
}
-static struct file_operations sbprof_tb_fops = {
+static const struct file_operations sbprof_tb_fops = {
.owner = THIS_MODULE,
.open = sbprof_tb_open,
.release = sbprof_tb_release,
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index 735cb8778f4c..7316a78fdd68 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -137,6 +137,8 @@ int tx4927_using_backplane = 0;
extern void gt64120_time_init(void);
extern void toshiba_rbtx4927_irq_setup(void);
+char *prom_getcmdline(void);
+
#ifdef CONFIG_PCI
#define CONFIG_TX4927BUG_WORKAROUND
#undef TX4927_SUPPORT_COMMAND_IO