From 9be401a2aee69a63c88a0b91d73d3a8db091abda Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Mon, 3 Mar 2008 16:36:23 +0900 Subject: ARM: OMAP: Remove compiler warning when i2c is not set Remove compiler warning when i2c is not set Signed-off-by: Kyungmin Park Acked-by: Jarkko Nikula --- include/asm-arm/arch-omap/common.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/asm-arm/arch-omap/common.h b/include/asm-arm/arch-omap/common.h index 442aecbb8f44..224e009e5296 100644 --- a/include/asm-arm/arch-omap/common.h +++ b/include/asm-arm/arch-omap/common.h @@ -27,9 +27,7 @@ #ifndef __ARCH_ARM_MACH_OMAP_COMMON_H #define __ARCH_ARM_MACH_OMAP_COMMON_H -#ifdef CONFIG_I2C_OMAP #include -#endif struct sys_timer; @@ -41,7 +39,12 @@ extern int omap_register_i2c_bus(int bus_id, u32 clkrate, struct i2c_board_info const *info, unsigned len); #else -#define omap_register_i2c_bus(a, b, c, d) 0 +static inline int omap_register_i2c_bus(int bus_id, u32 clkrate, + struct i2c_board_info const *info, + unsigned len) +{ + return 0; +} #endif #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ -- cgit v1.2.3-55-g7522 From 0cc0a441163b92fbda5fe1886cb6e9876cf08f40 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 28 Feb 2008 14:44:08 -0800 Subject: ARM: OMAP1: omap h3 regression and build fix Get rid of build warnings and errors in mainline for H3 boards; not all the H3 updates were correct, it seems like the OMAP1 boards are not getting proper build testing. Also, commit e27a93a944a5ba6a0112750c8243abba86d56e94 introduced a regression related to the tps65013 chip. Signed-off-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-h3.c | 22 ++++++++++++++++++++++ include/asm-arm/arch-omap/board-h3.h | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 6fc516855a8c..c3ef1ee5f77b 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,8 @@ #include #include +#define H3_TS_GPIO 48 + static int h3_keymap[] = { KEY(0, 0, KEY_LEFT), KEY(0, 1, KEY_RIGHT), @@ -373,6 +376,17 @@ static struct platform_device h3_lcd_device = { .id = -1, }; +static struct spi_board_info h3_spi_board_info[] __initdata = { + [0] = { + .modalias = "tsc2101", + .bus_num = 2, + .chip_select = 0, + .irq = OMAP_GPIO_IRQ(H3_TS_GPIO), + .max_speed_hz = 16000000, + /* .platform_data = &tsc_platform_data, */ + }, +}; + static struct omap_mcbsp_reg_cfg mcbsp_regs = { .spcr2 = FREE | FRST | GRST | XRST | XINTM(3), .spcr1 = RINTM(3) | RRST, @@ -457,6 +471,14 @@ static struct omap_board_config_kernel h3_config[] __initdata = { { OMAP_TAG_LCD, &h3_lcd_config }, }; +static struct i2c_board_info __initdata h3_i2c_board_info[] = { + { + I2C_BOARD_INFO("tps65010", 0x48), + .type = "tps65013", + /* .irq = OMAP_GPIO_IRQ(??), */ + }, +}; + static struct omap_gpio_switch h3_gpio_switches[] __initdata = { { .name = "mmc_slot", diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h index 1c2b55c61ca0..0f6404435ea8 100644 --- a/include/asm-arm/arch-omap/board-h3.h +++ b/include/asm-arm/arch-omap/board-h3.h @@ -36,7 +36,7 @@ #define NR_IRQS (MAXIRQNUM + 1) -extern void __init h3_mmc_init(void); +extern void h3_mmc_init(void); extern void h3_mmc_slot_cover_handler(void *arg, int state); #endif /* __ASM_ARCH_OMAP_H3_H */ -- cgit v1.2.3-55-g7522 From 09be7553959c9947f7cbccbe1c3094bb2e3ffd28 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 3 Mar 2008 01:31:32 -0800 Subject: ARM: OMAP1: Fix compile for boards depending on old gpio expander The long term fix is to switch boards to use drivers/gpio/pcf857x.c. Signed-off-by: Tony Lindgren --- include/asm-arm/arch-omap/gpioexpander.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include') diff --git a/include/asm-arm/arch-omap/gpioexpander.h b/include/asm-arm/arch-omap/gpioexpander.h index 7a43b0a912e4..4eed1f80e2fb 100644 --- a/include/asm-arm/arch-omap/gpioexpander.h +++ b/include/asm-arm/arch-omap/gpioexpander.h @@ -18,7 +18,18 @@ /* Function Prototypes for GPIO Expander functions */ +#ifdef CONFIG_GPIOEXPANDER_OMAP int read_gpio_expa(u8 *, int); int write_gpio_expa(u8 , int); +#else +static inline int read_gpio_expa(u8 *val, int addr) +{ + return 0; +} +static inline int write_gpio_expa(u8 val, int addr) +{ + return 0; +} +#endif #endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */ -- cgit v1.2.3-55-g7522 From 4eb329a5aa113048ec9dbe2bd81ca27adab04e2d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 5 Mar 2008 18:37:16 -0800 Subject: irda: replace __inline with inline Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/net/irda/irttp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h index 32c385dd9e06..0788c23d2828 100644 --- a/include/net/irda/irttp.h +++ b/include/net/irda/irttp.h @@ -169,17 +169,17 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb, void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow); struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance); -static __inline __u32 irttp_get_saddr(struct tsap_cb *self) +static inline __u32 irttp_get_saddr(struct tsap_cb *self) { return irlmp_get_saddr(self->lsap); } -static __inline __u32 irttp_get_daddr(struct tsap_cb *self) +static inline __u32 irttp_get_daddr(struct tsap_cb *self) { return irlmp_get_daddr(self->lsap); } -static __inline __u32 irttp_get_max_seg_size(struct tsap_cb *self) +static inline __u32 irttp_get_max_seg_size(struct tsap_cb *self) { return self->max_seg_size; } -- cgit v1.2.3-55-g7522 From 04005dd9ae7bf1031408869c33df96149ebb1086 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 5 Mar 2008 18:47:03 -0800 Subject: bluetooth: Make hci_sock_cleanup() return void hci_sock_cleanup() always returns 0 and its return value isn't used anywhere in the code. Compile-tested with 'make allyesconfig && make net/bluetooth/bluetooth.ko' Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Acked-by: Marcel Holtmann --- include/net/bluetooth/bluetooth.h | 2 +- net/bluetooth/hci_sock.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 771d17783c18..750648df13f4 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -170,7 +170,7 @@ static inline int skb_frags_no(struct sk_buff *skb) int bt_err(__u16 code); extern int hci_sock_init(void); -extern int hci_sock_cleanup(void); +extern void hci_sock_cleanup(void); extern int bt_sysfs_init(void); extern void bt_sysfs_cleanup(void); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 14991323c273..b5d4019d3572 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -734,7 +734,7 @@ error: return err; } -int __exit hci_sock_cleanup(void) +void __exit hci_sock_cleanup(void) { if (bt_sock_unregister(BTPROTO_HCI) < 0) BT_ERR("HCI socket unregistration failed"); @@ -742,6 +742,4 @@ int __exit hci_sock_cleanup(void) hci_unregister_notifier(&hci_sock_nblock); proto_unregister(&hci_sk_proto); - - return 0; } -- cgit v1.2.3-55-g7522 From 10debfd29c639366f26595606b51abd27ccbb028 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 5 Mar 2008 08:44:13 -0800 Subject: [ARM] include/asm-arm - use angle brackets for includes Signed-off-by: Joe Perches include/asm-arm/plat-s3c/uncompress.h | 4 ++-- include/asm-arm/proc-fns.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) Signed-off-by: Russell King --- include/asm-arm/plat-s3c/uncompress.h | 4 ++-- include/asm-arm/proc-fns.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/asm-arm/plat-s3c/uncompress.h b/include/asm-arm/plat-s3c/uncompress.h index b5e6208175d1..19b9eda39485 100644 --- a/include/asm-arm/plat-s3c/uncompress.h +++ b/include/asm-arm/plat-s3c/uncompress.h @@ -27,8 +27,8 @@ static void arch_detect_cpu(void); /* defines for UART registers */ -#include "asm/plat-s3c/regs-serial.h" -#include "asm/plat-s3c/regs-watchdog.h" +#include +#include /* working in physical space... */ #undef S3C2410_WDOGREG diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h index a4ce457199d3..75ec760f4c74 100644 --- a/include/asm-arm/proc-fns.h +++ b/include/asm-arm/proc-fns.h @@ -214,9 +214,9 @@ #ifndef __ASSEMBLY__ #ifndef MULTI_CPU -#include "asm/cpu-single.h" +#include #else -#include "asm/cpu-multi32.h" +#include #endif #include -- cgit v1.2.3-55-g7522 From 92df78519d0a6a8677cb827b5a1b7d2520d7e202 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Wed, 5 Mar 2008 06:59:14 +0100 Subject: [ARM] 4850/1: include generic pgtable.h for !CONFIG_MMU case The nonmmu version of pgtable.h needs to include asm-generic/pgtable.h as well. It needs to pick up empty definitions of things like arch_enter_lazy_cpu_mode() to compile cleanly. Signed-off-by: Greg Ungerer Signed-off-by: Russell King --- include/asm-arm/pgtable-nommu.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/asm-arm/pgtable-nommu.h b/include/asm-arm/pgtable-nommu.h index 33c83dd87965..2e5868bbe03b 100644 --- a/include/asm-arm/pgtable-nommu.h +++ b/include/asm-arm/pgtable-nommu.h @@ -92,6 +92,8 @@ extern unsigned int kobjsize(const void *objp); #define FIRST_USER_ADDRESS (0) +#include + #else /* -- cgit v1.2.3-55-g7522 From 76db5bd26f2d79712459bf80ce0e5c0c5c31b769 Mon Sep 17 00:00:00 2001 From: Vitaly Bordug Date: Thu, 6 Mar 2008 13:53:30 +0300 Subject: [POWERPC] 8xx: fix swap This makes swap routines operate correctly on the ppc_8xx based machines. Code has been revalidated on mpc885ads (8M sdram) with recent kernel. Based on patch from Yuri Tikhonov to do the same on arch/ppc instance. Recent kernel's size makes swap feature very important on low-memory platforms, those are actually non-operable without it. Signed-off-by: Yuri Tikhonov Signed-off-by: Vitaly Bordug Signed-off-by: Kumar Gala --- arch/powerpc/kernel/head_8xx.S | 30 +++++++++++++++++++++++++++++- include/asm-powerpc/pgtable-ppc32.h | 8 -------- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index f7458396cd7c..3c9452d4308b 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -332,8 +332,18 @@ InstructionTLBMiss: mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ lwz r10, 0(r11) /* Get the pte */ +#ifdef CONFIG_SWAP + /* do not set the _PAGE_ACCESSED bit of a non-present page */ + andi. r11, r10, _PAGE_PRESENT + beq 4f + ori r10, r10, _PAGE_ACCESSED + mfspr r11, SPRN_MD_TWC /* get the pte address again */ + stw r10, 0(r11) +4: +#else ori r10, r10, _PAGE_ACCESSED stw r10, 0(r11) +#endif /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 21, 22 and 28 must be clear. @@ -398,8 +408,17 @@ DataStoreTLBMiss: DO_8xx_CPU6(0x3b80, r3) mtspr SPRN_MD_TWC, r11 - mfspr r11, SPRN_MD_TWC /* get the pte address again */ +#ifdef CONFIG_SWAP + /* do not set the _PAGE_ACCESSED bit of a non-present page */ + andi. r11, r10, _PAGE_PRESENT + beq 4f ori r10, r10, _PAGE_ACCESSED +4: + /* and update pte in table */ +#else + ori r10, r10, _PAGE_ACCESSED +#endif + mfspr r11, SPRN_MD_TWC /* get the pte address again */ stw r10, 0(r11) /* The Linux PTE won't go exactly into the MMU TLB. @@ -507,7 +526,16 @@ DataTLBError: /* Update 'changed', among others. */ +#ifdef CONFIG_SWAP + ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE + /* do not set the _PAGE_ACCESSED bit of a non-present page */ + andi. r11, r10, _PAGE_PRESENT + beq 4f + ori r10, r10, _PAGE_ACCESSED +4: +#else ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE +#endif mfspr r11, SPRN_MD_TWC /* Get pte address again */ stw r10, 0(r11) /* and update pte in table */ diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h index d1332bbcbd9b..2c79f550272b 100644 --- a/include/asm-powerpc/pgtable-ppc32.h +++ b/include/asm-powerpc/pgtable-ppc32.h @@ -339,14 +339,6 @@ extern int icache_44x_need_flush; #define _PMD_PAGE_MASK 0x000c #define _PMD_PAGE_8M 0x000c -/* - * The 8xx TLB miss handler allegedly sets _PAGE_ACCESSED in the PTE - * for an address even if _PAGE_PRESENT is not set, as a performance - * optimization. This is a bug if you ever want to use swap unless - * _PAGE_ACCESSED is 2, which it isn't, or unless you have 8xx-specific - * definitions for __swp_entry etc. below, which would be gross. - * -- paulus - */ #define _PTE_NONE_MASK _PAGE_ACCESSED #else /* CONFIG_6xx */ -- cgit v1.2.3-55-g7522 From e9720acd728a46cb40daa52c99a979f7c4ff195c Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 7 Mar 2008 11:08:40 -0800 Subject: [NET]: Make /proc/net a symlink on /proc/self/net (v3) Current /proc/net is done with so called "shadows", but current implementation is broken and has little chances to get fixed. The problem is that dentries subtree of /proc/net directory has fancy revalidation rules to make processes living in different net namespaces see different entries in /proc/net subtree, but currently, tasks see in the /proc/net subdir the contents of any other namespace, depending on who opened the file first. The proposed fix is to turn /proc/net into a symlink, which points to /proc/self/net, which in turn shows what previously was in /proc/net - the network-related info, from the net namespace the appropriate task lives in. # ls -l /proc/net lrwxrwxrwx 1 root root 8 Mar 5 15:17 /proc/net -> self/net In other words - this behaves like /proc/mounts, but unlike "mounts", "net" is not a file, but a directory. Changes from v2: * Fixed discrepancy of /proc/net nlink count and selinux labeling screwup pointed out by Stephen. To get the correct nlink count the ->getattr callback for /proc/net is overridden to read one from the net->proc_net entry. To make selinux still work the net->proc_net entry is initialized properly, i.e. with the "net" name and the proc_net parent. Selinux fixes are Acked-by: Stephen Smalley Changes from v1: * Fixed a task_struct leak in get_proc_task_net, pointed out by Paul. Signed-off-by: Pavel Emelyanov Acked-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- fs/proc/base.c | 1 + fs/proc/generic.c | 26 ++++++---- fs/proc/internal.h | 7 +++ fs/proc/proc_net.c | 117 +++++++++++++++++++++++++++++++++----------- include/linux/proc_fs.h | 3 -- include/net/net_namespace.h | 1 - 6 files changed, 114 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/fs/proc/base.c b/fs/proc/base.c index 96ee899d6502..cc43cf0c1fa5 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2274,6 +2274,7 @@ static const struct pid_entry tgid_base_stuff[] = { DIR("task", S_IRUGO|S_IXUGO, task), DIR("fd", S_IRUSR|S_IXUSR, fd), DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), + DIR("net", S_IRUGO|S_IXUSR, net), REG("environ", S_IRUSR, environ), INF("auxv", S_IRUSR, pid_auxv), ONE("status", S_IRUGO, pid_status), diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 68971e66cd41..a36ad3c75cf4 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -377,15 +377,14 @@ static struct dentry_operations proc_dentry_operations = * Don't create negative dentries here, return -ENOENT by hand * instead. */ -struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) +struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir, + struct dentry *dentry) { struct inode *inode = NULL; - struct proc_dir_entry * de; int error = -ENOENT; lock_kernel(); spin_lock(&proc_subdir_lock); - de = PDE(dir); if (de) { for (de = de->subdir; de ; de = de->next) { if (de->namelen != dentry->d_name.len) @@ -393,8 +392,6 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { unsigned int ino; - if (de->shadow_proc) - de = de->shadow_proc(current, de); ino = de->low_ino; de_get(de); spin_unlock(&proc_subdir_lock); @@ -417,6 +414,12 @@ out_unlock: return ERR_PTR(error); } +struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +{ + return proc_lookup_de(PDE(dir), dir, dentry); +} + /* * This returns non-zero if at EOF, so that the /proc * root directory can use this and check if it should @@ -426,10 +429,9 @@ out_unlock: * value of the readdir() call, as long as it's non-negative * for success.. */ -int proc_readdir(struct file * filp, - void * dirent, filldir_t filldir) +int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, + filldir_t filldir) { - struct proc_dir_entry * de; unsigned int ino; int i; struct inode *inode = filp->f_path.dentry->d_inode; @@ -438,7 +440,6 @@ int proc_readdir(struct file * filp, lock_kernel(); ino = inode->i_ino; - de = PDE(inode); if (!de) { ret = -EINVAL; goto out; @@ -499,6 +500,13 @@ out: unlock_kernel(); return ret; } +int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) +{ + struct inode *inode = filp->f_path.dentry->d_inode; + + return proc_readdir_de(PDE(inode), filp, dirent, filldir); +} + /* * These are the generic /proc directory operations. They * use the in-memory "struct proc_dir_entry" tree to parse diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 1c81c8f1aeed..bc72f5c8c47d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -64,6 +64,8 @@ extern const struct file_operations proc_numa_maps_operations; extern const struct file_operations proc_smaps_operations; extern const struct file_operations proc_clear_refs_operations; extern const struct file_operations proc_pagemap_operations; +extern const struct file_operations proc_net_operations; +extern const struct inode_operations proc_net_inode_operations; void free_proc_entry(struct proc_dir_entry *de); @@ -83,3 +85,8 @@ static inline int proc_fd(struct inode *inode) { return PROC_I(inode)->fd; } + +struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *ino, + struct dentry *dentry); +int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, + filldir_t filldir); diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 14e9b5aaf863..4caa5f774fb7 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c @@ -63,6 +63,82 @@ int seq_release_net(struct inode *ino, struct file *f) } EXPORT_SYMBOL_GPL(seq_release_net); +static struct net *get_proc_task_net(struct inode *dir) +{ + struct task_struct *task; + struct nsproxy *ns; + struct net *net = NULL; + + rcu_read_lock(); + task = pid_task(proc_pid(dir), PIDTYPE_PID); + if (task != NULL) { + ns = task_nsproxy(task); + if (ns != NULL) + net = get_net(ns->net_ns); + } + rcu_read_unlock(); + + return net; +} + +static struct dentry *proc_tgid_net_lookup(struct inode *dir, + struct dentry *dentry, struct nameidata *nd) +{ + struct dentry *de; + struct net *net; + + de = ERR_PTR(-ENOENT); + net = get_proc_task_net(dir); + if (net != NULL) { + de = proc_lookup_de(net->proc_net, dir, dentry); + put_net(net); + } + return de; +} + +static int proc_tgid_net_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + struct net *net; + + net = get_proc_task_net(inode); + + generic_fillattr(inode, stat); + + if (net != NULL) { + stat->nlink = net->proc_net->nlink; + put_net(net); + } + + return 0; +} + +const struct inode_operations proc_net_inode_operations = { + .lookup = proc_tgid_net_lookup, + .getattr = proc_tgid_net_getattr, +}; + +static int proc_tgid_net_readdir(struct file *filp, void *dirent, + filldir_t filldir) +{ + int ret; + struct net *net; + + ret = -EINVAL; + net = get_proc_task_net(filp->f_path.dentry->d_inode); + if (net != NULL) { + ret = proc_readdir_de(net->proc_net, filp, dirent, filldir); + put_net(net); + } + return ret; +} + +const struct file_operations proc_net_operations = { + .read = generic_read_dir, + .readdir = proc_tgid_net_readdir, +}; + struct proc_dir_entry *proc_net_fops_create(struct net *net, const char *name, mode_t mode, const struct file_operations *fops) @@ -83,14 +159,6 @@ struct net *get_proc_net(const struct inode *inode) } EXPORT_SYMBOL_GPL(get_proc_net); -static struct proc_dir_entry *shadow_pde; - -static struct proc_dir_entry *proc_net_shadow(struct task_struct *task, - struct proc_dir_entry *de) -{ - return task->nsproxy->net_ns->proc_net; -} - struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name, struct proc_dir_entry *parent) { @@ -104,45 +172,39 @@ EXPORT_SYMBOL_GPL(proc_net_mkdir); static __net_init int proc_net_ns_init(struct net *net) { - struct proc_dir_entry *root, *netd, *net_statd; + struct proc_dir_entry *netd, *net_statd; int err; err = -ENOMEM; - root = kzalloc(sizeof(*root), GFP_KERNEL); - if (!root) + netd = kzalloc(sizeof(*netd), GFP_KERNEL); + if (!netd) goto out; - err = -EEXIST; - netd = proc_net_mkdir(net, "net", root); - if (!netd) - goto free_root; + netd->data = net; + netd->nlink = 2; + netd->name = "net"; + netd->namelen = 3; + netd->parent = &proc_root; err = -EEXIST; net_statd = proc_net_mkdir(net, "stat", netd); if (!net_statd) goto free_net; - root->data = net; - - net->proc_net_root = root; net->proc_net = netd; net->proc_net_stat = net_statd; - err = 0; + return 0; +free_net: + kfree(netd); out: return err; -free_net: - remove_proc_entry("net", root); -free_root: - kfree(root); - goto out; } static __net_exit void proc_net_ns_exit(struct net *net) { remove_proc_entry("stat", net->proc_net); - remove_proc_entry("net", net->proc_net_root); - kfree(net->proc_net_root); + kfree(net->proc_net); } static struct pernet_operations __net_initdata proc_net_ns_ops = { @@ -152,8 +214,7 @@ static struct pernet_operations __net_initdata proc_net_ns_ops = { int __init proc_net_init(void) { - shadow_pde = proc_mkdir("net", NULL); - shadow_pde->shadow_proc = proc_net_shadow; + proc_symlink("net", NULL, "self/net"); return register_pernet_subsys(&proc_net_ns_ops); } diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index d9a9e718ad19..9b6c935f69cf 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -50,8 +50,6 @@ typedef int (read_proc_t)(char *page, char **start, off_t off, typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data); typedef int (get_info_t)(char *, char **, off_t, int); -typedef struct proc_dir_entry *(shadow_proc_t)(struct task_struct *task, - struct proc_dir_entry *pde); struct proc_dir_entry { unsigned int low_ino; @@ -82,7 +80,6 @@ struct proc_dir_entry { int pde_users; /* number of callers into module in progress */ spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ struct completion *pde_unload_completion; - shadow_proc_t *shadow_proc; }; struct kcore_list { diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 28738b7d53eb..923f2b8b9096 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -31,7 +31,6 @@ struct net { struct proc_dir_entry *proc_net; struct proc_dir_entry *proc_net_stat; - struct proc_dir_entry *proc_net_root; struct list_head sysctl_table_headers; -- cgit v1.2.3-55-g7522 From e621e69137b24fdbbe7ad28214e8d81e614c25b7 Mon Sep 17 00:00:00 2001 From: Kirill A. Shutemov Date: Fri, 7 Mar 2008 11:11:13 -0800 Subject: [NET]: include into linux/ethtool.h for __u* typedef Signed-off-by: Kirill A. Shutemov Signed-off-by: David S. Miller --- include/linux/ethtool.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index fcbe8b640ffb..c8d216357865 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -12,6 +12,7 @@ #ifndef _LINUX_ETHTOOL_H #define _LINUX_ETHTOOL_H +#include /* This should work for both 32 and 64 bit userland. */ struct ethtool_cmd { -- cgit v1.2.3-55-g7522 From 1757f2d12dce775982aaa006bce1cf4f7ce90111 Mon Sep 17 00:00:00 2001 From: Yuri Tikhonov Date: Sat, 2 Feb 2008 10:47:31 +0300 Subject: [PPC] 8xx: swap bug-fix This makes swap routines operate correctly on the ppc_8xx based machines. Recent kernel's size makes swap feature very important on low-memory platfor those are actually non-operable without it. Signed-off-by: Yuri Tikhonov Signed-off-by: Kumar Gala --- arch/ppc/kernel/head_8xx.S | 30 +++++++++++++++++++++++++++++- include/asm-ppc/pgtable.h | 8 -------- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index eb8d26f87362..321bda2de2cb 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -329,8 +329,18 @@ InstructionTLBMiss: mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ lwz r10, 0(r11) /* Get the pte */ +#ifdef CONFIG_SWAP + /* do not set the _PAGE_ACCESSED bit of a non-present page */ + andi. r11, r10, _PAGE_PRESENT + beq 4f + ori r10, r10, _PAGE_ACCESSED + mfspr r11, SPRN_MD_TWC /* get the pte address again */ + stw r10, 0(r11) +4: +#else ori r10, r10, _PAGE_ACCESSED stw r10, 0(r11) +#endif /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 21, 22 and 28 must be clear. @@ -395,8 +405,17 @@ DataStoreTLBMiss: DO_8xx_CPU6(0x3b80, r3) mtspr SPRN_MD_TWC, r11 - mfspr r11, SPRN_MD_TWC /* get the pte address again */ +#ifdef CONFIG_SWAP + /* do not set the _PAGE_ACCESSED bit of a non-present page */ + andi. r11, r10, _PAGE_PRESENT + beq 4f + ori r10, r10, _PAGE_ACCESSED +4: + /* and update pte in table */ +#else ori r10, r10, _PAGE_ACCESSED +#endif + mfspr r11, SPRN_MD_TWC /* get the pte address again */ stw r10, 0(r11) /* The Linux PTE won't go exactly into the MMU TLB. @@ -575,7 +594,16 @@ DataTLBError: /* Update 'changed', among others. */ +#ifdef CONFIG_SWAP + ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE + /* do not set the _PAGE_ACCESSED bit of a non-present page */ + andi. r11, r10, _PAGE_PRESENT + beq 4f + ori r10, r10, _PAGE_ACCESSED +4: +#else ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE +#endif mfspr r11, SPRN_MD_TWC /* Get pte address again */ stw r10, 0(r11) /* and update pte in table */ diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index 69347bdbb401..70435d32129a 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -299,14 +299,6 @@ extern unsigned long ioremap_bot, ioremap_base; #define _PMD_PAGE_MASK 0x000c #define _PMD_PAGE_8M 0x000c -/* - * The 8xx TLB miss handler allegedly sets _PAGE_ACCESSED in the PTE - * for an address even if _PAGE_PRESENT is not set, as a performance - * optimization. This is a bug if you ever want to use swap unless - * _PAGE_ACCESSED is 2, which it isn't, or unless you have 8xx-specific - * definitions for __swp_entry etc. below, which would be gross. - * -- paulus - */ #define _PTE_NONE_MASK _PAGE_ACCESSED #else /* CONFIG_6xx */ -- cgit v1.2.3-55-g7522 From f13ba2f7d3a877967477ec8f64e1dae7a967c7e2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 8 Mar 2008 20:29:43 +0800 Subject: [CRYPTO] skcipher: Fix section mismatches The previous patch to move chainiv and eseqiv into blkcipher created a section mismatch for the chainiv exit function which was also called from __init. This patch removes the __exit marking on it. Signed-off-by: Herbert Xu --- crypto/chainiv.c | 4 +--- crypto/eseqiv.c | 2 -- include/crypto/internal/skcipher.h | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/crypto/chainiv.c b/crypto/chainiv.c index 0a7cac6e9089..6da3f577e4db 100644 --- a/crypto/chainiv.c +++ b/crypto/chainiv.c @@ -318,10 +318,8 @@ int __init chainiv_module_init(void) { return crypto_register_template(&chainiv_tmpl); } -EXPORT_SYMBOL_GPL(chainiv_module_init); -void __exit chainiv_module_exit(void) +void chainiv_module_exit(void) { crypto_unregister_template(&chainiv_tmpl); } -EXPORT_SYMBOL_GPL(chainiv_module_exit); diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c index 6f2cd063b6fe..b14f14e314b6 100644 --- a/crypto/eseqiv.c +++ b/crypto/eseqiv.c @@ -251,10 +251,8 @@ int __init eseqiv_module_init(void) { return crypto_register_template(&eseqiv_tmpl); } -EXPORT_SYMBOL_GPL(eseqiv_module_init); void __exit eseqiv_module_exit(void) { crypto_unregister_template(&eseqiv_tmpl); } -EXPORT_SYMBOL_GPL(eseqiv_module_exit); diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h index a8f12644a13c..ccc32bad9a89 100644 --- a/include/crypto/internal/skcipher.h +++ b/include/crypto/internal/skcipher.h @@ -68,7 +68,7 @@ void skcipher_geniv_exit(struct crypto_tfm *tfm); int __init eseqiv_module_init(void); void __exit eseqiv_module_exit(void); int __init chainiv_module_init(void); -void __exit chainiv_module_exit(void); +void chainiv_module_exit(void); static inline struct crypto_ablkcipher *skcipher_geniv_cipher( struct crypto_ablkcipher *geniv) -- cgit v1.2.3-55-g7522 From 38332cb98772f5ea757e6486bed7ed0381cb5f98 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Tue, 4 Mar 2008 14:59:54 -0800 Subject: time: prevent the loop in timespec_add_ns() from being optimised away Since some architectures don't support __udivdi3(). Signed-off-by: Segher Boessenkool Cc: john stultz Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Thomas Gleixner --- include/linux/time.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/time.h b/include/linux/time.h index 2091a19f1655..d32ef0ad4c0a 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -174,6 +174,10 @@ static inline void timespec_add_ns(struct timespec *a, u64 ns) { ns += a->tv_nsec; while(unlikely(ns >= NSEC_PER_SEC)) { + /* The following asm() prevents the compiler from + * optimising this loop into a modulo operation. */ + asm("" : "+r"(ns)); + ns -= NSEC_PER_SEC; a->tv_sec++; } -- cgit v1.2.3-55-g7522 From 10a398d04c4a1fc395840f4d040493375f562302 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 4 Mar 2008 15:14:26 -0800 Subject: time: remove obsolete CLOCK_TICK_ADJUST The first version of the ntp_interval/tick_length inconsistent usage patch was recently merged as bbe4d18ac2e058c56adb0cd71f49d9ed3216a405 http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bbe4d18ac2e058c56adb0cd71f49d9ed3216a405 While the fix did greatly improve the situation, it was correctly pointed out by Roman that it does have a small bug: If the users change clocksources after the system has been running and NTP has made corrections, the correctoins made against the old clocksource will be applied against the new clocksource, causing error. The second attempt, which corrects the issue in the NTP_INTERVAL_LENGTH definition has also made it up-stream as commit e13a2e61dd5152f5499d2003470acf9c838eab84 http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e13a2e61dd5152f5499d2003470acf9c838eab84 Roman has correctly pointed out that CLOCK_TICK_ADJUST is calculated based on the PIT's frequency, and isn't really relevant to non-PIT driven clocksources (that is, clocksources other then jiffies and pit). This patch reverts both of those changes, and simply removes CLOCK_TICK_ADJUST. This does remove the granularity error correction for users of PIT and Jiffies clocksource users, but the granularity error but for the majority of users, it should be within the 500ppm range NTP can accommodate for. For systems that have granularity errors greater then 500ppm, the "ntp_tick_adj=" boot option can be used to compensate. [johnstul@us.ibm.com: provided changelog] [mattilinnanvuori@yahoo.com: maek ntp_tick_adj static] Signed-off-by: Roman Zippel Acked-by: john stultz Signed-off-by: Matti Linnanvuori Signed-off-by: Andrew Morton Cc: mingo@elte.hu Signed-off-by: Thomas Gleixner --- include/linux/timex.h | 9 +-------- kernel/time/ntp.c | 11 ++++++++++- kernel/time/timekeeping.c | 6 ++---- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/linux/timex.h b/include/linux/timex.h index c3f374786a43..8ea3e71ba7fa 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -232,14 +232,7 @@ static inline int ntp_synced(void) #else #define NTP_INTERVAL_FREQ (HZ) #endif - -#define CLOCK_TICK_OVERFLOW (LATCH * HZ - CLOCK_TICK_RATE) -#define CLOCK_TICK_ADJUST (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \ - (s64)CLOCK_TICK_RATE) - -/* Because using NSEC_PER_SEC would be too easy */ -#define NTP_INTERVAL_LENGTH ((((s64)TICK_USEC * NSEC_PER_USEC * USER_HZ) + \ - CLOCK_TICK_ADJUST) / NTP_INTERVAL_FREQ) +#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ) /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ extern u64 current_tick_length(void); diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index d4bca927f715..5fd9b9469770 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -42,12 +42,13 @@ long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */ long time_freq; /* frequency offset (scaled ppm)*/ static long time_reftime; /* time at last adjustment (s) */ long time_adjust; +static long ntp_tick_adj; static void ntp_update_frequency(void) { u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT; - second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT; + second_length += (s64)ntp_tick_adj << TICK_LENGTH_SHIFT; second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC); tick_length_base = second_length; @@ -402,3 +403,11 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0) notify_cmos_timer(); return(result); } + +static int __init ntp_tick_adj_setup(char *str) +{ + ntp_tick_adj = simple_strtol(str, NULL, 0); + return 1; +} + +__setup("ntp_tick_adj=", ntp_tick_adj_setup); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 1af9fb050fe2..671af612b768 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -187,8 +187,7 @@ static void change_clocksource(void) clock->error = 0; clock->xtime_nsec = 0; - clocksource_calculate_interval(clock, - (unsigned long)(current_tick_length()>>TICK_LENGTH_SHIFT)); + clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH); tick_clock_notify(); @@ -245,8 +244,7 @@ void __init timekeeping_init(void) ntp_clear(); clock = clocksource_get_next(); - clocksource_calculate_interval(clock, - (unsigned long)(current_tick_length()>>TICK_LENGTH_SHIFT)); + clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH); clock->cycle_last = clocksource_read(clock); xtime.tv_sec = sec; -- cgit v1.2.3-55-g7522 From fbab976d7ce4556d4212d554f766dae461d22e16 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 7 Mar 2008 08:57:54 -0600 Subject: firmware: provide stubs for the FW_LOADER=n case libsas has a case where it uses the firmware loader to provide services, but doesn't want to select it all the time. This currently causes a compile failure in libsas if FW_LOADER=n. Fix this by providing error stubs for the firmware loader API in the FW_LOADER=n case. Signed-off-by: James Bottomley Cc: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- include/linux/firmware.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'include') diff --git a/include/linux/firmware.h b/include/linux/firmware.h index 33d8f2087b6e..4d10c7328d2d 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -10,7 +10,10 @@ struct firmware { size_t size; u8 *data; }; + struct device; + +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) int request_firmware(const struct firmware **fw, const char *name, struct device *device); int request_firmware_nowait( @@ -19,4 +22,24 @@ int request_firmware_nowait( void (*cont)(const struct firmware *fw, void *context)); void release_firmware(const struct firmware *fw); +#else +static inline int request_firmware(const struct firmware **fw, + const char *name, + struct device *device) +{ + return -EINVAL; +} +static inline int request_firmware_nowait( + struct module *module, int uevent, + const char *name, struct device *device, void *context, + void (*cont)(const struct firmware *fw, void *context)) +{ + return -EINVAL; +} + +static inline void release_firmware(const struct firmware *fw) +{ +} +#endif + #endif -- cgit v1.2.3-55-g7522 From b5e85dee2a5433246d5b7488918a1a0ad22c046a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 10 Mar 2008 16:41:06 -0700 Subject: [NETFILTER]: nfnetlink: fix ifdef in nfnetlink_compat.h Use __KERNEL__ instead of __KERNEL to make sure the headers are not usable by the kernel. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nfnetlink_compat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/netfilter/nfnetlink_compat.h b/include/linux/netfilter/nfnetlink_compat.h index 02a42d875cf7..e1451760c9cd 100644 --- a/include/linux/netfilter/nfnetlink_compat.h +++ b/include/linux/netfilter/nfnetlink_compat.h @@ -1,6 +1,6 @@ #ifndef _NFNETLINK_COMPAT_H #define _NFNETLINK_COMPAT_H -#ifndef __KERNEL +#ifndef __KERNEL__ /* Old nfnetlink macros for userspace */ /* nfnetlink groups: Up to 32 maximum */ -- cgit v1.2.3-55-g7522 From e61062587d0484c3852e822e844416c728362438 Mon Sep 17 00:00:00 2001 From: Robert P. J. Day Date: Fri, 7 Mar 2008 11:02:00 -0500 Subject: USB: g_printer.h does not need to be "unifdef"ed. Since the header file g_printer.h doesn't depend on __KERNEL__, there's no need to unifdef it in the Kbuild file. Signed-off-by: Robert P. J. Day Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/Kbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild index b8cba1dcb2c6..42e84fc315e3 100644 --- a/include/linux/usb/Kbuild +++ b/include/linux/usb/Kbuild @@ -3,5 +3,5 @@ header-y += cdc.h header-y += ch9.h header-y += gadgetfs.h header-y += midi.h -unifdef-y += g_printer.h +header-y += g_printer.h -- cgit v1.2.3-55-g7522 From 20f590df4fbb962d1f8fcb12c4b4e790c7054045 Mon Sep 17 00:00:00 2001 From: Robert P. J. Day Date: Fri, 7 Mar 2008 11:40:07 -0500 Subject: USB: Remove __KERNEL__ check from non-exported gadget.h. Since the header file gadget.h isn't being exported to userspace, there seems to be little point having a __KERNEL__ proprocessor check. Signed-off-by: Robert P. J. Day Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/gadget.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include') diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index aa3047ff00d1..f3295296b435 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -15,8 +15,6 @@ #ifndef __LINUX_USB_GADGET_H #define __LINUX_USB_GADGET_H -#ifdef __KERNEL__ - struct usb_ep; /** @@ -848,6 +846,4 @@ extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *, extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit; -#endif /* __KERNEL__ */ - #endif /* __LINUX_USB_GADGET_H */ -- cgit v1.2.3-55-g7522 From 019f692ea719a2da17606511d2648b8cc1762268 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 10 Mar 2008 16:43:41 -0700 Subject: [NETFILTER]: nf_conntrack: replace horrible hack with ksize() There's a horrible slab abuse in net/netfilter/nf_conntrack_extend.c that can be replaced with a call to ksize(). Cc: Christoph Lameter Signed-off-by: Pekka Enberg Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_extend.h | 1 - net/netfilter/nf_conntrack_extend.c | 19 +++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 49aac6323fbe..f736e842977f 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -17,7 +17,6 @@ enum nf_ct_ext_id struct nf_ct_ext { u8 offset[NF_CT_EXT_NUM]; u8 len; - u8 real_len; char data[0]; }; diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 8b9be1e978cd..2bd9963b5b3e 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -19,14 +19,6 @@ static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM]; static DEFINE_MUTEX(nf_ct_ext_type_mutex); -/* Horrible trick to figure out smallest amount worth kmallocing. */ -#define CACHE(x) (x) + 0 * -enum { - NF_CT_EXT_MIN_SIZE = -#include - 1 }; -#undef CACHE - void __nf_ct_ext_destroy(struct nf_conn *ct) { unsigned int i; @@ -53,7 +45,7 @@ EXPORT_SYMBOL(__nf_ct_ext_destroy); static void * nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp) { - unsigned int off, len, real_len; + unsigned int off, len; struct nf_ct_ext_type *t; rcu_read_lock(); @@ -61,16 +53,14 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp) BUG_ON(t == NULL); off = ALIGN(sizeof(struct nf_ct_ext), t->align); len = off + t->len; - real_len = t->alloc_size; rcu_read_unlock(); - *ext = kzalloc(real_len, gfp); + *ext = kzalloc(t->alloc_size, gfp); if (!*ext) return NULL; (*ext)->offset[id] = off; (*ext)->len = len; - (*ext)->real_len = real_len; return (void *)(*ext) + off; } @@ -95,7 +85,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) newlen = newoff + t->len; rcu_read_unlock(); - if (newlen >= ct->ext->real_len) { + if (newlen >= ksize(ct->ext)) { new = kmalloc(newlen, gfp); if (!new) return NULL; @@ -114,7 +104,6 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) rcu_read_unlock(); } kfree(ct->ext); - new->real_len = newlen; ct->ext = new; } @@ -156,8 +145,6 @@ static void update_alloc_size(struct nf_ct_ext_type *type) t1->alloc_size = ALIGN(t1->alloc_size, t2->align) + t2->len; } - if (t1->alloc_size < NF_CT_EXT_MIN_SIZE) - t1->alloc_size = NF_CT_EXT_MIN_SIZE; } } -- cgit v1.2.3-55-g7522 From 9f9351bbe34a9b12966b1fb6f7c21cfe128340c1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Mar 2008 11:43:34 -0700 Subject: rename DECLARE_PCI_DEVICE_TABLE to DEFINE_PCI_DEVICE_TABLE This macro is used to define tables, not to declare them. Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/pci.txt | 4 ++-- include/linux/pci.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/Documentation/pci.txt b/Documentation/pci.txt index bb7bd27d4682..d2c2e6e2b224 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -123,7 +123,7 @@ initialization with a pointer to a structure describing the driver The ID table is an array of struct pci_device_id entries ending with an -all-zero entry; use of the macro DECLARE_PCI_DEVICE_TABLE is the preferred +all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred method of declaring the table. Each entry consists of: vendor,device Vendor and device ID to match (or PCI_ANY_ID) @@ -193,7 +193,7 @@ Tips on when/where to use the above attributes: o Do not mark the struct pci_driver. o The ID table array should be marked __devinitconst; this is done - automatically if the table is declared with DECLARE_PCI_DEVICE_TABLE(). + automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE(). o The probe() and remove() functions should be marked __devinit and __devexit respectively. All initialization functions diff --git a/include/linux/pci.h b/include/linux/pci.h index f3165e7ac431..38eff1947750 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -389,13 +389,13 @@ struct pci_driver { #define to_pci_driver(drv) container_of(drv, struct pci_driver, driver) /** - * DECLARE_PCI_DEVICE_TABLE - macro used to describe a pci device table + * DEFINE_PCI_DEVICE_TABLE - macro used to describe a pci device table * @_table: device table name * * This macro is used to create a struct pci_device_id array (a device table) * in a generic manner. */ -#define DECLARE_PCI_DEVICE_TABLE(_table) \ +#define DEFINE_PCI_DEVICE_TABLE(_table) \ const struct pci_device_id _table[] __devinitconst /** -- cgit v1.2.3-55-g7522 From e1f19995f55294fbb00ea22ba85d7b0d80ba3813 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Mon, 10 Mar 2008 11:43:37 -0700 Subject: memstick: introduce correct definitions in the header Thanks to some input from kind people at JMicron it is now possible to have more correct definitions of protocol structures and bit field semantics. Signed-off-by: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/memstick/core/memstick.c | 4 +- drivers/memstick/core/mspro_block.c | 16 ++--- drivers/memstick/host/tifm_ms.c | 19 +++--- include/linux/memstick.h | 130 ++++++++++++++++++++++++------------ 4 files changed, 105 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index bba467fe4bce..5e0e960df456 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -271,7 +271,7 @@ void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, mrq->data_dir = READ; mrq->sg = *sg; - mrq->io_type = MEMSTICK_IO_SG; + mrq->long_data = 1; if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD) mrq->need_card_int = 1; @@ -306,7 +306,7 @@ void memstick_init_req(struct memstick_request *mrq, unsigned char tpc, if (mrq->data_dir == WRITE) memcpy(mrq->data, buf, mrq->data_len); - mrq->io_type = MEMSTICK_IO_VAL; + mrq->long_data = 0; if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD) mrq->need_card_int = 1; diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 423ad8cf4bb9..214211c8ac9a 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -629,7 +629,7 @@ static void mspro_block_process_request(struct memstick_dev *card, param.system = msb->system; param.data_count = cpu_to_be16(page_count); param.data_address = cpu_to_be32((uint32_t)t_sec); - param.cmd_param = 0; + param.tpc_param = 0; msb->data_dir = rq_data_dir(req); msb->transfer_cmd = msb->data_dir == READ @@ -761,7 +761,7 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card) .system = 0, .data_count = 0, .data_address = 0, - .cmd_param = 0 + .tpc_param = 0 }; card->next_request = h_mspro_block_req_init; @@ -773,8 +773,8 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card) if (card->current_mrq.error) return card->current_mrq.error; - msb->system = 0; - host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PARALLEL); + msb->system = MEMSTICK_SYS_PAR4; + host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); card->next_request = h_mspro_block_req_init; msb->mrq_handler = h_mspro_block_default; @@ -802,7 +802,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) .system = msb->system, .data_count = cpu_to_be16(1), .data_address = 0, - .cmd_param = 0 + .tpc_param = 0 }; struct mspro_attribute *attr = NULL; struct mspro_sys_attr *s_attr = NULL; @@ -922,7 +922,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) param.system = msb->system; param.data_count = cpu_to_be16((rc / msb->page_size) + 1); param.data_address = cpu_to_be32(addr / msb->page_size); - param.cmd_param = 0; + param.tpc_param = 0; sg_init_one(&msb->req_sg[0], buffer, be16_to_cpu(param.data_count) * msb->page_size); @@ -964,7 +964,7 @@ static int mspro_block_init_card(struct memstick_dev *card) struct memstick_host *host = card->host; int rc = 0; - msb->system = 0x80; + msb->system = MEMSTICK_SYS_SERIAL; card->reg_addr.r_offset = offsetof(struct mspro_register, status); card->reg_addr.r_length = sizeof(struct ms_status_register); card->reg_addr.w_offset = offsetof(struct mspro_register, param); @@ -973,7 +973,7 @@ static int mspro_block_init_card(struct memstick_dev *card) if (memstick_set_rw_addr(card)) return -EIO; - if (host->caps & MEMSTICK_CAP_PARALLEL) { + if (host->caps & MEMSTICK_CAP_PAR4) { if (mspro_block_switch_to_parallel(card)) printk(KERN_WARNING "%s: could not switch to " "parallel interface\n", card->dev.bus_id); diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 4fb24215bd95..5b5bd61b3a4a 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -209,7 +209,7 @@ static int tifm_ms_issue_cmd(struct tifm_ms *host) host->cmd_flags = 0; - if (host->req->io_type == MEMSTICK_IO_SG) { + if (host->req->long_data) { if (!host->no_dma) { if (1 != tifm_map_sg(sock, &host->req->sg, 1, host->req->data_dir == READ @@ -248,7 +248,7 @@ static int tifm_ms_issue_cmd(struct tifm_ms *host) cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM); cmd_mask |= TIFM_MS_SYS_DATA | TIFM_MS_SYS_NOT_RDY; writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); - } else if (host->req->io_type == MEMSTICK_IO_VAL) { + } else { data = host->req->data; data_len = host->req->data_len; @@ -294,8 +294,7 @@ static int tifm_ms_issue_cmd(struct tifm_ms *host) cmd_mask |= TIFM_MS_SYS_NOT_RDY; dev_dbg(&sock->dev, "mask %x\n", cmd_mask); writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); - } else - BUG(); + } mod_timer(&host->timer, jiffies + host->timeout_jiffies); writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), @@ -319,13 +318,13 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host) int rc; del_timer(&host->timer); - if (host->req->io_type == MEMSTICK_IO_SG) { + if (host->req->long_data) { if (!host->no_dma) tifm_unmap_sg(sock, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - } else if (host->req->io_type == MEMSTICK_IO_VAL) { + } else { writel(~TIFM_MS_SYS_DATA & readl(sock->addr + SOCK_MS_SYSTEM), sock->addr + SOCK_MS_SYSTEM); @@ -365,7 +364,7 @@ static int tifm_ms_check_status(struct tifm_ms *host) if (!host->req->error) { if (!(host->cmd_flags & CMD_READY)) return 1; - if ((host->req->io_type == MEMSTICK_IO_SG) + if (host->req->long_data && !(host->cmd_flags & FIFO_READY)) return 1; if (host->req->need_card_int @@ -505,7 +504,7 @@ static void tifm_ms_set_param(struct memstick_host *msh, writel((~TIFM_CTRL_FAST_CLK) & readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); - } else if (value == MEMSTICK_PARALLEL) { + } else if (value == MEMSTICK_PAR4) { host->mode_mask = 0; writel(TIFM_CTRL_FAST_CLK | readl(sock->addr + SOCK_CONTROL), @@ -542,7 +541,7 @@ static int tifm_ms_initialize_host(struct tifm_ms *host) writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM); writel(0xffffffff, sock->addr + SOCK_MS_STATUS); if (tifm_has_ms_pif(sock)) - msh->caps |= MEMSTICK_CAP_PARALLEL; + msh->caps |= MEMSTICK_CAP_PAR4; return 0; } @@ -601,7 +600,7 @@ static void tifm_ms_remove(struct tifm_dev *sock) writel(TIFM_FIFO_INT_SETALL, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); - if ((host->req->io_type == MEMSTICK_IO_SG) && !host->no_dma) + if (host->req->long_data && !host->no_dma) tifm_unmap_sg(sock, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_TODEVICE diff --git a/include/linux/memstick.h b/include/linux/memstick.h index 334d059d6794..c104e722de06 100644 --- a/include/linux/memstick.h +++ b/include/linux/memstick.h @@ -22,6 +22,8 @@ struct ms_status_register { unsigned char reserved; unsigned char interrupt; #define MEMSTICK_INT_CMDNAK 0x0001 +#define MEMSTICK_INT_IOREQ 0x0008 +#define MEMSTICK_INT_IOBREQ 0x0010 #define MEMSTICK_INT_BREQ 0x0020 #define MEMSTICK_INT_ERR 0x0040 #define MEMSTICK_INT_CED 0x0080 @@ -47,13 +49,17 @@ struct ms_status_register { struct ms_id_register { unsigned char type; - unsigned char reserved; + unsigned char if_mode; unsigned char category; unsigned char class; } __attribute__((packed)); struct ms_param_register { unsigned char system; +#define MEMSTICK_SYS_ATEN 0xc0 +#define MEMSTICK_SYS_BAMD 0x80 +#define MEMSTICK_SYS_PAM 0x08 + unsigned char block_address_msb; unsigned short block_address; unsigned char cp; @@ -90,16 +96,48 @@ struct ms_register { struct mspro_param_register { unsigned char system; +#define MEMSTICK_SYS_SERIAL 0x80 +#define MEMSTICK_SYS_PAR4 0x00 +#define MEMSTICK_SYS_PAR8 0x40 + + unsigned short data_count; + unsigned int data_address; + unsigned char tpc_param; +} __attribute__((packed)); + +struct mspro_io_info_register { + unsigned char version; + unsigned char io_category; + unsigned char current_req; + unsigned char card_opt_info; + unsigned char rdy_wait_time; +} __attribute__((packed)); + +struct mspro_io_func_register { + unsigned char func_enable; + unsigned char func_select; + unsigned char func_intmask; + unsigned char transfer_mode; +} __attribute__((packed)); + +struct mspro_io_cmd_register { + unsigned short tpc_param; unsigned short data_count; unsigned int data_address; - unsigned char cmd_param; } __attribute__((packed)); struct mspro_register { - struct ms_status_register status; - struct ms_id_register id; - unsigned char reserved[8]; - struct mspro_param_register param; + struct ms_status_register status; + struct ms_id_register id; + unsigned char reserved0[8]; + struct mspro_param_register param; + unsigned char reserved1[8]; + struct mspro_io_info_register io_info; + struct mspro_io_func_register io_func; + unsigned char reserved2[7]; + struct mspro_io_cmd_register io_cmd; + unsigned char io_int; + unsigned char io_int_func; } __attribute__((packed)); struct ms_register_addr { @@ -110,49 +148,55 @@ struct ms_register_addr { } __attribute__((packed)); enum { + MS_TPC_READ_MG_STATUS = 0x01, MS_TPC_READ_LONG_DATA = 0x02, MS_TPC_READ_SHORT_DATA = 0x03, + MS_TPC_READ_MG_DATA = 0x03, MS_TPC_READ_REG = 0x04, - MS_TPC_READ_IO_DATA = 0x05, /* unverified */ + MS_TPC_READ_QUAD_DATA = 0x05, + MS_TPC_READ_IO_DATA = 0x05, MS_TPC_GET_INT = 0x07, MS_TPC_SET_RW_REG_ADRS = 0x08, MS_TPC_EX_SET_CMD = 0x09, - MS_TPC_WRITE_IO_DATA = 0x0a, /* unverified */ + MS_TPC_WRITE_QUAD_DATA = 0x0a, + MS_TPC_WRITE_IO_DATA = 0x0a, MS_TPC_WRITE_REG = 0x0b, MS_TPC_WRITE_SHORT_DATA = 0x0c, + MS_TPC_WRITE_MG_DATA = 0x0c, MS_TPC_WRITE_LONG_DATA = 0x0d, MS_TPC_SET_CMD = 0x0e }; enum { - MS_CMD_BLOCK_END = 0x33, - MS_CMD_RESET = 0x3c, - MS_CMD_BLOCK_WRITE = 0x55, - MS_CMD_SLEEP = 0x5a, - MS_CMD_BLOCK_ERASE = 0x99, - MS_CMD_BLOCK_READ = 0xaa, - MS_CMD_CLEAR_BUF = 0xc3, - MS_CMD_FLASH_STOP = 0xcc, - MSPRO_CMD_FORMAT = 0x10, - MSPRO_CMD_SLEEP = 0x11, - MSPRO_CMD_READ_DATA = 0x20, - MSPRO_CMD_WRITE_DATA = 0x21, - MSPRO_CMD_READ_ATRB = 0x24, - MSPRO_CMD_STOP = 0x25, - MSPRO_CMD_ERASE = 0x26, - MSPRO_CMD_SET_IBA = 0x46, - MSPRO_CMD_SET_IBD = 0x47 -/* - MSPRO_CMD_RESET - MSPRO_CMD_WAKEUP - MSPRO_CMD_IN_IO_DATA - MSPRO_CMD_OUT_IO_DATA - MSPRO_CMD_READ_IO_ATRB - MSPRO_CMD_IN_IO_FIFO - MSPRO_CMD_OUT_IO_FIFO - MSPRO_CMD_IN_IOM - MSPRO_CMD_OUT_IOM -*/ + MS_CMD_BLOCK_END = 0x33, + MS_CMD_RESET = 0x3c, + MS_CMD_BLOCK_WRITE = 0x55, + MS_CMD_SLEEP = 0x5a, + MS_CMD_BLOCK_ERASE = 0x99, + MS_CMD_BLOCK_READ = 0xaa, + MS_CMD_CLEAR_BUF = 0xc3, + MS_CMD_FLASH_STOP = 0xcc, + MS_CMD_LOAD_ID = 0x60, + MS_CMD_CMP_ICV = 0x7f, + MSPRO_CMD_FORMAT = 0x10, + MSPRO_CMD_SLEEP = 0x11, + MSPRO_CMD_WAKEUP = 0x12, + MSPRO_CMD_READ_DATA = 0x20, + MSPRO_CMD_WRITE_DATA = 0x21, + MSPRO_CMD_READ_ATRB = 0x24, + MSPRO_CMD_STOP = 0x25, + MSPRO_CMD_ERASE = 0x26, + MSPRO_CMD_READ_QUAD = 0x27, + MSPRO_CMD_WRITE_QUAD = 0x28, + MSPRO_CMD_SET_IBD = 0x46, + MSPRO_CMD_GET_IBD = 0x47, + MSPRO_CMD_IN_IO_DATA = 0xb0, + MSPRO_CMD_OUT_IO_DATA = 0xb1, + MSPRO_CMD_READ_IO_ATRB = 0xb2, + MSPRO_CMD_IN_IO_FIFO = 0xb3, + MSPRO_CMD_OUT_IO_FIFO = 0xb4, + MSPRO_CMD_IN_IOM = 0xb5, + MSPRO_CMD_OUT_IOM = 0xb6, }; /*** Driver structures and functions ***/ @@ -165,7 +209,8 @@ enum memstick_param { MEMSTICK_POWER = 1, MEMSTICK_INTERFACE }; #define MEMSTICK_POWER_ON 1 #define MEMSTICK_SERIAL 0 -#define MEMSTICK_PARALLEL 1 +#define MEMSTICK_PAR4 1 +#define MEMSTICK_PAR8 2 struct memstick_host; struct memstick_driver; @@ -195,11 +240,7 @@ struct memstick_request { unsigned char data_dir:1, need_card_int:1, get_int_reg:1, - io_type:2; -#define MEMSTICK_IO_NONE 0 -#define MEMSTICK_IO_VAL 1 -#define MEMSTICK_IO_SG 2 - + long_data:1; unsigned char int_reg; int error; union { @@ -231,8 +272,9 @@ struct memstick_host { struct mutex lock; unsigned int id; unsigned int caps; -#define MEMSTICK_CAP_PARALLEL 1 -#define MEMSTICK_CAP_AUTO_GET_INT 2 +#define MEMSTICK_CAP_AUTO_GET_INT 1 +#define MEMSTICK_CAP_PAR4 2 +#define MEMSTICK_CAP_PAR8 4 struct work_struct media_checker; struct class_device cdev; -- cgit v1.2.3-55-g7522 From d114ad54ffb020dc781b6159c1c2f391c6ec418f Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Mon, 10 Mar 2008 11:43:38 -0700 Subject: memstick: add memstick_suspend/resume_host methods Bus driver may need to be informed that host is being suspended/resumed. Signed-off-by: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/memstick/core/memstick.c | 25 +++++++++++++++++++++++++ drivers/memstick/host/tifm_ms.c | 8 ++++---- include/linux/memstick.h | 2 ++ 3 files changed, 31 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index 5e0e960df456..3c97bac4e47b 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -561,6 +561,31 @@ void memstick_free_host(struct memstick_host *host) } EXPORT_SYMBOL(memstick_free_host); +/** + * memstick_suspend_host - notify bus driver of host suspension + * @host - host to use + */ +void memstick_suspend_host(struct memstick_host *host) +{ + mutex_lock(&host->lock); + host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); + mutex_unlock(&host->lock); +} +EXPORT_SYMBOL(memstick_suspend_host); + +/** + * memstick_resume_host - notify bus driver of host resumption + * @host - host to use + */ +void memstick_resume_host(struct memstick_host *host) +{ + mutex_lock(&host->lock); + host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); + mutex_unlock(&host->lock); + memstick_detect_change(host); +} +EXPORT_SYMBOL(memstick_resume_host); + int memstick_register_driver(struct memstick_driver *drv) { drv->driver.bus = &memstick_bus_type; diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 5b5bd61b3a4a..8b1c102fc317 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -627,17 +627,17 @@ static void tifm_ms_remove(struct tifm_dev *sock) static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state) { + struct memstick_host *msh = tifm_get_drvdata(sock); + + memstick_suspend_host(msh); return 0; } static int tifm_ms_resume(struct tifm_dev *sock) { struct memstick_host *msh = tifm_get_drvdata(sock); - struct tifm_ms *host = memstick_priv(msh); - - tifm_ms_initialize_host(host); - memstick_detect_change(msh); + memstick_resume_host(msh); return 0; } diff --git a/include/linux/memstick.h b/include/linux/memstick.h index c104e722de06..b7ee25888836 100644 --- a/include/linux/memstick.h +++ b/include/linux/memstick.h @@ -312,6 +312,8 @@ int memstick_add_host(struct memstick_host *host); void memstick_remove_host(struct memstick_host *host); void memstick_free_host(struct memstick_host *host); void memstick_detect_change(struct memstick_host *host); +void memstick_suspend_host(struct memstick_host *host); +void memstick_resume_host(struct memstick_host *host); void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, struct scatterlist *sg); -- cgit v1.2.3-55-g7522 From 92b22d935fed1e4d88b9b6f9a674ab2a4272ee78 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Mon, 10 Mar 2008 11:43:40 -0700 Subject: tifm: fix the MemoryStick host fifo handling code Additional input received from JMicron on MemoryStick host interfaces showed that some assumtions in fifo handling code were incorrect. This patch also fixes data corruption used to occure during PIO transfers. Signed-off-by: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/memstick/host/tifm_ms.c | 524 ++++++++++++++++++++-------------------- include/linux/tifm.h | 2 +- 2 files changed, 264 insertions(+), 262 deletions(-) (limited to 'include') diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index c62e709ca771..b88f5b30efbf 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -24,275 +24,289 @@ static int no_dma; module_param(no_dma, bool, 0644); -#define TIFM_MS_TIMEOUT 0x00100 -#define TIFM_MS_BADCRC 0x00200 -#define TIFM_MS_EOTPC 0x01000 -#define TIFM_MS_INT 0x02000 - -/* The meaning of the bit majority in this constant is unknown. */ -#define TIFM_MS_SERIAL 0x04010 +/* + * Some control bits of TIFM appear to conform to Sony's reference design, + * so I'm just assuming they all are. + */ -#define TIFM_MS_SYS_LATCH 0x00100 -#define TIFM_MS_SYS_NOT_RDY 0x00800 -#define TIFM_MS_SYS_DATA 0x10000 +#define TIFM_MS_STAT_DRQ 0x04000 +#define TIFM_MS_STAT_MSINT 0x02000 +#define TIFM_MS_STAT_RDY 0x01000 +#define TIFM_MS_STAT_CRC 0x00200 +#define TIFM_MS_STAT_TOE 0x00100 +#define TIFM_MS_STAT_EMP 0x00020 +#define TIFM_MS_STAT_FUL 0x00010 +#define TIFM_MS_STAT_CED 0x00008 +#define TIFM_MS_STAT_ERR 0x00004 +#define TIFM_MS_STAT_BRQ 0x00002 +#define TIFM_MS_STAT_CNK 0x00001 + +#define TIFM_MS_SYS_DMA 0x10000 +#define TIFM_MS_SYS_RESET 0x08000 +#define TIFM_MS_SYS_SRAC 0x04000 +#define TIFM_MS_SYS_INTEN 0x02000 +#define TIFM_MS_SYS_NOCRC 0x01000 +#define TIFM_MS_SYS_INTCLR 0x00800 +#define TIFM_MS_SYS_MSIEN 0x00400 +#define TIFM_MS_SYS_FCLR 0x00200 +#define TIFM_MS_SYS_FDIR 0x00100 +#define TIFM_MS_SYS_DAM 0x00080 +#define TIFM_MS_SYS_DRM 0x00040 +#define TIFM_MS_SYS_DRQSL 0x00020 +#define TIFM_MS_SYS_REI 0x00010 +#define TIFM_MS_SYS_REO 0x00008 +#define TIFM_MS_SYS_BSY_MASK 0x00007 + +#define TIFM_MS_SYS_FIFO (TIFM_MS_SYS_INTEN | TIFM_MS_SYS_MSIEN \ + | TIFM_MS_SYS_FCLR | TIFM_MS_SYS_BSY_MASK) /* Hardware flags */ enum { - CMD_READY = 0x0001, - FIFO_READY = 0x0002, - CARD_READY = 0x0004, - DATA_CARRY = 0x0008 + CMD_READY = 0x01, + FIFO_READY = 0x02, + CARD_INT = 0x04 }; struct tifm_ms { struct tifm_dev *dev; - unsigned short eject:1, - no_dma:1; - unsigned short cmd_flags; + struct timer_list timer; + struct memstick_request *req; unsigned int mode_mask; unsigned int block_pos; unsigned long timeout_jiffies; - - struct timer_list timer; - struct memstick_request *req; + unsigned char eject:1, + use_dma:1; + unsigned char cmd_flags; + unsigned char io_pos; unsigned int io_word; }; -static void tifm_ms_read_fifo(struct tifm_ms *host, unsigned int fifo_offset, - struct page *pg, unsigned int page_off, - unsigned int length) +static unsigned int tifm_ms_read_data(struct tifm_ms *host, + unsigned char *buf, unsigned int length) { struct tifm_dev *sock = host->dev; - unsigned int cnt = 0, off = 0; - unsigned char *buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + page_off; + unsigned int off = 0; + + while (host->io_pos && length) { + buf[off++] = host->io_word & 0xff; + host->io_word >>= 8; + length--; + host->io_pos--; + } + + if (!length) + return off; + + while (!(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) { + if (length < 4) + break; + *(unsigned int *)(buf + off) = __raw_readl(sock->addr + + SOCK_MS_DATA); + length -= 4; + off += 4; + } - if (host->cmd_flags & DATA_CARRY) { - while ((fifo_offset & 3) && length) { + if (length + && !(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) { + host->io_word = readl(sock->addr + SOCK_MS_DATA); + for (host->io_pos = 4; host->io_pos; --host->io_pos) { buf[off++] = host->io_word & 0xff; host->io_word >>= 8; length--; - fifo_offset++; + if (!length) + break; } - if (!(fifo_offset & 3)) - host->cmd_flags &= ~DATA_CARRY; - if (!length) - return; } - do { - host->io_word = readl(sock->addr + SOCK_FIFO_ACCESS - + fifo_offset); - cnt = 4; - while (length && cnt) { - buf[off++] = (host->io_word >> 8) & 0xff; - cnt--; - length--; - } - fifo_offset += 4 - cnt; - } while (length); - - if (cnt) - host->cmd_flags |= DATA_CARRY; - - kunmap_atomic(buf - page_off, KM_BIO_DST_IRQ); + return off; } -static void tifm_ms_write_fifo(struct tifm_ms *host, unsigned int fifo_offset, - struct page *pg, unsigned int page_off, - unsigned int length) +static unsigned int tifm_ms_write_data(struct tifm_ms *host, + unsigned char *buf, unsigned int length) { struct tifm_dev *sock = host->dev; - unsigned int cnt = 0, off = 0; - unsigned char *buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + page_off; + unsigned int off = 0; - if (host->cmd_flags & DATA_CARRY) { - while (fifo_offset & 3) { - host->io_word |= buf[off++] << (8 * (fifo_offset & 3)); + if (host->io_pos) { + while (host->io_pos < 4 && length) { + host->io_word |= buf[off++] << (host->io_pos * 8); + host->io_pos++; length--; - fifo_offset++; - } - if (!(fifo_offset & 3)) { - writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS - + fifo_offset - 4); - - host->cmd_flags &= ~DATA_CARRY; } - if (!length) - return; } - do { - cnt = 4; + if (host->io_pos == 4 + && !(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) { + writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + writel(host->io_word, sock->addr + SOCK_MS_DATA); + host->io_pos = 0; host->io_word = 0; - while (length && cnt) { - host->io_word |= buf[off++] << (4 - cnt); - cnt--; - length--; - } - fifo_offset += 4 - cnt; - if (!cnt) - writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS - + fifo_offset - 4); - - } while (length); - - if (cnt) - host->cmd_flags |= DATA_CARRY; + } else if (host->io_pos) { + return off; + } - kunmap_atomic(buf - page_off, KM_BIO_SRC_IRQ); -} + if (!length) + return off; -static void tifm_ms_move_block(struct tifm_ms *host, unsigned int length) -{ - unsigned int t_size; - unsigned int off = host->req->sg.offset + host->block_pos; - unsigned int p_off, p_cnt; - struct page *pg; - unsigned long flags; + while (!(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) { + if (length < 4) + break; + writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + __raw_writel(*(unsigned int *)(buf + off), + sock->addr + SOCK_MS_DATA); + length -= 4; + off += 4; + } - dev_dbg(&host->dev->dev, "moving block\n"); - local_irq_save(flags); - t_size = length; - while (t_size) { - pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT); - p_off = offset_in_page(off); - p_cnt = PAGE_SIZE - p_off; - p_cnt = min(p_cnt, t_size); + switch (length) { + case 3: + host->io_word |= buf[off + 2] << 16; + host->io_pos++; + case 2: + host->io_word |= buf[off + 1] << 8; + host->io_pos++; + case 1: + host->io_word |= buf[off]; + host->io_pos++; + } - if (host->req->data_dir == WRITE) - tifm_ms_write_fifo(host, length - t_size, - pg, p_off, p_cnt); - else - tifm_ms_read_fifo(host, length - t_size, - pg, p_off, p_cnt); + off += host->io_pos; - t_size -= p_cnt; - } - local_irq_restore(flags); + return off; } -static int tifm_ms_transfer_data(struct tifm_ms *host, int skip) +static unsigned int tifm_ms_transfer_data(struct tifm_ms *host) { struct tifm_dev *sock = host->dev; - unsigned int length = host->req->sg.length - host->block_pos; + unsigned int length; + unsigned int off; + unsigned int t_size, p_off, p_cnt; + unsigned char *buf; + struct page *pg; + unsigned long flags = 0; - if (!length) - return 1; + if (host->req->long_data) { + length = host->req->sg.length - host->block_pos; + off = host->req->sg.offset + host->block_pos; + } else { + length = host->req->data_len - host->block_pos; + off = 0; + } + dev_dbg(&sock->dev, "fifo data transfer, %d, %d\n", length, + host->block_pos); + + while (length) { + if (host->req->long_data) { + pg = nth_page(sg_page(&host->req->sg), + off >> PAGE_SHIFT); + p_off = offset_in_page(off); + p_cnt = PAGE_SIZE - p_off; + p_cnt = min(p_cnt, length); + + local_irq_save(flags); + buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off; + } else { + buf = host->req->data + host->block_pos; + p_cnt = host->req->data_len - host->block_pos; + } - if (length > TIFM_FIFO_SIZE) - length = TIFM_FIFO_SIZE; + t_size = host->req->data_dir == WRITE + ? tifm_ms_write_data(host, buf, p_cnt) + : tifm_ms_read_data(host, buf, p_cnt); - if (!skip) { - tifm_ms_move_block(host, length); - host->block_pos += length; - } + if (host->req->long_data) { + kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ); + local_irq_restore(flags); + } - if ((host->req->data_dir == READ) - && (host->block_pos == host->req->sg.length)) - return 1; + if (!t_size) + break; + host->block_pos += t_size; + length -= t_size; + off += t_size; + } - writel(ilog2(length) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE); - if (host->req->data_dir == WRITE) - writel((1 << 8) | TIFM_DMA_TX, sock->addr + SOCK_DMA_CONTROL); - else - writel((1 << 8), sock->addr + SOCK_DMA_CONTROL); + dev_dbg(&sock->dev, "fifo data transfer, %d remaining\n", length); + if (!length && (host->req->data_dir == WRITE)) { + if (host->io_pos) { + writel(TIFM_MS_SYS_FDIR + | readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + writel(host->io_word, sock->addr + SOCK_MS_DATA); + } + writel(TIFM_MS_SYS_FDIR + | readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + writel(0, sock->addr + SOCK_MS_DATA); + } else { + readl(sock->addr + SOCK_MS_DATA); + } - return 0; + return length; } static int tifm_ms_issue_cmd(struct tifm_ms *host) { struct tifm_dev *sock = host->dev; unsigned char *data; - unsigned int data_len = 0, cmd = 0, cmd_mask = 0, cnt, tval = 0; + unsigned int data_len, cmd, sys_param; + host->cmd_flags = 0; + host->block_pos = 0; + host->io_pos = 0; + host->io_word = 0; host->cmd_flags = 0; - if (host->req->long_data) { - if (!host->no_dma) { - if (1 != tifm_map_sg(sock, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE)) { - host->req->error = -ENOMEM; - return host->req->error; - } - data_len = sg_dma_len(&host->req->sg); - } else - data_len = host->req->sg.length; - - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(TIFM_FIFO_ENABLE, - sock->addr + SOCK_FIFO_CONTROL); - writel(TIFM_FIFO_INTMASK, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); + data = host->req->data; - if (!host->no_dma) { - writel(ilog2(data_len) - 2, - sock->addr + SOCK_FIFO_PAGE_SIZE); - writel(sg_dma_address(&host->req->sg), - sock->addr + SOCK_DMA_ADDRESS); - if (host->req->data_dir == WRITE) - writel((1 << 8) | TIFM_DMA_TX | TIFM_DMA_EN, - sock->addr + SOCK_DMA_CONTROL); - else - writel((1 << 8) | TIFM_DMA_EN, - sock->addr + SOCK_DMA_CONTROL); - } else { - tifm_ms_transfer_data(host, - host->req->data_dir == READ); - } + host->use_dma = !no_dma; - cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM); - cmd_mask |= TIFM_MS_SYS_DATA | TIFM_MS_SYS_NOT_RDY; - writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); + if (host->req->long_data) { + data_len = host->req->sg.length; + if (!is_power_of_2(data_len)) + host->use_dma = 0; } else { - data = host->req->data; data_len = host->req->data_len; + host->use_dma = 0; + } - cmd_mask = host->mode_mask | 0x2607; /* unknown constant */ - - if (host->req->data_dir == WRITE) { - cmd_mask |= TIFM_MS_SYS_LATCH; - writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); - for (cnt = 0; (data_len - cnt) >= 4; cnt += 4) { - writel(TIFM_MS_SYS_LATCH - | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - __raw_writel(*(unsigned int *)(data + cnt), - sock->addr + SOCK_MS_DATA); - dev_dbg(&sock->dev, "writing %x\n", - *(int *)(data + cnt)); - } - switch (data_len - cnt) { - case 3: - tval |= data[cnt + 2] << 16; - case 2: - tval |= data[cnt + 1] << 8; - case 1: - tval |= data[cnt]; - writel(TIFM_MS_SYS_LATCH - | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel(tval, sock->addr + SOCK_MS_DATA); - dev_dbg(&sock->dev, "writing %x\n", tval); - } + writel(TIFM_FIFO_INT_SETALL, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); + writel(TIFM_FIFO_ENABLE, + sock->addr + SOCK_FIFO_CONTROL); + + if (host->use_dma) { + if (1 != tifm_map_sg(sock, &host->req->sg, 1, + host->req->data_dir == READ + ? PCI_DMA_FROMDEVICE + : PCI_DMA_TODEVICE)) { + host->req->error = -ENOMEM; + return host->req->error; + } + data_len = sg_dma_len(&host->req->sg); - writel(TIFM_MS_SYS_LATCH - | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel(0, sock->addr + SOCK_MS_DATA); - dev_dbg(&sock->dev, "writing %x\n", 0); + writel(ilog2(data_len) - 2, + sock->addr + SOCK_FIFO_PAGE_SIZE); + writel(TIFM_FIFO_INTMASK, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); + sys_param = TIFM_DMA_EN | (1 << 8); + if (host->req->data_dir == WRITE) + sys_param |= TIFM_DMA_TX; - } else - writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); + writel(TIFM_FIFO_INTMASK, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); - cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM); - cmd_mask &= ~TIFM_MS_SYS_DATA; - cmd_mask |= TIFM_MS_SYS_NOT_RDY; - dev_dbg(&sock->dev, "mask %x\n", cmd_mask); - writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); + writel(sg_dma_address(&host->req->sg), + sock->addr + SOCK_DMA_ADDRESS); + writel(sys_param, sock->addr + SOCK_DMA_CONTROL); + } else { + writel(host->mode_mask | TIFM_MS_SYS_FIFO, + sock->addr + SOCK_MS_SYSTEM); + + writel(TIFM_FIFO_MORE, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); } mod_timer(&host->timer, jiffies + host->timeout_jiffies); @@ -300,11 +314,21 @@ static int tifm_ms_issue_cmd(struct tifm_ms *host) sock->addr + SOCK_CONTROL); host->req->error = 0; + sys_param = readl(sock->addr + SOCK_MS_SYSTEM); + sys_param |= TIFM_MS_SYS_INTCLR; + + if (host->use_dma) + sys_param |= TIFM_MS_SYS_DMA; + else + sys_param &= ~TIFM_MS_SYS_DMA; + + writel(sys_param, sock->addr + SOCK_MS_SYSTEM); + cmd = (host->req->tpc & 0xf) << 12; cmd |= data_len; writel(cmd, sock->addr + SOCK_MS_COMMAND); - dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, cmd_mask); + dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, sys_param); return 0; } @@ -312,47 +336,20 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host) { struct tifm_dev *sock = host->dev; struct memstick_host *msh = tifm_get_drvdata(sock); - unsigned int tval = 0, data_len; - unsigned char *data; int rc; del_timer(&host->timer); - if (host->req->long_data) { - if (!host->no_dma) - tifm_unmap_sg(sock, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); - } else { - writel(~TIFM_MS_SYS_DATA & readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - - data = host->req->data; - data_len = host->req->data_len; - if (host->req->data_dir == READ) { - for (rc = 0; (data_len - rc) >= 4; rc += 4) - *(int *)(data + rc) - = __raw_readl(sock->addr - + SOCK_MS_DATA); - - if (data_len - rc) - tval = readl(sock->addr + SOCK_MS_DATA); - switch (data_len - rc) { - case 3: - data[rc + 2] = (tval >> 16) & 0xff; - case 2: - data[rc + 1] = (tval >> 8) & 0xff; - case 1: - data[rc] = tval & 0xff; - } - readl(sock->addr + SOCK_MS_DATA); - } - } + if (host->use_dma) + tifm_unmap_sg(sock, &host->req->sg, 1, + host->req->data_dir == READ + ? PCI_DMA_FROMDEVICE + : PCI_DMA_TODEVICE); writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); + dev_dbg(&sock->dev, "TPC complete\n"); do { rc = memstick_next_req(msh, &host->req); } while (!rc && tifm_ms_issue_cmd(host)); @@ -363,11 +360,10 @@ static int tifm_ms_check_status(struct tifm_ms *host) if (!host->req->error) { if (!(host->cmd_flags & CMD_READY)) return 1; - if (host->req->long_data - && !(host->cmd_flags & FIFO_READY)) + if (!(host->cmd_flags & FIFO_READY)) return 1; if (host->req->need_card_int - && !(host->cmd_flags & CARD_READY)) + && !(host->cmd_flags & CARD_INT)) return 1; } return 0; @@ -377,18 +373,24 @@ static int tifm_ms_check_status(struct tifm_ms *host) static void tifm_ms_data_event(struct tifm_dev *sock) { struct tifm_ms *host; - unsigned int fifo_status = 0; + unsigned int fifo_status = 0, host_status = 0; int rc = 1; spin_lock(&sock->lock); host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock)); fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); - dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n", - fifo_status, host->cmd_flags); + host_status = readl(sock->addr + SOCK_MS_STATUS); + dev_dbg(&sock->dev, + "data event: fifo_status %x, host_status %x, flags %x\n", + fifo_status, host_status, host->cmd_flags); if (host->req) { - if (fifo_status & TIFM_FIFO_READY) { - if (!host->no_dma || tifm_ms_transfer_data(host, 0)) { + if (host->use_dma && (fifo_status & 1)) { + host->cmd_flags |= FIFO_READY; + rc = tifm_ms_check_status(host); + } + if (!host->use_dma && (fifo_status & TIFM_FIFO_MORE)) { + if (!tifm_ms_transfer_data(host)) { host->cmd_flags |= FIFO_READY; rc = tifm_ms_check_status(host); } @@ -417,9 +419,9 @@ static void tifm_ms_card_event(struct tifm_dev *sock) host_status, host->cmd_flags); if (host->req) { - if (host_status & TIFM_MS_TIMEOUT) + if (host_status & TIFM_MS_STAT_TOE) host->req->error = -ETIME; - else if (host_status & TIFM_MS_BADCRC) + else if (host_status & TIFM_MS_STAT_CRC) host->req->error = -EILSEQ; if (host->req->error) { @@ -428,18 +430,17 @@ static void tifm_ms_card_event(struct tifm_dev *sock) writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); } - if (host_status & TIFM_MS_EOTPC) + if (host_status & TIFM_MS_STAT_RDY) host->cmd_flags |= CMD_READY; - if (host_status & TIFM_MS_INT) - host->cmd_flags |= CARD_READY; + + if (host_status & TIFM_MS_STAT_MSINT) + host->cmd_flags |= CARD_INT; rc = tifm_ms_check_status(host); } - writel(TIFM_MS_SYS_NOT_RDY | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel((~TIFM_MS_SYS_DATA) & readl(sock->addr + SOCK_MS_SYSTEM), + writel(TIFM_MS_SYS_INTCLR | readl(sock->addr + SOCK_MS_SYSTEM), sock->addr + SOCK_MS_SYSTEM); if (!rc) @@ -499,7 +500,7 @@ static void tifm_ms_set_param(struct memstick_host *msh, break; case MEMSTICK_INTERFACE: if (value == MEMSTICK_SERIAL) { - host->mode_mask = TIFM_MS_SERIAL; + host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI; writel((~TIFM_CTRL_FAST_CLK) & readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); @@ -535,9 +536,10 @@ static int tifm_ms_initialize_host(struct tifm_ms *host) struct tifm_dev *sock = host->dev; struct memstick_host *msh = tifm_get_drvdata(sock); - host->mode_mask = TIFM_MS_SERIAL; - writel(0x8000, sock->addr + SOCK_MS_SYSTEM); - writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM); + host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI; + writel(TIFM_MS_SYS_RESET, sock->addr + SOCK_MS_SYSTEM); + writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, + sock->addr + SOCK_MS_SYSTEM); writel(0xffffffff, sock->addr + SOCK_MS_STATUS); if (tifm_has_ms_pif(sock)) msh->caps |= MEMSTICK_CAP_PAR4; @@ -566,7 +568,6 @@ static int tifm_ms_probe(struct tifm_dev *sock) tifm_set_drvdata(sock, msh); host->dev = sock; host->timeout_jiffies = msecs_to_jiffies(1000); - host->no_dma = no_dma; setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host); @@ -599,7 +600,7 @@ static void tifm_ms_remove(struct tifm_dev *sock) writel(TIFM_FIFO_INT_SETALL, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); - if (host->req->long_data && !host->no_dma) + if (host->use_dma) tifm_unmap_sg(sock, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_TODEVICE @@ -616,7 +617,8 @@ static void tifm_ms_remove(struct tifm_dev *sock) memstick_remove_host(msh); - writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM); + writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, + sock->addr + SOCK_MS_SYSTEM); writel(0xffffffff, sock->addr + SOCK_MS_STATUS); memstick_free_host(msh); diff --git a/include/linux/tifm.h b/include/linux/tifm.h index da76ed85f595..848c0f392541 100644 --- a/include/linux/tifm.h +++ b/include/linux/tifm.h @@ -70,9 +70,9 @@ enum { #define TIFM_FIFO_ENABLE 0x00000001 #define TIFM_FIFO_READY 0x00000001 +#define TIFM_FIFO_MORE 0x00000008 #define TIFM_FIFO_INT_SETALL 0x0000ffff #define TIFM_FIFO_INTMASK 0x00000005 -#define TIFM_FIFO_SIZE 0x00000200 #define TIFM_DMA_RESET 0x00000002 #define TIFM_DMA_TX 0x00008000 -- cgit v1.2.3-55-g7522 From 60fdd931d577fcca351930fda4cde26ce07d35af Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Mon, 10 Mar 2008 11:43:43 -0700 Subject: memstick: add support for JMicron jmb38x MemoryStick host controller Signed-off-by: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/memstick/Kconfig | 2 +- drivers/memstick/host/Kconfig | 10 + drivers/memstick/host/Makefile | 6 +- drivers/memstick/host/jmb38x_ms.c | 945 ++++++++++++++++++++++++++++++++++++++ include/linux/pci_ids.h | 1 + 5 files changed, 960 insertions(+), 4 deletions(-) create mode 100644 drivers/memstick/host/jmb38x_ms.c (limited to 'include') diff --git a/drivers/memstick/Kconfig b/drivers/memstick/Kconfig index 1093fdb07297..f0ca41c20323 100644 --- a/drivers/memstick/Kconfig +++ b/drivers/memstick/Kconfig @@ -8,7 +8,7 @@ menuconfig MEMSTICK Sony MemoryStick is a proprietary storage/extension card protocol. If you want MemoryStick support, you should say Y here and also - to the specific driver for your MMC interface. + to the specific driver for your MemoryStick interface. if MEMSTICK diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig index c002fcc3c879..4ce5c8dffb68 100644 --- a/drivers/memstick/host/Kconfig +++ b/drivers/memstick/host/Kconfig @@ -20,3 +20,13 @@ config MEMSTICK_TIFM_MS To compile this driver as a module, choose M here: the module will be called tifm_ms. +config MEMSTICK_JMICRON_38X + tristate "JMicron JMB38X MemoryStick interface support (EXPERIMENTAL)" + depends on EXPERIMENTAL && PCI + + help + Say Y here if you want to be able to access MemoryStick cards with + the JMicron(R) JMB38X MemoryStick card reader. + + To compile this driver as a module, choose M here: the + module will be called jmb38x_ms. diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile index ee666380efa1..12530e4311d3 100644 --- a/drivers/memstick/host/Makefile +++ b/drivers/memstick/host/Makefile @@ -3,8 +3,8 @@ # ifeq ($(CONFIG_MEMSTICK_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG + EXTRA_CFLAGS += -DDEBUG endif -obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o - +obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o +obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c new file mode 100644 index 000000000000..03fe8783b1ee --- /dev/null +++ b/drivers/memstick/host/jmb38x_ms.c @@ -0,0 +1,945 @@ +/* + * jmb38x_ms.c - JMicron jmb38x MemoryStick card reader + * + * Copyright (C) 2008 Alex Dubov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "jmb38x_ms" + +static int no_dma; +module_param(no_dma, bool, 0644); + +enum { + DMA_ADDRESS = 0x00, + BLOCK = 0x04, + DMA_CONTROL = 0x08, + TPC_P0 = 0x0c, + TPC_P1 = 0x10, + TPC = 0x14, + HOST_CONTROL = 0x18, + DATA = 0x1c, + STATUS = 0x20, + INT_STATUS = 0x24, + INT_STATUS_ENABLE = 0x28, + INT_SIGNAL_ENABLE = 0x2c, + TIMER = 0x30, + TIMER_CONTROL = 0x34, + PAD_OUTPUT_ENABLE = 0x38, + PAD_PU_PD = 0x3c, + CLOCK_DELAY = 0x40, + ADMA_ADDRESS = 0x44, + CLOCK_CONTROL = 0x48, + LED_CONTROL = 0x4c, + VERSION = 0x50 +}; + +struct jmb38x_ms_host { + struct jmb38x_ms *chip; + void __iomem *addr; + spinlock_t lock; + int id; + char host_id[DEVICE_ID_SIZE]; + int irq; + unsigned int block_pos; + unsigned long timeout_jiffies; + struct timer_list timer; + struct memstick_request *req; + unsigned char eject:1, + use_dma:1; + unsigned char cmd_flags; + unsigned char io_pos; + unsigned int io_word[2]; +}; + +struct jmb38x_ms { + struct pci_dev *pdev; + int host_cnt; + struct memstick_host *hosts[]; +}; + +#define BLOCK_COUNT_MASK 0xffff0000 +#define BLOCK_SIZE_MASK 0x00000fff + +#define DMA_CONTROL_ENABLE 0x00000001 + +#define TPC_DATA_SEL 0x00008000 +#define TPC_DIR 0x00004000 +#define TPC_WAIT_INT 0x00002000 +#define TPC_GET_INT 0x00000800 +#define TPC_CODE_SZ_MASK 0x00000700 +#define TPC_DATA_SZ_MASK 0x00000007 + +#define HOST_CONTROL_RESET_REQ 0x00008000 +#define HOST_CONTROL_REI 0x00004000 +#define HOST_CONTROL_LED 0x00000400 +#define HOST_CONTROL_FAST_CLK 0x00000200 +#define HOST_CONTROL_RESET 0x00000100 +#define HOST_CONTROL_POWER_EN 0x00000080 +#define HOST_CONTROL_CLOCK_EN 0x00000040 +#define HOST_CONTROL_IF_SHIFT 4 + +#define HOST_CONTROL_IF_SERIAL 0x0 +#define HOST_CONTROL_IF_PAR4 0x1 +#define HOST_CONTROL_IF_PAR8 0x3 + +#define STATUS_HAS_MEDIA 0x00000400 +#define STATUS_FIFO_EMPTY 0x00000200 +#define STATUS_FIFO_FULL 0x00000100 + +#define INT_STATUS_TPC_ERR 0x00080000 +#define INT_STATUS_CRC_ERR 0x00040000 +#define INT_STATUS_TIMER_TO 0x00020000 +#define INT_STATUS_HSK_TO 0x00010000 +#define INT_STATUS_ANY_ERR 0x00008000 +#define INT_STATUS_FIFO_WRDY 0x00000080 +#define INT_STATUS_FIFO_RRDY 0x00000040 +#define INT_STATUS_MEDIA_OUT 0x00000010 +#define INT_STATUS_MEDIA_IN 0x00000008 +#define INT_STATUS_DMA_BOUNDARY 0x00000004 +#define INT_STATUS_EOTRAN 0x00000002 +#define INT_STATUS_EOTPC 0x00000001 + +#define INT_STATUS_ALL 0x000f801f + +#define PAD_OUTPUT_ENABLE_MS 0x0F3F + +#define PAD_PU_PD_OFF 0x7FFF0000 +#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 +#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 + +enum { + CMD_READY = 0x01, + FIFO_READY = 0x02, + REG_DATA = 0x04, + AUTO_GET_INT = 0x08 +}; + +static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host, + unsigned char *buf, unsigned int length) +{ + unsigned int off = 0; + + while (host->io_pos && length) { + buf[off++] = host->io_word[0] & 0xff; + host->io_word[0] >>= 8; + length--; + host->io_pos--; + } + + if (!length) + return off; + + while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) { + if (length < 4) + break; + *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA); + length -= 4; + off += 4; + } + + if (length + && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) { + host->io_word[0] = readl(host->addr + DATA); + for (host->io_pos = 4; host->io_pos; --host->io_pos) { + buf[off++] = host->io_word[0] & 0xff; + host->io_word[0] >>= 8; + length--; + if (!length) + break; + } + } + + return off; +} + +static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host, + unsigned char *buf, + unsigned int length) +{ + unsigned int off = 0; + + while (host->io_pos > 4 && length) { + buf[off++] = host->io_word[0] & 0xff; + host->io_word[0] >>= 8; + length--; + host->io_pos--; + } + + if (!length) + return off; + + while (host->io_pos && length) { + buf[off++] = host->io_word[1] & 0xff; + host->io_word[1] >>= 8; + length--; + host->io_pos--; + } + + return off; +} + +static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host, + unsigned char *buf, + unsigned int length) +{ + unsigned int off = 0; + + if (host->io_pos) { + while (host->io_pos < 4 && length) { + host->io_word[0] |= buf[off++] << (host->io_pos * 8); + host->io_pos++; + length--; + } + } + + if (host->io_pos == 4 + && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) { + writel(host->io_word[0], host->addr + DATA); + host->io_pos = 0; + host->io_word[0] = 0; + } else if (host->io_pos) { + return off; + } + + if (!length) + return off; + + while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) { + if (length < 4) + break; + + __raw_writel(*(unsigned int *)(buf + off), + host->addr + DATA); + length -= 4; + off += 4; + } + + switch (length) { + case 3: + host->io_word[0] |= buf[off + 2] << 16; + host->io_pos++; + case 2: + host->io_word[0] |= buf[off + 1] << 8; + host->io_pos++; + case 1: + host->io_word[0] |= buf[off]; + host->io_pos++; + } + + off += host->io_pos; + + return off; +} + +static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host, + unsigned char *buf, + unsigned int length) +{ + unsigned int off = 0; + + while (host->io_pos < 4 && length) { + host->io_word[0] &= ~(0xff << (host->io_pos * 8)); + host->io_word[0] |= buf[off++] << (host->io_pos * 8); + host->io_pos++; + length--; + } + + if (!length) + return off; + + while (host->io_pos < 8 && length) { + host->io_word[1] &= ~(0xff << (host->io_pos * 8)); + host->io_word[1] |= buf[off++] << (host->io_pos * 8); + host->io_pos++; + length--; + } + + return off; +} + +static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host) +{ + unsigned int length; + unsigned int off; + unsigned int t_size, p_off, p_cnt; + unsigned char *buf; + struct page *pg; + unsigned long flags = 0; + + if (host->req->long_data) { + length = host->req->sg.length - host->block_pos; + off = host->req->sg.offset + host->block_pos; + } else { + length = host->req->data_len - host->block_pos; + off = 0; + } + + while (length) { + if (host->req->long_data) { + pg = nth_page(sg_page(&host->req->sg), + off >> PAGE_SHIFT); + p_off = offset_in_page(off); + p_cnt = PAGE_SIZE - p_off; + p_cnt = min(p_cnt, length); + + local_irq_save(flags); + buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off; + } else { + buf = host->req->data + host->block_pos; + p_cnt = host->req->data_len - host->block_pos; + } + + if (host->req->data_dir == WRITE) + t_size = !(host->cmd_flags & REG_DATA) + ? jmb38x_ms_write_data(host, buf, p_cnt) + : jmb38x_ms_write_reg_data(host, buf, p_cnt); + else + t_size = !(host->cmd_flags & REG_DATA) + ? jmb38x_ms_read_data(host, buf, p_cnt) + : jmb38x_ms_read_reg_data(host, buf, p_cnt); + + if (host->req->long_data) { + kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ); + local_irq_restore(flags); + } + + if (!t_size) + break; + host->block_pos += t_size; + length -= t_size; + off += t_size; + } + + if (!length && host->req->data_dir == WRITE) { + if (host->cmd_flags & REG_DATA) { + writel(host->io_word[0], host->addr + TPC_P0); + writel(host->io_word[1], host->addr + TPC_P1); + } else if (host->io_pos) { + writel(host->io_word[0], host->addr + DATA); + } + } + + return length; +} + +static int jmb38x_ms_issue_cmd(struct memstick_host *msh) +{ + struct jmb38x_ms_host *host = memstick_priv(msh); + unsigned char *data; + unsigned int data_len, cmd, t_val; + + if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) { + dev_dbg(msh->cdev.dev, "no media status\n"); + host->req->error = -ETIME; + return host->req->error; + } + + dev_dbg(msh->cdev.dev, "control %08x\n", + readl(host->addr + HOST_CONTROL)); + dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS)); + dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS)); + + host->cmd_flags = 0; + host->block_pos = 0; + host->io_pos = 0; + host->io_word[0] = 0; + host->io_word[1] = 0; + + cmd = host->req->tpc << 16; + cmd |= TPC_DATA_SEL; + + if (host->req->data_dir == READ) + cmd |= TPC_DIR; + if (host->req->need_card_int) + cmd |= TPC_WAIT_INT; + if (host->req->get_int_reg) + cmd |= TPC_GET_INT; + + data = host->req->data; + + host->use_dma = !no_dma; + + if (host->req->long_data) { + data_len = host->req->sg.length; + } else { + data_len = host->req->data_len; + host->use_dma = 0; + } + + if (data_len <= 8) { + cmd &= ~(TPC_DATA_SEL | 0xf); + host->cmd_flags |= REG_DATA; + cmd |= data_len & 0xf; + host->use_dma = 0; + } + + if (host->use_dma) { + if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1, + host->req->data_dir == READ + ? PCI_DMA_FROMDEVICE + : PCI_DMA_TODEVICE)) { + host->req->error = -ENOMEM; + return host->req->error; + } + data_len = sg_dma_len(&host->req->sg); + writel(sg_dma_address(&host->req->sg), + host->addr + DMA_ADDRESS); + writel(((1 << 16) & BLOCK_COUNT_MASK) + | (data_len & BLOCK_SIZE_MASK), + host->addr + BLOCK); + writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL); + } else if (!(host->cmd_flags & REG_DATA)) { + writel(((1 << 16) & BLOCK_COUNT_MASK) + | (data_len & BLOCK_SIZE_MASK), + host->addr + BLOCK); + t_val = readl(host->addr + INT_STATUS_ENABLE); + t_val |= host->req->data_dir == READ + ? INT_STATUS_FIFO_RRDY + : INT_STATUS_FIFO_WRDY; + + writel(t_val, host->addr + INT_STATUS_ENABLE); + writel(t_val, host->addr + INT_SIGNAL_ENABLE); + } else { + cmd &= ~(TPC_DATA_SEL | 0xf); + host->cmd_flags |= REG_DATA; + cmd |= data_len & 0xf; + + if (host->req->data_dir == WRITE) { + jmb38x_ms_transfer_data(host); + writel(host->io_word[0], host->addr + TPC_P0); + writel(host->io_word[1], host->addr + TPC_P1); + } + } + + mod_timer(&host->timer, jiffies + host->timeout_jiffies); + writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL), + host->addr + HOST_CONTROL); + host->req->error = 0; + + writel(cmd, host->addr + TPC); + dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len); + + return 0; +} + +static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last) +{ + struct jmb38x_ms_host *host = memstick_priv(msh); + unsigned int t_val = 0; + int rc; + + del_timer(&host->timer); + + dev_dbg(msh->cdev.dev, "c control %08x\n", + readl(host->addr + HOST_CONTROL)); + dev_dbg(msh->cdev.dev, "c status %08x\n", + readl(host->addr + INT_STATUS)); + dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS)); + + if (host->req->get_int_reg) { + t_val = readl(host->addr + TPC_P0); + host->req->int_reg = (t_val & 0xff); + } + + if (host->use_dma) { + writel(0, host->addr + DMA_CONTROL); + pci_unmap_sg(host->chip->pdev, &host->req->sg, 1, + host->req->data_dir == READ + ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + } else { + t_val = readl(host->addr + INT_STATUS_ENABLE); + if (host->req->data_dir == READ) + t_val &= ~INT_STATUS_FIFO_RRDY; + else + t_val &= ~INT_STATUS_FIFO_WRDY; + + writel(t_val, host->addr + INT_STATUS_ENABLE); + writel(t_val, host->addr + INT_SIGNAL_ENABLE); + } + + writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL), + host->addr + HOST_CONTROL); + + if (!last) { + do { + rc = memstick_next_req(msh, &host->req); + } while (!rc && jmb38x_ms_issue_cmd(msh)); + } else { + do { + rc = memstick_next_req(msh, &host->req); + if (!rc) + host->req->error = -ETIME; + } while (!rc); + } +} + +static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id) +{ + struct memstick_host *msh = dev_id; + struct jmb38x_ms_host *host = memstick_priv(msh); + unsigned int irq_status; + + spin_lock(&host->lock); + irq_status = readl(host->addr + INT_STATUS); + dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status); + if (irq_status == 0 || irq_status == (~0)) { + spin_unlock(&host->lock); + return IRQ_NONE; + } + + if (host->req) { + if (irq_status & INT_STATUS_ANY_ERR) { + if (irq_status & INT_STATUS_CRC_ERR) + host->req->error = -EILSEQ; + else + host->req->error = -ETIME; + } else { + if (host->use_dma) { + if (irq_status & INT_STATUS_EOTRAN) + host->cmd_flags |= FIFO_READY; + } else { + if (irq_status & (INT_STATUS_FIFO_RRDY + | INT_STATUS_FIFO_WRDY)) + jmb38x_ms_transfer_data(host); + + if (irq_status & INT_STATUS_EOTRAN) { + jmb38x_ms_transfer_data(host); + host->cmd_flags |= FIFO_READY; + } + } + + if (irq_status & INT_STATUS_EOTPC) { + host->cmd_flags |= CMD_READY; + if (host->cmd_flags & REG_DATA) { + if (host->req->data_dir == READ) { + host->io_word[0] + = readl(host->addr + + TPC_P0); + host->io_word[1] + = readl(host->addr + + TPC_P1); + host->io_pos = 8; + + jmb38x_ms_transfer_data(host); + } + host->cmd_flags |= FIFO_READY; + } + } + } + } + + if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) { + dev_dbg(&host->chip->pdev->dev, "media changed\n"); + memstick_detect_change(msh); + } + + writel(irq_status, host->addr + INT_STATUS); + + if (host->req + && (((host->cmd_flags & CMD_READY) + && (host->cmd_flags & FIFO_READY)) + || host->req->error)) + jmb38x_ms_complete_cmd(msh, 0); + + spin_unlock(&host->lock); + return IRQ_HANDLED; +} + +static void jmb38x_ms_abort(unsigned long data) +{ + struct memstick_host *msh = (struct memstick_host *)data; + struct jmb38x_ms_host *host = memstick_priv(msh); + unsigned long flags; + + dev_dbg(&host->chip->pdev->dev, "abort\n"); + spin_lock_irqsave(&host->lock, flags); + if (host->req) { + host->req->error = -ETIME; + jmb38x_ms_complete_cmd(msh, 0); + } + spin_unlock_irqrestore(&host->lock, flags); +} + +static void jmb38x_ms_request(struct memstick_host *msh) +{ + struct jmb38x_ms_host *host = memstick_priv(msh); + unsigned long flags; + int rc; + + spin_lock_irqsave(&host->lock, flags); + if (host->req) { + spin_unlock_irqrestore(&host->lock, flags); + BUG(); + return; + } + + do { + rc = memstick_next_req(msh, &host->req); + } while (!rc && jmb38x_ms_issue_cmd(msh)); + spin_unlock_irqrestore(&host->lock, flags); +} + +static void jmb38x_ms_reset(struct jmb38x_ms_host *host) +{ + unsigned int host_ctl = readl(host->addr + HOST_CONTROL); + + writel(host_ctl | HOST_CONTROL_RESET_REQ | HOST_CONTROL_RESET, + host->addr + HOST_CONTROL); + + while (HOST_CONTROL_RESET_REQ + & (host_ctl = readl(host->addr + HOST_CONTROL))) { + ndelay(100); + dev_dbg(&host->chip->pdev->dev, "reset\n"); + } + + writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); + writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); + + dev_dbg(&host->chip->pdev->dev, "reset\n"); +} + +static void jmb38x_ms_set_param(struct memstick_host *msh, + enum memstick_param param, + int value) +{ + struct jmb38x_ms_host *host = memstick_priv(msh); + unsigned int host_ctl; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + + switch (param) { + case MEMSTICK_POWER: + if (value == MEMSTICK_POWER_ON) { + jmb38x_ms_reset(host); + + writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 + : PAD_PU_PD_ON_MS_SOCK0, + host->addr + PAD_PU_PD); + + writel(PAD_OUTPUT_ENABLE_MS, + host->addr + PAD_OUTPUT_ENABLE); + + host_ctl = readl(host->addr + HOST_CONTROL); + host_ctl |= 7; + writel(host_ctl | (HOST_CONTROL_POWER_EN + | HOST_CONTROL_CLOCK_EN), + host->addr + HOST_CONTROL); + + dev_dbg(&host->chip->pdev->dev, "power on\n"); + } else if (value == MEMSTICK_POWER_OFF) { + writel(readl(host->addr + HOST_CONTROL) + & ~(HOST_CONTROL_POWER_EN + | HOST_CONTROL_CLOCK_EN), + host->addr + HOST_CONTROL); + writel(0, host->addr + PAD_OUTPUT_ENABLE); + writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); + dev_dbg(&host->chip->pdev->dev, "power off\n"); + } + break; + case MEMSTICK_INTERFACE: + /* jmb38x_ms_reset(host); */ + + host_ctl = readl(host->addr + HOST_CONTROL); + host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); + /* host_ctl |= 7; */ + + if (value == MEMSTICK_SERIAL) { + host_ctl &= ~HOST_CONTROL_FAST_CLK; + host_ctl |= HOST_CONTROL_IF_SERIAL + << HOST_CONTROL_IF_SHIFT; + host_ctl |= HOST_CONTROL_REI; + writel(0, host->addr + CLOCK_DELAY); + } else if (value == MEMSTICK_PAR4) { + host_ctl |= HOST_CONTROL_FAST_CLK; + host_ctl |= HOST_CONTROL_IF_PAR4 + << HOST_CONTROL_IF_SHIFT; + host_ctl &= ~HOST_CONTROL_REI; + writel(4, host->addr + CLOCK_DELAY); + } else if (value == MEMSTICK_PAR8) { + host_ctl |= HOST_CONTROL_FAST_CLK; + host_ctl |= HOST_CONTROL_IF_PAR8 + << HOST_CONTROL_IF_SHIFT; + host_ctl &= ~HOST_CONTROL_REI; + writel(4, host->addr + CLOCK_DELAY); + } + writel(host_ctl, host->addr + HOST_CONTROL); + break; + }; + + spin_unlock_irqrestore(&host->lock, flags); +} + +#ifdef CONFIG_PM + +static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state) +{ + struct jmb38x_ms *jm = pci_get_drvdata(dev); + int cnt; + + for (cnt = 0; cnt < jm->host_cnt; ++cnt) { + if (!jm->hosts[cnt]) + break; + memstick_suspend_host(jm->hosts[cnt]); + } + + pci_save_state(dev); + pci_enable_wake(dev, pci_choose_state(dev, state), 0); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + return 0; +} + +static int jmb38x_ms_resume(struct pci_dev *dev) +{ + struct jmb38x_ms *jm = pci_get_drvdata(dev); + int rc; + + pci_set_power_state(dev, PCI_D0); + pci_restore_state(dev); + rc = pci_enable_device(dev); + if (rc) + return rc; + pci_set_master(dev); + + pci_read_config_dword(dev, 0xac, &rc); + pci_write_config_dword(dev, 0xac, rc | 0x00470000); + + for (rc = 0; rc < jm->host_cnt; ++rc) { + if (!jm->hosts[rc]) + break; + memstick_resume_host(jm->hosts[rc]); + memstick_detect_change(jm->hosts[rc]); + } + + return 0; +} + +#else + +#define jmb38x_ms_suspend NULL +#define jmb38x_ms_resume NULL + +#endif /* CONFIG_PM */ + +static int jmb38x_ms_count_slots(struct pci_dev *pdev) +{ + int cnt, rc = 0; + + for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) { + if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt))) + break; + + if (256 != pci_resource_len(pdev, cnt)) + break; + + ++rc; + } + return rc; +} + +static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) +{ + struct memstick_host *msh; + struct jmb38x_ms_host *host; + + msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host), + &jm->pdev->dev); + if (!msh) + return NULL; + + host = memstick_priv(msh); + host->chip = jm; + host->addr = ioremap(pci_resource_start(jm->pdev, cnt), + pci_resource_len(jm->pdev, cnt)); + if (!host->addr) + goto err_out_free; + + spin_lock_init(&host->lock); + host->id = cnt; + snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d", + host->id); + host->irq = jm->pdev->irq; + host->timeout_jiffies = msecs_to_jiffies(4000); + msh->request = jmb38x_ms_request; + msh->set_param = jmb38x_ms_set_param; + /* + msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4 + | MEMSTICK_CAP_PAR8; + */ + msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; + + setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh); + + if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id, + msh)) + return msh; + + iounmap(host->addr); +err_out_free: + kfree(msh); + return NULL; +} + +static void jmb38x_ms_free_host(struct memstick_host *msh) +{ + struct jmb38x_ms_host *host = memstick_priv(msh); + + free_irq(host->irq, msh); + iounmap(host->addr); + memstick_free_host(msh); +} + +static int jmb38x_ms_probe(struct pci_dev *pdev, + const struct pci_device_id *dev_id) +{ + struct jmb38x_ms *jm; + int pci_dev_busy = 0; + int rc, cnt; + + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) + return rc; + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + pci_set_master(pdev); + + rc = pci_request_regions(pdev, DRIVER_NAME); + if (rc) { + pci_dev_busy = 1; + goto err_out; + } + + pci_read_config_dword(pdev, 0xac, &rc); + pci_write_config_dword(pdev, 0xac, rc | 0x00470000); + + cnt = jmb38x_ms_count_slots(pdev); + if (!cnt) { + rc = -ENODEV; + pci_dev_busy = 1; + goto err_out; + } + + jm = kzalloc(sizeof(struct jmb38x_ms) + + cnt * sizeof(struct memstick_host *), GFP_KERNEL); + if (!jm) { + rc = -ENOMEM; + goto err_out_int; + } + + jm->pdev = pdev; + jm->host_cnt = cnt; + pci_set_drvdata(pdev, jm); + + for (cnt = 0; cnt < jm->host_cnt; ++cnt) { + jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt); + if (!jm->hosts[cnt]) + break; + + rc = memstick_add_host(jm->hosts[cnt]); + + if (rc) { + jmb38x_ms_free_host(jm->hosts[cnt]); + jm->hosts[cnt] = NULL; + break; + } + } + + if (cnt) + return 0; + + rc = -ENODEV; + + pci_set_drvdata(pdev, NULL); + kfree(jm); +err_out_int: + pci_release_regions(pdev); +err_out: + if (!pci_dev_busy) + pci_disable_device(pdev); + return rc; +} + +static void jmb38x_ms_remove(struct pci_dev *dev) +{ + struct jmb38x_ms *jm = pci_get_drvdata(dev); + struct jmb38x_ms_host *host; + int cnt; + unsigned long flags; + + for (cnt = 0; cnt < jm->host_cnt; ++cnt) { + if (!jm->hosts[cnt]) + break; + + host = memstick_priv(jm->hosts[cnt]); + + writel(0, host->addr + INT_SIGNAL_ENABLE); + writel(0, host->addr + INT_STATUS_ENABLE); + mmiowb(); + dev_dbg(&jm->pdev->dev, "interrupts off\n"); + spin_lock_irqsave(&host->lock, flags); + if (host->req) { + host->req->error = -ETIME; + jmb38x_ms_complete_cmd(jm->hosts[cnt], 1); + } + spin_unlock_irqrestore(&host->lock, flags); + + memstick_remove_host(jm->hosts[cnt]); + dev_dbg(&jm->pdev->dev, "host removed\n"); + + jmb38x_ms_free_host(jm->hosts[cnt]); + } + + pci_set_drvdata(dev, NULL); + pci_release_regions(dev); + pci_disable_device(dev); + kfree(jm); +} + +static struct pci_device_id jmb38x_ms_id_tbl [] = { + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0 }, + { } +}; + +static struct pci_driver jmb38x_ms_driver = { + .name = DRIVER_NAME, + .id_table = jmb38x_ms_id_tbl, + .probe = jmb38x_ms_probe, + .remove = jmb38x_ms_remove, + .suspend = jmb38x_ms_suspend, + .resume = jmb38x_ms_resume +}; + +static int __init jmb38x_ms_init(void) +{ + return pci_register_driver(&jmb38x_ms_driver); +} + +static void __exit jmb38x_ms_exit(void) +{ + pci_unregister_driver(&jmb38x_ms_driver); +} + +MODULE_AUTHOR("Alex Dubov"); +MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl); + +module_init(jmb38x_ms_init); +module_exit(jmb38x_ms_exit); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index effdb558a588..70eb3c803d47 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2184,6 +2184,7 @@ #define PCI_DEVICE_ID_JMICRON_JMB366 0x2366 #define PCI_DEVICE_ID_JMICRON_JMB368 0x2368 #define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381 +#define PCI_DEVICE_ID_JMICRON_JMB38X_MS 0x2383 #define PCI_VENDOR_ID_KORENIX 0x1982 #define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600 -- cgit v1.2.3-55-g7522 From 985a34bd75cc8c96e43f00dcdda7c3fdb51a3026 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 9 Mar 2008 13:14:37 +0100 Subject: x86: remove quicklists quicklists cause a serious memory leak on 32-bit x86, as documented at: http://bugzilla.kernel.org/show_bug.cgi?id=9991 the reason is that the quicklist pool is a special-purpose cache that grows out of proportion. It is not accounted for anywhere and users have no way to even realize that it's the quicklists that are causing RAM usage spikes. It was supposed to be a relatively small pool, but as demonstrated by KOSAKI Motohiro, they can grow as large as: Quicklists: 1194304 kB given how much trouble this code has caused historically, and given that Andrew objected to its introduction on x86 (years ago), the best option at this point is to remove them. [ any performance benefits of caching constructed pgds should be implemented in a more generic way (possibly within the page allocator), while still allowing constructed pages to be allocated by other workloads. ] Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 3 --- arch/x86/mm/pgtable_32.c | 18 +++++++++--------- include/asm-x86/pgtable_32.h | 5 ++--- 3 files changed, 11 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f41c9538ca30..237fc128143d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -66,9 +66,6 @@ config MMU config ZONE_DMA def_bool y -config QUICKLIST - def_bool X86_32 - config SBUS bool diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index 73aba7125203..2f9e9afcb9f4 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c @@ -342,12 +342,16 @@ static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp) pgd_t *pgd_alloc(struct mm_struct *mm) { - pgd_t *pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor); + pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); - mm->pgd = pgd; /* so that alloc_pd can use it */ + /* so that alloc_pd can use it */ + mm->pgd = pgd; + if (pgd) + pgd_ctor(pgd); if (pgd && !pgd_prepopulate_pmd(mm, pgd)) { - quicklist_free(0, pgd_dtor, pgd); + pgd_dtor(pgd); + free_page((unsigned long)pgd); pgd = NULL; } @@ -357,12 +361,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm) void pgd_free(struct mm_struct *mm, pgd_t *pgd) { pgd_mop_up_pmds(mm, pgd); - quicklist_free(0, pgd_dtor, pgd); -} - -void check_pgt_cache(void) -{ - quicklist_trim(0, pgd_dtor, 25, 16); + pgd_dtor(pgd); + free_page((unsigned long)pgd); } void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte) diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h index a842c7222b1e..4e6a0fca0b47 100644 --- a/include/asm-x86/pgtable_32.h +++ b/include/asm-x86/pgtable_32.h @@ -26,10 +26,9 @@ struct mm_struct; struct vm_area_struct; extern pgd_t swapper_pg_dir[1024]; -extern struct kmem_cache *pmd_cache; -void check_pgt_cache(void); -static inline void pgtable_cache_init(void) {} +static inline void pgtable_cache_init(void) { } +static inline void check_pgt_cache(void) { } void paging_init(void); -- cgit v1.2.3-55-g7522 From 308a163931928332b57dfdfb3520c1924a337ef5 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 26 Jan 2008 14:08:02 +0900 Subject: [MIPS] Fix plat_ioremap for JMR3927 TX39XX's "reserved" segment in CKSEG3 area is 0xff000000-0xfffeffff. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/mach-jmr3927/ioremap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-mips/mach-jmr3927/ioremap.h b/include/asm-mips/mach-jmr3927/ioremap.h index aa131ad7f717..29989ff10d66 100644 --- a/include/asm-mips/mach-jmr3927/ioremap.h +++ b/include/asm-mips/mach-jmr3927/ioremap.h @@ -25,7 +25,7 @@ static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, { #define TXX9_DIRECTMAP_BASE 0xff000000ul if (offset >= TXX9_DIRECTMAP_BASE && - offset < TXX9_DIRECTMAP_BASE + 0xf0000) + offset < TXX9_DIRECTMAP_BASE + 0xff0000) return (void __iomem *)offset; return NULL; } -- cgit v1.2.3-55-g7522 From 1af0eea21431bed5d07dffc0fefab57fd72f7e90 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 8 Mar 2008 09:44:37 +0000 Subject: [MIPS] IP27: Tighten up CPU description to fix warnings. Signed-off-by: Ralf Baechle --- include/asm-mips/mach-ip27/cpu-feature-overrides.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/asm-mips/mach-ip27/cpu-feature-overrides.h b/include/asm-mips/mach-ip27/cpu-feature-overrides.h index fe076380c189..7d3112b148d9 100644 --- a/include/asm-mips/mach-ip27/cpu-feature-overrides.h +++ b/include/asm-mips/mach-ip27/cpu-feature-overrides.h @@ -34,7 +34,11 @@ #define cpu_has_64bits 1 #define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_6k_cache 0 #define cpu_has_4k_cache 1 +#define cpu_has_8k_cache 0 +#define cpu_has_tx39_cache 0 #define cpu_has_inclusive_pcaches 1 -- cgit v1.2.3-55-g7522 From 234fcd1484a66158b561b36b421547f0ab85fee9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 8 Mar 2008 09:56:28 +0000 Subject: [MIPS] Fix loads of section missmatches Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-bugs64.c | 4 +- arch/mips/kernel/cpu-probe.c | 10 ++--- arch/mips/kernel/head.S | 2 +- arch/mips/kernel/traps.c | 7 ++-- arch/mips/lib/uncached.c | 2 +- arch/mips/mips-boards/generic/time.c | 2 +- arch/mips/mipssim/sim_time.c | 2 +- arch/mips/mm/c-r3k.c | 2 +- arch/mips/mm/c-r4k.c | 30 +++++++------- arch/mips/mm/c-tx39.c | 2 +- arch/mips/mm/cache.c | 5 ++- arch/mips/mm/cex-sb1.S | 4 +- arch/mips/mm/pg-r4k.c | 22 +++++------ arch/mips/mm/pg-sb1.c | 4 +- arch/mips/mm/sc-ip22.c | 2 +- arch/mips/mm/sc-mips.c | 3 +- arch/mips/mm/sc-r5k.c | 2 +- arch/mips/mm/sc-rm7k.c | 2 +- arch/mips/mm/tlb-r3k.c | 2 +- arch/mips/mm/tlb-r4k.c | 8 ++-- arch/mips/mm/tlb-r8k.c | 4 +- arch/mips/mm/tlbex.c | 70 ++++++++++++++++----------------- arch/mips/mm/uasm.c | 68 ++++++++++++++++---------------- arch/mips/mm/uasm.h | 76 ++++++++++++++++-------------------- arch/mips/pci/pci-ip27.c | 2 +- arch/mips/pci/pci.c | 2 +- arch/mips/sgi-ip27/ip27-init.c | 2 +- arch/mips/sgi-ip27/ip27-timer.c | 2 +- arch/mips/sgi-ip27/ip27-xtalk.c | 6 +-- include/asm-mips/cacheflush.h | 2 +- 30 files changed, 171 insertions(+), 180 deletions(-) (limited to 'include') diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index 417bb3e336ac..a1b48af0992f 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -167,7 +167,7 @@ static inline void check_mult_sh(void) panic(bug64hit, !R4000_WAR ? r4kwar : nowar); } -static volatile int daddi_ov __initdata = 0; +static volatile int daddi_ov __cpuinitdata = 0; asmlinkage void __init do_daddi_ov(struct pt_regs *regs) { @@ -239,7 +239,7 @@ static inline void check_daddi(void) panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); } -int daddiu_bug __initdata = -1; +int daddiu_bug __cpuinitdata = -1; static inline void check_daddiu(void) { diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 5861a432a52f..89c3304cb93c 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -550,7 +550,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c) } } -static char unknown_isa[] __initdata = KERN_ERR \ +static char unknown_isa[] __cpuinitdata = KERN_ERR \ "Unsupported ISA type, c0.config0: %d."; static inline unsigned int decode_config0(struct cpuinfo_mips *c) @@ -656,7 +656,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) return config3 & MIPS_CONF_M; } -static void __init decode_configs(struct cpuinfo_mips *c) +static void __cpuinit decode_configs(struct cpuinfo_mips *c) { /* MIPS32 or MIPS64 compliant CPU. */ c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | @@ -814,7 +814,7 @@ const char *__cpu_name[NR_CPUS]; /* * Name a CPU */ -static __init const char *cpu_to_name(struct cpuinfo_mips *c) +static __cpuinit const char *cpu_to_name(struct cpuinfo_mips *c) { const char *name = NULL; @@ -896,7 +896,7 @@ static __init const char *cpu_to_name(struct cpuinfo_mips *c) return name; } -__init void cpu_probe(void) +__cpuinit void cpu_probe(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int cpu = smp_processor_id(); @@ -959,7 +959,7 @@ __init void cpu_probe(void) c->srsets = 1; } -__init void cpu_report(void) +__cpuinit void cpu_report(void) { struct cpuinfo_mips *c = ¤t_cpu_data; diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index a24fb7900901..361364501d34 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -195,7 +195,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point j start_kernel END(kernel_entry) - __INIT + __CPUINIT #ifdef CONFIG_SMP /* diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 79cf7e913b99..984c0d0a7b4d 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1306,7 +1306,7 @@ int cp0_compare_irq; int cp0_perfcount_irq; EXPORT_SYMBOL_GPL(cp0_perfcount_irq); -void __init per_cpu_trap_init(void) +void __cpuinit per_cpu_trap_init(void) { unsigned int cpu = smp_processor_id(); unsigned int status_set = ST0_CU0; @@ -1423,11 +1423,12 @@ void __init set_handler(unsigned long offset, void *addr, unsigned long size) flush_icache_range(ebase + offset, ebase + offset + size); } -static char panic_null_cerr[] __initdata = +static char panic_null_cerr[] __cpuinitdata = "Trying to set NULL cache error exception handler"; /* Install uncached CPU exception handler */ -void __init set_uncached_handler(unsigned long offset, void *addr, unsigned long size) +void __cpuinit set_uncached_handler(unsigned long offset, void *addr, + unsigned long size) { #ifdef CONFIG_32BIT unsigned long uncached_ebase = KSEG1ADDR(ebase); diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c index 27b012d4341c..a6d1c77034d5 100644 --- a/arch/mips/lib/uncached.c +++ b/arch/mips/lib/uncached.c @@ -36,7 +36,7 @@ * values, so we can avoid sharing the same stack area between a cached * and the uncached mode. */ -unsigned long __init run_uncached(void *func) +unsigned long __cpuinit run_uncached(void *func) { register long sp __asm__("$sp"); register long ret __asm__("$2"); diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index f02ce6308e51..b50e0fc406ac 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -146,7 +146,7 @@ void __init plat_perf_setup(void) } } -unsigned int __init get_c0_compare_int(void) +unsigned int __cpuinit get_c0_compare_int(void) { #ifdef MSC01E_INT_BASE if (cpu_has_veic) { diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c index e39bbe989da3..881ecbc1fa23 100644 --- a/arch/mips/mipssim/sim_time.c +++ b/arch/mips/mipssim/sim_time.c @@ -83,7 +83,7 @@ static void mips_timer_dispatch(void) } -unsigned __init get_c0_compare_int(void) +unsigned __cpuinit get_c0_compare_int(void) { #ifdef MSC01E_INT_BASE if (cpu_has_veic) { diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 562abb77d1d5..76935e320214 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -307,7 +307,7 @@ static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) r3k_flush_dcache_range(start, start + size); } -void __init r3k_cache_init(void) +void __cpuinit r3k_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 2c4f7e11f0d5..6496925b5e29 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -93,7 +93,7 @@ static inline void r4k_blast_dcache_page_dc32(unsigned long addr) blast_dcache32_page(addr); } -static void __init r4k_blast_dcache_page_setup(void) +static void __cpuinit r4k_blast_dcache_page_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -107,7 +107,7 @@ static void __init r4k_blast_dcache_page_setup(void) static void (* r4k_blast_dcache_page_indexed)(unsigned long addr); -static void __init r4k_blast_dcache_page_indexed_setup(void) +static void __cpuinit r4k_blast_dcache_page_indexed_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -121,7 +121,7 @@ static void __init r4k_blast_dcache_page_indexed_setup(void) static void (* r4k_blast_dcache)(void); -static void __init r4k_blast_dcache_setup(void) +static void __cpuinit r4k_blast_dcache_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -206,7 +206,7 @@ static inline void tx49_blast_icache32_page_indexed(unsigned long page) static void (* r4k_blast_icache_page)(unsigned long addr); -static void __init r4k_blast_icache_page_setup(void) +static void __cpuinit r4k_blast_icache_page_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -223,7 +223,7 @@ static void __init r4k_blast_icache_page_setup(void) static void (* r4k_blast_icache_page_indexed)(unsigned long addr); -static void __init r4k_blast_icache_page_indexed_setup(void) +static void __cpuinit r4k_blast_icache_page_indexed_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -247,7 +247,7 @@ static void __init r4k_blast_icache_page_indexed_setup(void) static void (* r4k_blast_icache)(void); -static void __init r4k_blast_icache_setup(void) +static void __cpuinit r4k_blast_icache_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -268,7 +268,7 @@ static void __init r4k_blast_icache_setup(void) static void (* r4k_blast_scache_page)(unsigned long addr); -static void __init r4k_blast_scache_page_setup(void) +static void __cpuinit r4k_blast_scache_page_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -286,7 +286,7 @@ static void __init r4k_blast_scache_page_setup(void) static void (* r4k_blast_scache_page_indexed)(unsigned long addr); -static void __init r4k_blast_scache_page_indexed_setup(void) +static void __cpuinit r4k_blast_scache_page_indexed_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -304,7 +304,7 @@ static void __init r4k_blast_scache_page_indexed_setup(void) static void (* r4k_blast_scache)(void); -static void __init r4k_blast_scache_setup(void) +static void __cpuinit r4k_blast_scache_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -691,11 +691,11 @@ static inline void rm7k_erratum31(void) } } -static char *way_string[] __initdata = { NULL, "direct mapped", "2-way", +static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way", "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" }; -static void __init probe_pcache(void) +static void __cpuinit probe_pcache(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); @@ -1016,7 +1016,7 @@ static void __init probe_pcache(void) * executes in KSEG1 space or else you will crash and burn badly. You have * been warned. */ -static int __init probe_scache(void) +static int __cpuinit probe_scache(void) { unsigned long flags, addr, begin, end, pow2; unsigned int config = read_c0_config(); @@ -1095,7 +1095,7 @@ extern int r5k_sc_init(void); extern int rm7k_sc_init(void); extern int mips_sc_init(void); -static void __init setup_scache(void) +static void __cpuinit setup_scache(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); @@ -1206,7 +1206,7 @@ void au1x00_fixup_config_od(void) } } -static void __init coherency_setup(void) +static void __cpuinit coherency_setup(void) { change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); @@ -1238,7 +1238,7 @@ static void __init coherency_setup(void) } } -void __init r4k_cache_init(void) +void __cpuinit r4k_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 9ea121e8cdce..b09d56981d53 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -329,7 +329,7 @@ static __init void tx39_probe_cache(void) } } -void __init tx39_cache_init(void) +void __cpuinit tx39_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 6a24651971df..51ab1faa027d 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -127,9 +127,10 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address, } } -static char cache_panic[] __initdata = "Yeee, unsupported cache architecture."; +static char cache_panic[] __cpuinitdata = + "Yeee, unsupported cache architecture."; -void __init cpu_cache_init(void) +void __devinit cpu_cache_init(void) { if (cpu_has_3k_cache) { extern void __weak r3k_cache_init(void); diff --git a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S index e54a62f2807c..2d08268bb705 100644 --- a/arch/mips/mm/cex-sb1.S +++ b/arch/mips/mm/cex-sb1.S @@ -34,8 +34,6 @@ * is changed. */ - __INIT - .set mips64 .set noreorder .set noat @@ -51,6 +49,8 @@ * (0x170-0x17f) are used to preserve k0, k1, and ra. */ + __CPUINIT + LEAF(except_vec2_sb1) /* * If this error is recoverable, we need to exit the handler diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index 9185fbf37c0d..455dedb5b39e 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c @@ -66,21 +66,21 @@ EXPORT_SYMBOL(copy_page); * with 64-bit kernels. The prefetch offsets have been experimentally tuned * an Origin 200. */ -static int pref_offset_clear __initdata = 512; -static int pref_offset_copy __initdata = 256; +static int pref_offset_clear __cpuinitdata = 512; +static int pref_offset_copy __cpuinitdata = 256; -static unsigned int pref_src_mode __initdata; -static unsigned int pref_dst_mode __initdata; +static unsigned int pref_src_mode __cpuinitdata; +static unsigned int pref_dst_mode __cpuinitdata; -static int load_offset __initdata; -static int store_offset __initdata; +static int load_offset __cpuinitdata; +static int store_offset __cpuinitdata; -static unsigned int __initdata *dest, *epc; +static unsigned int __cpuinitdata *dest, *epc; static unsigned int instruction_pending; static union mips_instruction delayed_mi; -static void __init emit_instruction(union mips_instruction mi) +static void __cpuinit emit_instruction(union mips_instruction mi) { if (instruction_pending) *epc++ = delayed_mi.word; @@ -222,7 +222,7 @@ static inline void build_cdex_p(void) emit_instruction(mi); } -static void __init __build_store_reg(int reg) +static void __cpuinit __build_store_reg(int reg) { union mips_instruction mi; unsigned int width; @@ -339,7 +339,7 @@ static inline void build_jr_ra(void) flush_delay_slot_or_nop(); } -void __init build_clear_page(void) +void __cpuinit build_clear_page(void) { unsigned int loop_start; unsigned long off; @@ -442,7 +442,7 @@ dest = label(); pr_debug("\t.set pop\n"); } -void __init build_copy_page(void) +void __cpuinit build_copy_page(void) { unsigned int loop_start; unsigned long off; diff --git a/arch/mips/mm/pg-sb1.c b/arch/mips/mm/pg-sb1.c index 89925ec57d6a..49e289d05414 100644 --- a/arch/mips/mm/pg-sb1.c +++ b/arch/mips/mm/pg-sb1.c @@ -293,10 +293,10 @@ void copy_page(void *to, void *from) EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(copy_page); -void __init build_clear_page(void) +void __cpuinit build_clear_page(void) { } -void __init build_copy_page(void) +void __cpuinit build_copy_page(void) { } diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c index d236cf8b7374..1f602a110e10 100644 --- a/arch/mips/mm/sc-ip22.c +++ b/arch/mips/mm/sc-ip22.c @@ -168,7 +168,7 @@ struct bcache_ops indy_sc_ops = { .bc_inv = indy_sc_wback_invalidate }; -void __init indy_sc_init(void) +void __cpuinit indy_sc_init(void) { if (indy_sc_probe()) { indy_sc_enable(); diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index c13170bc675c..b55c2d1b998f 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -100,7 +100,7 @@ static inline int __init mips_sc_probe(void) return 1; } -int __init mips_sc_init(void) +int __cpuinit mips_sc_init(void) { int found = mips_sc_probe(); if (found) { @@ -109,4 +109,3 @@ int __init mips_sc_init(void) } return found; } - diff --git a/arch/mips/mm/sc-r5k.c b/arch/mips/mm/sc-r5k.c index d35b6c1103a3..f330d38e5575 100644 --- a/arch/mips/mm/sc-r5k.c +++ b/arch/mips/mm/sc-r5k.c @@ -99,7 +99,7 @@ static struct bcache_ops r5k_sc_ops = { .bc_inv = r5k_dma_cache_inv_sc }; -void __init r5k_sc_init(void) +void __cpuinit r5k_sc_init(void) { if (r5k_sc_probe()) { r5k_sc_enable(); diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index 31ec73052423..fc227f3b1199 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -128,7 +128,7 @@ struct bcache_ops rm7k_sc_ops = { .bc_inv = rm7k_sc_inv }; -void __init rm7k_sc_init(void) +void __cpuinit rm7k_sc_init(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index 7948e9a5e372..a782549ac80e 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -281,7 +281,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, } } -void __init tlb_init(void) +void __cpuinit tlb_init(void) { local_flush_tlb_all(); diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 2ad08fca598b..63065d6e8063 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -388,7 +388,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, * lifetime of the system */ -static int temp_tlb_entry __initdata; +static int temp_tlb_entry __cpuinitdata; __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) @@ -427,7 +427,7 @@ out: return ret; } -static void __init probe_tlb(unsigned long config) +static void __cpuinit probe_tlb(unsigned long config) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int reg; @@ -455,7 +455,7 @@ static void __init probe_tlb(unsigned long config) c->tlbsize = ((reg >> 25) & 0x3f) + 1; } -static int __initdata ntlb = 0; +static int __cpuinitdata ntlb = 0; static int __init set_ntlb(char *str) { get_option(&str, &ntlb); @@ -464,7 +464,7 @@ static int __init set_ntlb(char *str) __setup("ntlb=", set_ntlb); -void __init tlb_init(void) +void __cpuinit tlb_init(void) { unsigned int config = read_c0_config(); diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c index bd8409d8ff62..4f01a3be215c 100644 --- a/arch/mips/mm/tlb-r8k.c +++ b/arch/mips/mm/tlb-r8k.c @@ -214,14 +214,14 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) local_irq_restore(flags); } -static void __init probe_tlb(unsigned long config) +static void __cpuinit probe_tlb(unsigned long config) { struct cpuinfo_mips *c = ¤t_cpu_data; c->tlbsize = 3 * 128; /* 3 sets each 128 entries */ } -void __init tlb_init(void) +void __cpuinit tlb_init(void) { unsigned int config = read_c0_config(); unsigned long status; diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 218a6cc415e8..3a93d4ce2703 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -60,7 +60,7 @@ static inline int __maybe_unused r10000_llsc_war(void) * why; it's not an issue caused by the core RTL. * */ -static int __init m4kc_tlbp_war(void) +static int __cpuinit m4kc_tlbp_war(void) { return (current_cpu_data.processor_id & 0xffff00) == (PRID_COMP_MIPS | PRID_IMP_4KC); @@ -144,16 +144,16 @@ static inline void dump_handler(const u32 *handler, int count) * We deliberately chose a buffer size of 128, so we won't scribble * over anything important on overflow before we panic. */ -static u32 tlb_handler[128] __initdata; +static u32 tlb_handler[128] __cpuinitdata; /* simply assume worst case size for labels and relocs */ -static struct uasm_label labels[128] __initdata; -static struct uasm_reloc relocs[128] __initdata; +static struct uasm_label labels[128] __cpuinitdata; +static struct uasm_reloc relocs[128] __cpuinitdata; /* * The R3000 TLB handler is simple. */ -static void __init build_r3000_tlb_refill_handler(void) +static void __cpuinit build_r3000_tlb_refill_handler(void) { long pgdc = (long)pgd_current; u32 *p; @@ -197,7 +197,7 @@ static void __init build_r3000_tlb_refill_handler(void) * other one.To keep things simple, we first assume linear space, * then we relocate it to the final handler layout as needed. */ -static u32 final_handler[64] __initdata; +static u32 final_handler[64] __cpuinitdata; /* * Hazards @@ -221,7 +221,7 @@ static u32 final_handler[64] __initdata; * * As if we MIPS hackers wouldn't know how to nop pipelines happy ... */ -static void __init __maybe_unused build_tlb_probe_entry(u32 **p) +static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p) { switch (current_cpu_type()) { /* Found by experiment: R4600 v2.0 needs this, too. */ @@ -245,7 +245,7 @@ static void __init __maybe_unused build_tlb_probe_entry(u32 **p) */ enum tlb_write_entry { tlb_random, tlb_indexed }; -static void __init build_tlb_write_entry(u32 **p, struct uasm_label **l, +static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, struct uasm_reloc **r, enum tlb_write_entry wmode) { @@ -389,7 +389,7 @@ static void __init build_tlb_write_entry(u32 **p, struct uasm_label **l, * TMP and PTR are scratch. * TMP will be clobbered, PTR will hold the pmd entry. */ -static void __init +static void __cpuinit build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, unsigned int ptr) { @@ -450,7 +450,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, * BVADDR is the faulting address, PTR is scratch. * PTR will hold the pgd for vmalloc. */ -static void __init +static void __cpuinit build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int bvaddr, unsigned int ptr) { @@ -522,7 +522,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, * TMP and PTR are scratch. * TMP will be clobbered, PTR will hold the pgd entry. */ -static void __init __maybe_unused +static void __cpuinit __maybe_unused build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) { long pgdc = (long)pgd_current; @@ -557,7 +557,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) #endif /* !CONFIG_64BIT */ -static void __init build_adjust_context(u32 **p, unsigned int ctx) +static void __cpuinit build_adjust_context(u32 **p, unsigned int ctx) { unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); @@ -583,7 +583,7 @@ static void __init build_adjust_context(u32 **p, unsigned int ctx) uasm_i_andi(p, ctx, ctx, mask); } -static void __init build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) +static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) { /* * Bug workaround for the Nevada. It seems as if under certain @@ -608,7 +608,7 @@ static void __init build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) UASM_i_ADDU(p, ptr, ptr, tmp); /* add in offset */ } -static void __init build_update_entries(u32 **p, unsigned int tmp, +static void __cpuinit build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) { /* @@ -651,7 +651,7 @@ static void __init build_update_entries(u32 **p, unsigned int tmp, #endif } -static void __init build_r4000_tlb_refill_handler(void) +static void __cpuinit build_r4000_tlb_refill_handler(void) { u32 *p = tlb_handler; struct uasm_label *l = labels; @@ -783,7 +783,7 @@ u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned; u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned; u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned; -static void __init +static void __cpuinit iPTE_LW(u32 **p, struct uasm_label **l, unsigned int pte, unsigned int ptr) { #ifdef CONFIG_SMP @@ -803,7 +803,7 @@ iPTE_LW(u32 **p, struct uasm_label **l, unsigned int pte, unsigned int ptr) #endif } -static void __init +static void __cpuinit iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, unsigned int mode) { @@ -863,7 +863,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, * the page table where this PTE is located, PTE will be re-loaded * with it's original value. */ -static void __init +static void __cpuinit build_pte_present(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, enum label_id lid) { @@ -874,7 +874,7 @@ build_pte_present(u32 **p, struct uasm_label **l, struct uasm_reloc **r, } /* Make PTE valid, store result in PTR. */ -static void __init +static void __cpuinit build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr) { @@ -887,7 +887,7 @@ build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte, * Check if PTE can be written to, if not branch to LABEL. Regardless * restore PTE with value from PTR when done. */ -static void __init +static void __cpuinit build_pte_writable(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, enum label_id lid) { @@ -900,7 +900,7 @@ build_pte_writable(u32 **p, struct uasm_label **l, struct uasm_reloc **r, /* Make PTE writable, update software status bits as well, then store * at PTR. */ -static void __init +static void __cpuinit build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr) { @@ -914,7 +914,7 @@ build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte, * Check if PTE can be modified, if not branch to LABEL. Regardless * restore PTE with value from PTR when done. */ -static void __init +static void __cpuinit build_pte_modifiable(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, enum label_id lid) { @@ -931,7 +931,7 @@ build_pte_modifiable(u32 **p, struct uasm_label **l, struct uasm_reloc **r, * This places the pte into ENTRYLO0 and writes it with tlbwi. * Then it returns. */ -static void __init +static void __cpuinit build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp) { uasm_i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */ @@ -947,7 +947,7 @@ build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp) * may have the probe fail bit set as a result of a trap on a * kseg2 access, i.e. without refill. Then it returns. */ -static void __init +static void __cpuinit build_r3000_tlb_reload_write(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int pte, unsigned int tmp) @@ -965,7 +965,7 @@ build_r3000_tlb_reload_write(u32 **p, struct uasm_label **l, uasm_i_rfe(p); /* branch delay */ } -static void __init +static void __cpuinit build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte, unsigned int ptr) { @@ -985,7 +985,7 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte, uasm_i_tlbp(p); /* load delay */ } -static void __init build_r3000_tlb_load_handler(void) +static void __cpuinit build_r3000_tlb_load_handler(void) { u32 *p = handle_tlbl; struct uasm_label *l = labels; @@ -1015,7 +1015,7 @@ static void __init build_r3000_tlb_load_handler(void) dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); } -static void __init build_r3000_tlb_store_handler(void) +static void __cpuinit build_r3000_tlb_store_handler(void) { u32 *p = handle_tlbs; struct uasm_label *l = labels; @@ -1045,7 +1045,7 @@ static void __init build_r3000_tlb_store_handler(void) dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); } -static void __init build_r3000_tlb_modify_handler(void) +static void __cpuinit build_r3000_tlb_modify_handler(void) { u32 *p = handle_tlbm; struct uasm_label *l = labels; @@ -1078,7 +1078,7 @@ static void __init build_r3000_tlb_modify_handler(void) /* * R4000 style TLB load/store/modify handlers. */ -static void __init +static void __cpuinit build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int pte, unsigned int ptr) @@ -1103,7 +1103,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l, build_tlb_probe_entry(p); } -static void __init +static void __cpuinit build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, unsigned int ptr) @@ -1120,7 +1120,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l, #endif } -static void __init build_r4000_tlb_load_handler(void) +static void __cpuinit build_r4000_tlb_load_handler(void) { u32 *p = handle_tlbl; struct uasm_label *l = labels; @@ -1160,7 +1160,7 @@ static void __init build_r4000_tlb_load_handler(void) dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); } -static void __init build_r4000_tlb_store_handler(void) +static void __cpuinit build_r4000_tlb_store_handler(void) { u32 *p = handle_tlbs; struct uasm_label *l = labels; @@ -1191,7 +1191,7 @@ static void __init build_r4000_tlb_store_handler(void) dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); } -static void __init build_r4000_tlb_modify_handler(void) +static void __cpuinit build_r4000_tlb_modify_handler(void) { u32 *p = handle_tlbm; struct uasm_label *l = labels; @@ -1223,7 +1223,7 @@ static void __init build_r4000_tlb_modify_handler(void) dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); } -void __init build_tlb_refill_handler(void) +void __cpuinit build_tlb_refill_handler(void) { /* * The refill handler is generated per-CPU, multi-node systems @@ -1269,7 +1269,7 @@ void __init build_tlb_refill_handler(void) } } -void __init flush_tlb_handlers(void) +void __cpuinit flush_tlb_handlers(void) { flush_icache_range((unsigned long)handle_tlbl, (unsigned long)handle_tlbl + sizeof(handle_tlbl)); diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index e3f74ed5f704..1a6f7704cc89 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -82,7 +82,7 @@ struct insn { | (e) << RE_SH \ | (f) << FUNC_SH) -static struct insn insn_table[] __initdata = { +static struct insn insn_table[] __cpuinitdata = { { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, @@ -135,7 +135,7 @@ static struct insn insn_table[] __initdata = { #undef M -static inline __init u32 build_rs(u32 arg) +static inline __cpuinit u32 build_rs(u32 arg) { if (arg & ~RS_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -143,7 +143,7 @@ static inline __init u32 build_rs(u32 arg) return (arg & RS_MASK) << RS_SH; } -static inline __init u32 build_rt(u32 arg) +static inline __cpuinit u32 build_rt(u32 arg) { if (arg & ~RT_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -151,7 +151,7 @@ static inline __init u32 build_rt(u32 arg) return (arg & RT_MASK) << RT_SH; } -static inline __init u32 build_rd(u32 arg) +static inline __cpuinit u32 build_rd(u32 arg) { if (arg & ~RD_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -159,7 +159,7 @@ static inline __init u32 build_rd(u32 arg) return (arg & RD_MASK) << RD_SH; } -static inline __init u32 build_re(u32 arg) +static inline __cpuinit u32 build_re(u32 arg) { if (arg & ~RE_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -167,7 +167,7 @@ static inline __init u32 build_re(u32 arg) return (arg & RE_MASK) << RE_SH; } -static inline __init u32 build_simm(s32 arg) +static inline __cpuinit u32 build_simm(s32 arg) { if (arg > 0x7fff || arg < -0x8000) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -175,7 +175,7 @@ static inline __init u32 build_simm(s32 arg) return arg & 0xffff; } -static inline __init u32 build_uimm(u32 arg) +static inline __cpuinit u32 build_uimm(u32 arg) { if (arg & ~IMM_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -183,7 +183,7 @@ static inline __init u32 build_uimm(u32 arg) return arg & IMM_MASK; } -static inline __init u32 build_bimm(s32 arg) +static inline __cpuinit u32 build_bimm(s32 arg) { if (arg > 0x1ffff || arg < -0x20000) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -194,7 +194,7 @@ static inline __init u32 build_bimm(s32 arg) return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); } -static inline __init u32 build_jimm(u32 arg) +static inline __cpuinit u32 build_jimm(u32 arg) { if (arg & ~((JIMM_MASK) << 2)) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -202,7 +202,7 @@ static inline __init u32 build_jimm(u32 arg) return (arg >> 2) & JIMM_MASK; } -static inline __init u32 build_func(u32 arg) +static inline __cpuinit u32 build_func(u32 arg) { if (arg & ~FUNC_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -210,7 +210,7 @@ static inline __init u32 build_func(u32 arg) return arg & FUNC_MASK; } -static inline __init u32 build_set(u32 arg) +static inline __cpuinit u32 build_set(u32 arg) { if (arg & ~SET_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -222,7 +222,7 @@ static inline __init u32 build_set(u32 arg) * The order of opcode arguments is implicitly left to right, * starting with RS and ending with FUNC or IMM. */ -static void __init build_insn(u32 **buf, enum opcode opc, ...) +static void __cpuinit build_insn(u32 **buf, enum opcode opc, ...) { struct insn *ip = NULL; unsigned int i; @@ -375,14 +375,14 @@ I_u3u1u2(_xor) I_u2u1u3(_xori) /* Handle labels. */ -void __init uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) +void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) { (*lab)->addr = addr; (*lab)->lab = lid; (*lab)++; } -int __init uasm_in_compat_space_p(long addr) +int __cpuinit uasm_in_compat_space_p(long addr) { /* Is this address in 32bit compat space? */ #ifdef CONFIG_64BIT @@ -392,7 +392,7 @@ int __init uasm_in_compat_space_p(long addr) #endif } -int __init uasm_rel_highest(long val) +int __cpuinit uasm_rel_highest(long val) { #ifdef CONFIG_64BIT return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; @@ -401,7 +401,7 @@ int __init uasm_rel_highest(long val) #endif } -int __init uasm_rel_higher(long val) +int __cpuinit uasm_rel_higher(long val) { #ifdef CONFIG_64BIT return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; @@ -410,17 +410,17 @@ int __init uasm_rel_higher(long val) #endif } -int __init uasm_rel_hi(long val) +int __cpuinit uasm_rel_hi(long val) { return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; } -int __init uasm_rel_lo(long val) +int __cpuinit uasm_rel_lo(long val) { return ((val & 0xffff) ^ 0x8000) - 0x8000; } -void __init UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) +void __cpuinit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) { if (!uasm_in_compat_space_p(addr)) { uasm_i_lui(buf, rs, uasm_rel_highest(addr)); @@ -436,7 +436,7 @@ void __init UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) uasm_i_lui(buf, rs, uasm_rel_hi(addr)); } -void __init UASM_i_LA(u32 **buf, unsigned int rs, long addr) +void __cpuinit UASM_i_LA(u32 **buf, unsigned int rs, long addr) { UASM_i_LA_mostly(buf, rs, addr); if (uasm_rel_lo(addr)) { @@ -448,7 +448,7 @@ void __init UASM_i_LA(u32 **buf, unsigned int rs, long addr) } /* Handle relocations. */ -void __init +void __cpuinit uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) { (*rel)->addr = addr; @@ -457,7 +457,7 @@ uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) (*rel)++; } -static inline void __init +static inline void __cpuinit __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { long laddr = (long)lab->addr; @@ -474,7 +474,7 @@ __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) } } -void __init +void __cpuinit uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { struct uasm_label *l; @@ -485,7 +485,7 @@ uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) __resolve_relocs(rel, l); } -void __init +void __cpuinit uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off) { for (; rel->lab != UASM_LABEL_INVALID; rel++) @@ -493,7 +493,7 @@ uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off) rel->addr += off; } -void __init +void __cpuinit uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off) { for (; lab->lab != UASM_LABEL_INVALID; lab++) @@ -501,7 +501,7 @@ uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off) lab->addr += off; } -void __init +void __cpuinit uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, u32 *end, u32 *target) { @@ -513,7 +513,7 @@ uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, uasm_move_labels(lab, first, end, off); } -int __init uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) +int __cpuinit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) { for (; rel->lab != UASM_LABEL_INVALID; rel++) { if (rel->addr == addr @@ -526,49 +526,49 @@ int __init uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) } /* Convenience functions for labeled branches. */ -void __init +void __cpuinit uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bltz(p, reg, 0); } -void __init +void __cpuinit uasm_il_b(u32 **p, struct uasm_reloc **r, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_b(p, 0); } -void __init +void __cpuinit uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_beqz(p, reg, 0); } -void __init +void __cpuinit uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_beqzl(p, reg, 0); } -void __init +void __cpuinit uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bnez(p, reg, 0); } -void __init +void __cpuinit uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bgezl(p, reg, 0); } -void __init +void __cpuinit uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); diff --git a/arch/mips/mm/uasm.h b/arch/mips/mm/uasm.h index a10fc1135c76..fe0574f6e77d 100644 --- a/arch/mips/mm/uasm.h +++ b/arch/mips/mm/uasm.h @@ -11,38 +11,38 @@ #include #define Ip_u1u2u3(op) \ -void __init \ +void __cpuinit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u2u1u3(op) \ -void __init \ +void __cpuinit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u3u1u2(op) \ -void __init \ +void __cpuinit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u1u2s3(op) \ -void __init \ +void __cpuinit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2s3u1(op) \ -void __init \ +void __cpuinit \ uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c) #define Ip_u2u1s3(op) \ -void __init \ +void __cpuinit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u1u2(op) \ -void __init uasm_i##op(u32 **buf, unsigned int a, unsigned int b) +void __cpuinit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) #define Ip_u1s2(op) \ -void __init uasm_i##op(u32 **buf, unsigned int a, signed int b) +void __cpuinit uasm_i##op(u32 **buf, unsigned int a, signed int b) -#define Ip_u1(op) void __init uasm_i##op(u32 **buf, unsigned int a) +#define Ip_u1(op) void __cpuinit uasm_i##op(u32 **buf, unsigned int a) -#define Ip_0(op) void __init uasm_i##op(u32 **buf) +#define Ip_0(op) void __cpuinit uasm_i##op(u32 **buf) Ip_u2u1s3(_addiu); Ip_u3u1u2(_addu); @@ -98,19 +98,19 @@ struct uasm_label { int lab; }; -void __init uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); +void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); #ifdef CONFIG_64BIT -int __init uasm_in_compat_space_p(long addr); -int __init uasm_rel_highest(long val); -int __init uasm_rel_higher(long val); +int uasm_in_compat_space_p(long addr); +int uasm_rel_highest(long val); +int uasm_rel_higher(long val); #endif -int __init uasm_rel_hi(long val); -int __init uasm_rel_lo(long val); -void __init UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr); -void __init UASM_i_LA(u32 **buf, unsigned int rs, long addr); +int uasm_rel_hi(long val); +int uasm_rel_lo(long val); +void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr); +void UASM_i_LA(u32 **buf, unsigned int rs, long addr); #define UASM_L_LA(lb) \ -static inline void __init uasm_l##lb(struct uasm_label **lab, u32 *addr) \ +static inline void __cpuinit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ { \ uasm_build_label(lab, addr, label##lb); \ } @@ -164,29 +164,19 @@ struct uasm_reloc { /* This is zero so we can use zeroed label arrays. */ #define UASM_LABEL_INVALID 0 -void __init uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid); -void __init -uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab); -void __init -uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off); -void __init -uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off); -void __init -uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, - u32 *end, u32 *target); -int __init uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr); +void uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid); +void uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab); +void uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off); +void uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off); +void uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, + u32 *first, u32 *end, u32 *target); +int uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr); /* Convenience functions for labeled branches. */ -void __init -uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); -void __init uasm_il_b(u32 **p, struct uasm_reloc **r, int lid); -void __init -uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); -void __init -uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); -void __init -uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); -void __init -uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); -void __init -uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid); +void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index a322543ac34e..bb64828a92fe 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -40,7 +40,7 @@ int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; extern struct pci_ops bridge_pci_ops; -int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) +int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid) { unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index f9471d77c096..358ad6210949 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -260,7 +260,7 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev, } } -void pcibios_fixup_bus(struct pci_bus *bus) +void __devinit pcibios_fixup_bus(struct pci_bus *bus) { /* Propagate hose info into the subordinate devices. */ diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index a49e7c85f724..7093e7c573a4 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -53,7 +53,7 @@ extern void pcibr_setup(cnodeid_t); extern void xtalk_probe_node(cnodeid_t nid); -static void __init per_hub_init(cnodeid_t cnode) +static void __cpuinit per_hub_init(cnodeid_t cnode) { struct hub_data *hub = hub_data(cnode); nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 08d45369be45..25d3baf0ebc4 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -285,7 +285,7 @@ void __cpuinit cpu_time_init(void) set_c0_status(SRB_TIMOCLK); } -void __init hub_rtc_init(cnodeid_t cnode) +void __cpuinit hub_rtc_init(cnodeid_t cnode) { /* * We only need to initialize the current node. diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index fc82f34a32ce..6ae64e8dfc40 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -22,7 +22,7 @@ extern int bridge_probe(nasid_t nasid, int widget, int masterwid); -static int __init probe_one_port(nasid_t nasid, int widget, int masterwid) +static int __cpuinit probe_one_port(nasid_t nasid, int widget, int masterwid) { widgetreg_t widget_id; xwidget_part_num_t partnum; @@ -46,7 +46,7 @@ static int __init probe_one_port(nasid_t nasid, int widget, int masterwid) return 0; } -static int __init xbow_probe(nasid_t nasid) +static int __cpuinit xbow_probe(nasid_t nasid) { lboard_t *brd; klxbow_t *xbow_p; @@ -99,7 +99,7 @@ static int __init xbow_probe(nasid_t nasid) return 0; } -void __init xtalk_probe_node(cnodeid_t nid) +void __cpuinit xtalk_probe_node(cnodeid_t nid) { volatile u64 hubreg; nasid_t nasid; diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h index 4933b4947ed0..01e7eadc97e2 100644 --- a/include/asm-mips/cacheflush.h +++ b/include/asm-mips/cacheflush.h @@ -93,7 +93,7 @@ extern void (*flush_data_cache_page)(unsigned long addr); clear_bit(PG_dcache_dirty, &(page)->flags) /* Run kernel code uncached, useful for cache probing functions. */ -unsigned long __init run_uncached(void *func); +unsigned long run_uncached(void *func); extern void *kmap_coherent(struct page *page, unsigned long addr); extern void kunmap_coherent(void); -- cgit v1.2.3-55-g7522 From 2ac7401d11370b7a8e3a1c74aac03a021fd61048 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 10 Mar 2008 09:31:50 +0000 Subject: [MIPS] Fix yosemite build error didn't pickup the definition of PKMAP_BASE from fixmap.h, ugh. Signed-off-by: Ralf Baechle --- include/asm-mips/highmem.h | 1 - include/asm-mips/pgtable-32.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-mips/highmem.h b/include/asm-mips/highmem.h index 4d6bd5c31c7b..4374ab2adc75 100644 --- a/include/asm-mips/highmem.h +++ b/include/asm-mips/highmem.h @@ -39,7 +39,6 @@ extern pte_t *pkmap_page_table; * easily, subsequent pte tables have to be allocated in one physical * chunk of RAM. */ -#define PKMAP_BASE (0xfe000000UL) #define LAST_PKMAP 1024 #define LAST_PKMAP_MASK (LAST_PKMAP-1) #define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) diff --git a/include/asm-mips/pgtable-32.h b/include/asm-mips/pgtable-32.h index a0947092d0e0..ceefe027c761 100644 --- a/include/asm-mips/pgtable-32.h +++ b/include/asm-mips/pgtable-32.h @@ -65,6 +65,8 @@ extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, #define VMALLOC_START MAP_BASE +#define PKMAP_BASE (0xfe000000UL) + #ifdef CONFIG_HIGHMEM # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) #else -- cgit v1.2.3-55-g7522 From 127f1668617ae638f90f113a32f956887acbb94a Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 20 Feb 2008 23:11:53 +0900 Subject: [MIPS] Lasat: fix LASAT_CASCADE_IRQ Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle --- include/asm-mips/mach-lasat/irq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-mips/mach-lasat/irq.h b/include/asm-mips/mach-lasat/irq.h index da75f89f3723..3a282419d5f9 100644 --- a/include/asm-mips/mach-lasat/irq.h +++ b/include/asm-mips/mach-lasat/irq.h @@ -1,7 +1,7 @@ #ifndef _ASM_MACH_LASAT_IRQ_H #define _ASM_MACH_LASAT_IRQ_H -#define LASAT_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 0) +#define LASAT_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 2) #define LASAT_IRQ_BASE 8 #define LASAT_IRQ_END 23 -- cgit v1.2.3-55-g7522 From 69e634f1e27c8e5b954ea4be2d05dd744cabc0bc Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 12 Mar 2008 13:58:10 +0000 Subject: [MIPS] Clocksource: Only install r4k counter as clocksource if present. Signed-off-by: Ralf Baechle --- arch/mips/kernel/csrc-r4k.c | 7 ++++++- include/asm-mips/time.h | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c index 0e2b5cd81f67..86e026f067bc 100644 --- a/arch/mips/kernel/csrc-r4k.c +++ b/arch/mips/kernel/csrc-r4k.c @@ -22,12 +22,17 @@ static struct clocksource clocksource_mips = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -void __init init_mips_clocksource(void) +int __init init_mips_clocksource(void) { + if (!cpu_has_counter || !mips_hpt_frequency) + return -ENXIO; + /* Calclate a somewhat reasonable rating value */ clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); clocksource_register(&clocksource_mips); + + return 0; } diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index a8fd16e1981f..d3bd5c5aa2ec 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -64,10 +64,11 @@ static inline int mips_clockevent_init(void) * Initialize the count register as a clocksource */ #ifdef CONFIG_CEVT_R4K -extern void init_mips_clocksource(void); +extern int init_mips_clocksource(void); #else -static inline void init_mips_clocksource(void) +static inline int init_mips_clocksource(void) { + return 0; } #endif -- cgit v1.2.3-55-g7522 From 0738c4bb8f2a8bf15178f852494643b0981f578b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 12 Mar 2008 16:51:31 +0900 Subject: nommu: Provide is_vmalloc_addr() stub. Introduced in commit-id 9e2779fa281cfda13ac060753d674bbcaa23367e and ifdef'ed out for nommu in 8ca3ed87db062201e1fa15b64a9214e193fc3a8a, both approaches end up breaking the nommu build in different ways. An impressive feat for a 2-liner. Current is_vmalloc_addr() users fall in to two camps: - Determining whether to use vfree()/kfree() - Whether to do vmlist traversal (only /proc/kcore). Since we don't support /proc/kcore on nommu, that leaves the vfree()/kfree() determination use cases. nommu vfree() happens to be a wrapper to kfree() anyways, so is_vmalloc_addr() can always return 0 and end up with the right behaviour. Signed-off-by: Paul Mundt Signed-off-by: Linus Torvalds --- include/linux/mm.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index 3f3ccfe42de0..b695875d63e3 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -235,15 +235,22 @@ static inline int get_page_unless_zero(struct page *page) struct page *vmalloc_to_page(const void *addr); unsigned long vmalloc_to_pfn(const void *addr); -#ifdef CONFIG_MMU -/* Determine if an address is within the vmalloc range */ +/* + * Determine if an address is within the vmalloc range + * + * On nommu, vmalloc/vfree wrap through kmalloc/kfree directly, so there + * is no special casing required. + */ static inline int is_vmalloc_addr(const void *x) { +#ifdef CONFIG_MMU unsigned long addr = (unsigned long)x; return addr >= VMALLOC_START && addr < VMALLOC_END; -} +#else + return 0; #endif +} static inline struct page *compound_head(struct page *page) { -- cgit v1.2.3-55-g7522 From a8ae50ba9336ff77d0df0943ac27b79ba0a5a521 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 12 Mar 2008 17:52:56 +0100 Subject: Remove from user-visible headers. It was all wrapped in '#ifdef CONFIG_BLOCK' anyway, so userspace was getting nothing useful out of it. And the special #ifndef __KERNEL__ version of 'struct partition' makes me inclined to promote an attitude of violence... Stick some comments on some of the #endifs too, while we're at it. Signed-off-by: David Woodhouse Signed-off-by: Linus Torvalds --- include/linux/Kbuild | 1 - include/linux/genhd.h | 30 +++--------------------------- 2 files changed, 3 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 994df3780007..0fac822c1157 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -205,7 +205,6 @@ unifdef-y += futex.h unifdef-y += fs.h unifdef-y += gameport.h unifdef-y += generic_serial.h -unifdef-y += genhd.h unifdef-y += gfs2_ondisk.h unifdef-y += hayesesp.h unifdef-y += hdlcdrv.h diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 32c2ac49a070..ecd2bf63fc84 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -55,24 +55,6 @@ enum { UNIXWARE_PARTITION = 0x63, /* Same as GNU_HURD and SCO Unix */ }; -#ifndef __KERNEL__ - -struct partition { - unsigned char boot_ind; /* 0x80 - active */ - unsigned char head; /* starting head */ - unsigned char sector; /* starting sector */ - unsigned char cyl; /* starting cylinder */ - unsigned char sys_ind; /* What partition type */ - unsigned char end_head; /* end head */ - unsigned char end_sector; /* end sector */ - unsigned char end_cyl; /* end cylinder */ - unsigned int start_sect; /* starting sector counting from 0 */ - unsigned int nr_sects; /* nr of sectors in partition */ -} __attribute__((packed)); - -#endif - -#ifdef __KERNEL__ #include #include #include @@ -228,7 +210,7 @@ static inline void part_stat_set_all(struct hd_struct *part, int value) { sizeof(struct disk_stats)); } -#else +#else /* !CONFIG_SMP */ #define __disk_stat_add(gendiskp, field, addnd) \ (gendiskp->dkstats.field += addnd) #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) @@ -256,7 +238,7 @@ static inline void part_stat_set_all(struct hd_struct *part, int value) memset(&part->dkstats, value, sizeof(struct disk_stats)); } -#endif +#endif /* CONFIG_SMP */ #define disk_stat_add(gendiskp, field, addnd) \ do { \ @@ -395,8 +377,6 @@ static inline void set_capacity(struct gendisk *disk, sector_t size) disk->capacity = size; } -#endif /* __KERNEL__ */ - #ifdef CONFIG_SOLARIS_X86_PARTITION #define SOLARIS_X86_NUMSLICE 16 @@ -540,8 +520,6 @@ struct unixware_disklabel { # define MINIX_NR_SUBPARTITIONS 4 #endif /* CONFIG_MINIX_SUBPARTITION */ -#ifdef __KERNEL__ - #define ADDPART_FLAG_NONE 0 #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 @@ -570,8 +548,6 @@ static inline struct block_device *bdget_disk(struct gendisk *disk, int index) return bdget(MKDEV(disk->major, disk->first_minor) + index); } -#endif - #else /* CONFIG_BLOCK */ static inline void printk_all_partitions(void) { } @@ -584,4 +560,4 @@ static inline dev_t blk_lookup_devt(const char *name) #endif /* CONFIG_BLOCK */ -#endif +#endif /* _LINUX_GENHD_H */ -- cgit v1.2.3-55-g7522 From 07c941d00087581c9553661c2c4fb593da37f525 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 12 Mar 2008 10:48:48 +1100 Subject: [POWERPC] Fix undefined pmu_sys_suspended compilation error pmu_sys_suspended is declared extern when: defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) but only defined when: defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) which is wrong. Let's fix that. Signed-off-by: Tony Breeds Signed-off-by: Paul Mackerras --- include/linux/pmu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/pmu.h b/include/linux/pmu.h index 4c5f65392d36..b02b57c0fba0 100644 --- a/include/linux/pmu.h +++ b/include/linux/pmu.h @@ -192,7 +192,7 @@ extern unsigned int pmu_power_flags; extern void pmu_backlight_init(void); /* some code needs to know if the PMU was suspended for hibernation */ -#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) +#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) extern int pmu_sys_suspended; #else /* if power management is not configured it can't be suspended */ -- cgit v1.2.3-55-g7522 From a99d9a6ebdf8328d5c61ca9f1038f4815e25720e Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 12 Mar 2008 10:48:48 +1100 Subject: [POWERPC] Fix drivers/macintosh/mediabay.c when !CONFIG_ADB_PMU When building drivers/macintosh/mediabay.c if CONFIG_ADB_PMU isn't defined we get: drivers/built-in.o: In function `media_bay_step': mediabay.c:(.text+0x92b84): undefined reference to `pmu_suspend' mediabay.c:(.text+0x92c08): undefined reference to `pmu_resume' Create empty place holders in that scenario. Signed-off-by: Tony Breeds Signed-off-by: Paul Mackerras --- include/linux/pmu.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/linux/pmu.h b/include/linux/pmu.h index b02b57c0fba0..cafe98d96948 100644 --- a/include/linux/pmu.h +++ b/include/linux/pmu.h @@ -147,8 +147,15 @@ extern void pmu_wait_complete(struct adb_request *req); /* For use before switching interrupts off for a long time; * warning: not stackable */ +#if defined(CONFIG_ADB_PMU) extern void pmu_suspend(void); extern void pmu_resume(void); +#else +static inline void pmu_suspend(void) +{} +static inline void pmu_resume(void) +{} +#endif extern void pmu_enable_irled(int on); -- cgit v1.2.3-55-g7522 From f1dd9c379cac7d5a76259e7dffcd5f8edc697d17 Mon Sep 17 00:00:00 2001 From: Zhang Yanmin Date: Wed, 12 Mar 2008 22:52:37 -0700 Subject: [NET]: Fix tbench regression in 2.6.25-rc1 Comparing with kernel 2.6.24, tbench result has regression with 2.6.25-rc1. 1) On 2 quad-core processor stoakley: 4%. 2) On 4 quad-core processor tigerton: more than 30%. bisect located below patch. b4ce92775c2e7ff9cf79cca4e0a19c8c5fd6287b is first bad commit commit b4ce92775c2e7ff9cf79cca4e0a19c8c5fd6287b Author: Herbert Xu Date: Tue Nov 13 21:33:32 2007 -0800 [IPV6]: Move nfheader_len into rt6_info The dst member nfheader_len is only used by IPv6. It's also currently creating a rather ugly alignment hole in struct dst. Therefore this patch moves it from there into struct rt6_info. Above patch changes the cache line alignment, especially member __refcnt. I did a testing by adding 2 unsigned long pading before lastuse, so the 3 members, lastuse/__refcnt/__use, are moved to next cache line. The performance is recovered. I created a patch to rearrange the members in struct dst_entry. With Eric and Valdis Kletnieks's suggestion, I made finer arrangement. 1) Move tclassid under ops in case CONFIG_NET_CLS_ROUTE=y. So sizeof(dst_entry)=200 no matter if CONFIG_NET_CLS_ROUTE=y/n. I tested many patches on my 16-core tigerton by moving tclassid to different place. It looks like tclassid could also have impact on performance. If moving tclassid before metrics, or just don't move tclassid, the performance isn't good. So I move it behind metrics. 2) Add comments before __refcnt. On 16-core tigerton: If CONFIG_NET_CLS_ROUTE=y, the result with below patch is about 18% better than the one without the patch; If CONFIG_NET_CLS_ROUTE=n, the result with below patch is about 30% better than the one without the patch. With 32bit 2.6.25-rc1 on 8-core stoakley, the new patch doesn't introduce regression. Thank Eric, Valdis, and David! Signed-off-by: Zhang Yanmin Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/dst.h | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/net/dst.h b/include/net/dst.h index e3ac7d0fc4e1..ae13370e8484 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -52,15 +52,10 @@ struct dst_entry unsigned short header_len; /* more space at head required */ unsigned short trailer_len; /* space to reserve at tail */ - u32 metrics[RTAX_MAX]; - struct dst_entry *path; - - unsigned long rate_last; /* rate limiting for ICMP */ unsigned int rate_tokens; + unsigned long rate_last; /* rate limiting for ICMP */ -#ifdef CONFIG_NET_CLS_ROUTE - __u32 tclassid; -#endif + struct dst_entry *path; struct neighbour *neighbour; struct hh_cache *hh; @@ -70,10 +65,20 @@ struct dst_entry int (*output)(struct sk_buff*); struct dst_ops *ops; - - unsigned long lastuse; + + u32 metrics[RTAX_MAX]; + +#ifdef CONFIG_NET_CLS_ROUTE + __u32 tclassid; +#endif + + /* + * __refcnt wants to be on a different cache line from + * input/output/ops or performance tanks badly + */ atomic_t __refcnt; /* client references */ int __use; + unsigned long lastuse; union { struct dst_entry *next; struct rtable *rt_next; -- cgit v1.2.3-55-g7522 From cc74d96f47b0d916840f92092595e3be9731e047 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Mar 2008 21:48:03 -0700 Subject: PCI: fix issue with busses registering multiple times in sysfs PCI busses can be registered multiple times, so we need to detect if we have registered our bus structure in sysfs already. If so, don't do it again. Thanks to Guennadi Liakhovetski for reporting the problem, and to Linus for poking me to get me to believe that it was a real problem. Cc: Linus Torvalds Cc: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/pci/bus.c | 6 +++++- include/linux/pci.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 6a9403d79e0c..d708358326e5 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -143,14 +143,18 @@ void pci_bus_add_devices(struct pci_bus *bus) /* register the bus with sysfs as the parent is now * properly registered. */ child_bus = dev->subordinate; + if (child_bus->is_added) + continue; child_bus->dev.parent = child_bus->bridge; retval = device_register(&child_bus->dev); if (retval) dev_err(&dev->dev, "Error registering pci_bus," " continuing...\n"); - else + else { + child_bus->is_added = 1; retval = device_create_file(&child_bus->dev, &dev_attr_cpuaffinity); + } if (retval) dev_err(&dev->dev, "Error creating cpuaffinity" " file, continuing...\n"); diff --git a/include/linux/pci.h b/include/linux/pci.h index 38eff1947750..9010f5458767 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -278,6 +278,7 @@ struct pci_bus { struct device dev; struct bin_attribute *legacy_io; /* legacy I/O for this bus */ struct bin_attribute *legacy_mem; /* legacy mem */ + unsigned int is_added:1; }; #define pci_bus_b(n) list_entry(n, struct pci_bus, node) -- cgit v1.2.3-55-g7522 From 12d48739d0b5d96efe6b7d26107f5572c6215f4a Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Thu, 13 Mar 2008 12:32:37 -0700 Subject: h8300: fix recent uaccess breakage Al Viro wrote: > > After that commit in asm-h8300/uaccess.h we have > > #define get_user(x, ptr) \ > ({ \ > int __gu_err = 0; \ > uint32_t __gu_val = 0; \ > ^^^^^^^^^^^^^^^^^ > switch (sizeof(*(ptr))) { \ > case 1: \ > case 2: \ > case 4: \ > __gu_val = *(ptr); \ > break; \ > case 8: \ > memcpy(&__gu_val, ptr, sizeof (*(ptr))); \ > ^^^^^^^^^^^^^^^^ > > which, of course, is FUBAR whenever we actually hit that case - memcpy of > 8 bytes into uint32_t is obviously wrong. Why don't we simply do Cc: Al Viro Signed-off-by: Yoshinori Sato Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-h8300/uaccess.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/asm-h8300/uaccess.h b/include/asm-h8300/uaccess.h index a22350ec271a..356068cd0879 100644 --- a/include/asm-h8300/uaccess.h +++ b/include/asm-h8300/uaccess.h @@ -91,22 +91,19 @@ extern int __put_user_bad(void); #define get_user(x, ptr) \ ({ \ int __gu_err = 0; \ - uint32_t __gu_val = 0; \ + typeof(*(ptr)) __gu_val = *ptr; \ switch (sizeof(*(ptr))) { \ case 1: \ case 2: \ case 4: \ - __gu_val = *(ptr); \ - break; \ - case 8: \ - memcpy(&__gu_val, ptr, sizeof (*(ptr))); \ + case 8: \ break; \ default: \ - __gu_val = 0; \ __gu_err = __get_user_bad(); \ + __gu_val = 0; \ break; \ } \ - (x) = (typeof(*(ptr)))__gu_val; \ + (x) = __gu_val; \ __gu_err; \ }) #define __get_user(x, ptr) get_user(x, ptr) -- cgit v1.2.3-55-g7522 From 9b89ca7a3847c0d5b1e86e83f4860a866f28a89b Mon Sep 17 00:00:00 2001 From: Marc Dionne Date: Fri, 14 Mar 2008 13:11:29 +0000 Subject: struct export_operations: adjust comments to match current members The comments in the definition of struct export_operations don't match the current members. Add a comment for the 2 new functions and remove 2 comments for unused ones. Signed-off-by: Marc Dionne Acked-by: David Howells Acked-by: Christoph Hellwig Signed-off-by: Linus Torvalds --- include/linux/exportfs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 51d214138814..adcbb05b120b 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -49,11 +49,11 @@ struct fid { /** * struct export_operations - for nfsd to communicate with file systems - * @decode_fh: decode a file handle fragment and return a &struct dentry * @encode_fh: encode a file handle fragment from a dentry + * @fh_to_dentry: find the implied object and get a dentry for it + * @fh_to_parent: find the implied object's parent and get a dentry for it * @get_name: find the name for a given inode in a given directory * @get_parent: find the parent of a given directory - * @get_dentry: find a dentry for the inode given a file handle sub-fragment * * See Documentation/filesystems/Exporting for details on how to use * this interface correctly. -- cgit v1.2.3-55-g7522 From ff80c66ab637df825122558d1f3f3cbdd830f962 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 18 Feb 2008 14:00:18 -0800 Subject: [PARISC] wire up timerfd syscalls Signed-off-by: Kyle McMartin --- arch/parisc/kernel/syscall_table.S | 3 +++ include/asm-parisc/unistd.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'include') diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 3a1dd22e8138..6b5ac38f5a99 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -404,6 +404,9 @@ ENTRY_SAME(ni_syscall) /* was timerfd */ ENTRY_SAME(eventfd) ENTRY_COMP(fallocate) /* 305 */ + ENTRY_SAME(timerfd_create) + ENTRY_COMP(timerfd_settime) + ENTRY_COMP(timerfd_gettime) /* Nothing yet */ diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h index 081b4ae61866..f74d207c76da 100644 --- a/include/asm-parisc/unistd.h +++ b/include/asm-parisc/unistd.h @@ -798,6 +798,9 @@ #define __NR_timerfd (__NR_Linux + 303) #define __NR_eventfd (__NR_Linux + 304) #define __NR_fallocate (__NR_Linux + 305) +#define __NR_timerfd_create (__NR_Linux + 306) +#define __NR_timerfd_settime (__NR_Linux + 307) +#define __NR_timerfd_gettime (__NR_Linux + 308) #define __NR_Linux_syscalls (__NR_fallocate + 1) -- cgit v1.2.3-55-g7522 From d912e1dc8bb5718c3603beb43d0770dac0271374 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 18 Feb 2008 14:13:43 -0800 Subject: [PARISC] move VMALLOC_* definitions to fixmap.h They make way more sense here, really... Signed-off-by: Kyle McMartin --- include/asm-parisc/fixmap.h | 9 ++++++++- include/asm-parisc/pgtable.h | 8 -------- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/asm-parisc/fixmap.h b/include/asm-parisc/fixmap.h index a5caf4b122b7..de3fe3a18229 100644 --- a/include/asm-parisc/fixmap.h +++ b/include/asm-parisc/fixmap.h @@ -20,4 +20,11 @@ #define KERNEL_MAP_START (GATEWAY_PAGE_SIZE) #define KERNEL_MAP_END (TMPALIAS_MAP_START) -#endif +#ifndef __ASSEMBLY__ +extern void *vmalloc_start; +#define PCXL_DMA_MAP_SIZE (8*1024*1024) +#define VMALLOC_START ((unsigned long)vmalloc_start) +#define VMALLOC_END (KERNEL_MAP_END) +#endif /*__ASSEMBLY__*/ + +#endif /*_ASM_FIXMAP_H*/ diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h index cd0fa4f73320..dc86adbec916 100644 --- a/include/asm-parisc/pgtable.h +++ b/include/asm-parisc/pgtable.h @@ -116,14 +116,6 @@ #define FIRST_USER_ADDRESS 0 -#ifndef __ASSEMBLY__ -extern void *vmalloc_start; -#define PCXL_DMA_MAP_SIZE (8*1024*1024) -#define VMALLOC_START ((unsigned long)vmalloc_start) -/* this is a fixmap remnant, see fixmap.h */ -#define VMALLOC_END (KERNEL_MAP_END) -#endif - /* NB: The tlb miss handlers make certain assumptions about the order */ /* of the following bits, so be careful (One example, bits 25-31 */ /* are moved together in one instruction). */ -- cgit v1.2.3-55-g7522 From 9aa150b8d8af2532b6ce9ea36374cb997ac55807 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 18 Feb 2008 14:16:26 -0800 Subject: [PARISC] unbreak pgalloc.h Commit 2f569afd9ced9ebec9a6eb3dbf6f83429be0a7b4 broke the compile rather spectacularly. Fix code errors. Signed-off-by: Kyle McMartin --- include/asm-parisc/pgalloc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-parisc/pgalloc.h b/include/asm-parisc/pgalloc.h index 3996dfc30a3f..fc987a1c12a8 100644 --- a/include/asm-parisc/pgalloc.h +++ b/include/asm-parisc/pgalloc.h @@ -138,10 +138,10 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) free_page((unsigned long)pte); } -static inline void pte_free_kernel(struct mm_struct *mm, struct page *pte) +static inline void pte_free(struct mm_struct *mm, struct page *pte) { pgtable_page_dtor(pte); - pte_free_kernel(page_address((pte)); + pte_free_kernel(mm, page_address(pte)); } #define check_pgt_cache() do { } while (0) -- cgit v1.2.3-55-g7522 From e2be75ae21ea13ca19d4f2c3ff5a8df3f0e6c38e Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 18 Feb 2008 14:21:17 -0800 Subject: [PARISC] bump __NR_syscalls oops, forgot this in the previous commit. Signed-off-by: Kyle McMartin --- include/asm-parisc/unistd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h index f74d207c76da..a7d857f0e4f4 100644 --- a/include/asm-parisc/unistd.h +++ b/include/asm-parisc/unistd.h @@ -802,7 +802,7 @@ #define __NR_timerfd_settime (__NR_Linux + 307) #define __NR_timerfd_gettime (__NR_Linux + 308) -#define __NR_Linux_syscalls (__NR_fallocate + 1) +#define __NR_Linux_syscalls (__NR_timerfd_gettime + 1) #define __IGNORE_select /* newselect */ -- cgit v1.2.3-55-g7522 From 179183bf1fcff3830f0c05058ec0fc4d0878c67c Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 18 Feb 2008 14:26:41 -0800 Subject: [PARISC] remove unused pdc_iodc_printf function Signed-off-by: Kyle McMartin --- arch/parisc/kernel/pdc_cons.c | 13 ------------- include/asm-parisc/pdc.h | 1 - 2 files changed, 14 deletions(-) (limited to 'include') diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c index 33b1f84441b1..e7afc899d717 100644 --- a/arch/parisc/kernel/pdc_cons.c +++ b/arch/parisc/kernel/pdc_cons.c @@ -58,19 +58,6 @@ static void pdc_console_write(struct console *co, const char *s, unsigned count) pdc_iodc_print(s, count); } -void pdc_printf(const char *fmt, ...) -{ - va_list args; - char buf[1024]; - int i, len; - - va_start(args, fmt); - len = vscnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - - pdc_iodc_print(buf, len); -} - int pdc_console_poll_key(struct console *co) { return pdc_iodc_getc(); diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h index deda8c311373..b340c42f6bbc 100644 --- a/include/asm-parisc/pdc.h +++ b/include/asm-parisc/pdc.h @@ -646,7 +646,6 @@ void pdc_io_reset(void); void pdc_io_reset_devices(void); int pdc_iodc_getc(void); int pdc_iodc_print(unsigned char *str, unsigned count); -void pdc_printf(const char *fmt, ...); void pdc_emergency_unlock(void); int pdc_sti_call(unsigned long func, unsigned long flags, -- cgit v1.2.3-55-g7522 From ef1afd4d79f0479960ff36bb5fe6ec6eba1ebff2 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 18 Feb 2008 23:34:34 -0800 Subject: [PARISC] pdc_console: fix bizarre panic on boot Commit 721fdf34167580ff98263c74cead8871d76936e6 introduced a subtle bug by accidently removing the "static" from iodc_dbuf. This resulted in, what appeared to be, a trap without *current set to a task. Probably the result of a trap in real mode while calling firmware. Also do other misc clean ups. Since the only input from firmware is non blocking, share iodc_dbuf between input and output, and spinlock the only callers. Signed-off-by: Kyle McMartin --- arch/parisc/kernel/firmware.c | 27 +++++++++++++++++---------- arch/parisc/kernel/pdc_cons.c | 19 +++++++++++++++++-- include/asm-parisc/pdc.h | 2 +- 3 files changed, 35 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index 4ab83d56974d..7177a6cd1b7f 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -1080,6 +1080,9 @@ void pdc_io_reset_devices(void) spin_unlock_irqrestore(&pdc_lock, flags); } +/* locked by pdc_console_lock */ +static int __attribute__((aligned(8))) iodc_retbuf[32]; +static char __attribute__((aligned(64))) iodc_dbuf[4096]; /** * pdc_iodc_print - Console print using IODC. @@ -1091,24 +1094,20 @@ void pdc_io_reset_devices(void) * Since the HP console requires CR+LF to perform a 'newline', we translate * "\n" to "\r\n". */ -int pdc_iodc_print(unsigned char *str, unsigned count) +int pdc_iodc_print(const unsigned char *str, unsigned count) { - /* XXX Should we spinlock posx usage */ static int posx; /* for simple TAB-Simulation... */ - int __attribute__((aligned(8))) iodc_retbuf[32]; - char __attribute__((aligned(64))) iodc_dbuf[4096]; unsigned int i; unsigned long flags; - memset(iodc_dbuf, 0, 4096); - for (i = 0; i < count && i < 2048;) { + for (i = 0; i < count && i < 79;) { switch(str[i]) { case '\n': iodc_dbuf[i+0] = '\r'; iodc_dbuf[i+1] = '\n'; i += 2; posx = 0; - break; + goto print; case '\t': while (posx & 7) { iodc_dbuf[i] = ' '; @@ -1124,6 +1123,16 @@ int pdc_iodc_print(unsigned char *str, unsigned count) } } + /* if we're at the end of line, and not already inserting a newline, + * insert one anyway. iodc console doesn't claim to support >79 char + * lines. don't account for this in the return value. + */ + if (i == 79 && iodc_dbuf[i-1] != '\n') { + iodc_dbuf[i+0] = '\r'; + iodc_dbuf[i+1] = '\n'; + } + +print: spin_lock_irqsave(&pdc_lock, flags); real32_call(PAGE0->mem_cons.iodc_io, (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, @@ -1142,11 +1151,9 @@ int pdc_iodc_print(unsigned char *str, unsigned count) */ int pdc_iodc_getc(void) { - unsigned long flags; - static int __attribute__((aligned(8))) iodc_retbuf[32]; - static char __attribute__((aligned(64))) iodc_dbuf[4096]; int ch; int status; + unsigned long flags; /* Bail if no console input device. */ if (!PAGE0->mem_kbd.iodc_io) diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c index e7afc899d717..ccb68090781e 100644 --- a/arch/parisc/kernel/pdc_cons.c +++ b/arch/parisc/kernel/pdc_cons.c @@ -52,15 +52,30 @@ #include #include /* for iodc_call() proto and friends */ +static spinlock_t pdc_console_lock = SPIN_LOCK_UNLOCKED; static void pdc_console_write(struct console *co, const char *s, unsigned count) { - pdc_iodc_print(s, count); + int i = 0; + unsigned long flags; + + spin_lock_irqsave(&pdc_console_lock, flags); + do { + i += pdc_iodc_print(s + i, count - i); + } while (i < count); + spin_unlock_irqrestore(&pdc_console_lock, flags); } int pdc_console_poll_key(struct console *co) { - return pdc_iodc_getc(); + int c; + unsigned long flags; + + spin_lock_irqsave(&pdc_console_lock, flags); + c = pdc_iodc_getc(); + spin_unlock_irqrestore(&pdc_console_lock, flags); + + return c; } static int pdc_console_setup(struct console *co, char *options) diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h index b340c42f6bbc..9eaa794c3e4a 100644 --- a/include/asm-parisc/pdc.h +++ b/include/asm-parisc/pdc.h @@ -645,7 +645,7 @@ int pdc_soft_power_button(int sw_control); void pdc_io_reset(void); void pdc_io_reset_devices(void); int pdc_iodc_getc(void); -int pdc_iodc_print(unsigned char *str, unsigned count); +int pdc_iodc_print(const unsigned char *str, unsigned count); void pdc_emergency_unlock(void); int pdc_sti_call(unsigned long func, unsigned long flags, -- cgit v1.2.3-55-g7522 From fd5d3f6a32984ea6cd551030b82fb44a43197ba0 Mon Sep 17 00:00:00 2001 From: Randolph Chung Date: Sun, 24 Feb 2008 10:44:21 -0800 Subject: [PARISC] clean up include/asm-parisc/elf.h Cleanup some cruft. No functionality changes. Signed-off-by: Randolph Chung Signed-off-by: Kyle McMartin --- include/asm-parisc/elf.h | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h index ce0c0d844c7d..d0a4a8262818 100644 --- a/include/asm-parisc/elf.h +++ b/include/asm-parisc/elf.h @@ -204,7 +204,7 @@ typedef struct elf64_fdesc { /* * The following definitions are those for 32-bit ELF binaries on a 32-bit * kernel and for 64-bit binaries on a 64-bit kernel. To run 32-bit binaries - * on a 64-bit kernel, arch/parisc64/kernel/binfmt_elf32.c defines these + * on a 64-bit kernel, arch/parisc/kernel/binfmt_elf32.c defines these * macros appropriately and then #includes binfmt_elf.c, which then includes * this file. */ @@ -216,26 +216,25 @@ typedef struct elf64_fdesc { * Note that this header file is used by default in fs/binfmt_elf.c. So * the following macros are for the default case. However, for the 64 * bit kernel we also support 32 bit parisc binaries. To do that - * arch/parisc64/kernel/binfmt_elf32.c defines its own set of these + * arch/parisc/kernel/binfmt_elf32.c defines its own set of these * macros, and then it includes fs/binfmt_elf.c to provide an alternate * elf binary handler for 32 bit binaries (on the 64 bit kernel). */ #ifdef CONFIG_64BIT -#define ELF_CLASS ELFCLASS64 +#define ELF_CLASS ELFCLASS64 #else #define ELF_CLASS ELFCLASS32 #endif typedef unsigned long elf_greg_t; -/* This yields a string that ld.so will use to load implementation - specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. - - For the moment, we have only optimizations for the Intel generations, - but that could change... */ +/* + * This yields a string that ld.so will use to load implementation + * specific libraries for optimization. This is more specific in + * intent than poking at uname or /proc/cpuinfo. + */ -#define ELF_PLATFORM ("PARISC\0" /*+((boot_cpu_data.x86-3)*5) */) +#define ELF_PLATFORM ("PARISC\0") #define SET_PERSONALITY(ex, ibcs2) \ current->personality = PER_LINUX; \ @@ -310,7 +309,7 @@ struct pt_regs; /* forward declaration... */ #define ELF_OSABI ELFOSABI_LINUX /* %r23 is set by ld.so to a pointer to a function which might be - registered using atexit. This provides a mean for the dynamic + registered using atexit. This provides a means for the dynamic linker to call DT_FINI functions for shared libraries that have been loaded before the code runs. @@ -339,6 +338,5 @@ struct pt_regs; /* forward declaration... */ but it's not easy, and we've already done it here. */ #define ELF_HWCAP 0 -/* (boot_cpu_data.x86_capability) */ #endif -- cgit v1.2.3-55-g7522 From c20a84c91048c76c1379011c96b1a5cee5c7d9a0 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sat, 1 Mar 2008 10:25:52 -0800 Subject: [PARISC] futex: special case cmpxchg NULL in kernel space Commit a0c1e9073ef7428a14309cba010633a6cd6719ea added code to futex.c to detect whether futex_atomic_cmpxchg_inatomic was implemented at run time: + curval = cmpxchg_futex_value_locked(NULL, 0, 0); + if (curval == -EFAULT) + futex_cmpxchg_enabled = 1; This is bogus on parisc, since page zero in kernel virtual space is the gateway page for syscall entry, and should not be read from the kernel. (That, and we really don't like the kernel faulting on its own address space...) Signed-off-by: Kyle McMartin --- include/asm-parisc/futex.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-parisc/futex.h b/include/asm-parisc/futex.h index dbee6e60aa81..fdc6d055ef7f 100644 --- a/include/asm-parisc/futex.h +++ b/include/asm-parisc/futex.h @@ -56,6 +56,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) int err = 0; int uval; + /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is + * our gateway page, and causes no end of trouble... + */ + if (segment_eq(KERNEL_DS, get_fs()) && !uaddr) + return -EFAULT; + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; @@ -67,5 +73,5 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) return uval; } -#endif -#endif +#endif /*__KERNEL__*/ +#endif /*_ASM_PARISC_FUTEX_H*/ -- cgit v1.2.3-55-g7522 From 2af3e6017e53065ddf40bb19190a29199b7ffee3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 6 Mar 2008 16:02:42 +0100 Subject: The ps2esdi driver was marked as BROKEN more than two years ago due to being no longer working for some time. A driver that had been marked as BROKEN for such a long time seems to be unlikely to be revived in the forseeable future. But if anyone wants to ever revive this driver, the code is still present in the older kernel releases. Signed-off-by: Adrian Bunk Acked-by: Alan Cox Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- Documentation/mca.txt | 17 +- drivers/block/Kconfig | 10 - drivers/block/Makefile | 1 - drivers/block/ps2esdi.c | 1079 ----------------------------------------------- include/linux/Kbuild | 1 - include/linux/ps2esdi.h | 98 ----- 6 files changed, 5 insertions(+), 1201 deletions(-) delete mode 100644 drivers/block/ps2esdi.c delete mode 100644 include/linux/ps2esdi.h (limited to 'include') diff --git a/Documentation/mca.txt b/Documentation/mca.txt index aabce4ad90f9..510375d4209a 100644 --- a/Documentation/mca.txt +++ b/Documentation/mca.txt @@ -143,14 +143,7 @@ MCA Device Drivers Currently, there are a number of MCA-specific device drivers. -1) PS/2 ESDI - drivers/block/ps2esdi.c - include/linux/ps2esdi.h - Uses major number 36, and should use /dev files /dev/eda, /dev/edb. - Supports two drives, but only one controller. May use the - command-line args "ed=cyl,head,sec" and "tp720". - -2) PS/2 SCSI +1) PS/2 SCSI drivers/scsi/ibmmca.c drivers/scsi/ibmmca.h The driver for the IBM SCSI subsystem. Includes both integrated @@ -159,25 +152,25 @@ Currently, there are a number of MCA-specific device drivers. machine with a front-panel display (i.e. model 95), you can use "ibmmcascsi=display" to enable a drive activity indicator. -3) 3c523 +2) 3c523 drivers/net/3c523.c drivers/net/3c523.h 3Com 3c523 Etherlink/MC ethernet driver. -4) SMC Ultra/MCA and IBM Adapter/A +3) SMC Ultra/MCA and IBM Adapter/A drivers/net/smc-mca.c drivers/net/smc-mca.h Driver for the MCA version of the SMC Ultra and various other OEM'ed and work-alike cards (Elite, Adapter/A, etc). -5) NE/2 +4) NE/2 driver/net/ne2.c driver/net/ne2.h The NE/2 is the MCA version of the NE2000. This may not work with clones that have a different adapter id than the original NE/2. -6) Future Domain MCS-600/700, OEM'd IBM Fast SCSI Adapter/A and +5) Future Domain MCS-600/700, OEM'd IBM Fast SCSI Adapter/A and Reply Sound Blaster/SCSI (SCSI part) Better support for these cards than the driver for ISA. Supports multiple cards with IRQ sharing. diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index b6d230b3209f..0d1d2133d9bc 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -44,16 +44,6 @@ config MAC_FLOPPY If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) floppy controller, say Y here. Most commonly found in PowerMacs. -config BLK_DEV_PS2 - tristate "PS/2 ESDI hard disk support" - depends on MCA && MCA_LEGACY && BROKEN - help - Say Y here if you have a PS/2 machine with a MCA bus and an ESDI - hard disk. - - To compile this driver as a module, choose M here: the - module will be called ps2esdi. - config AMIGA_Z2RAM tristate "Amiga Zorro II ramdisk support" depends on ZORRO diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 01c972415cb2..5e584306be99 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o obj-$(CONFIG_BLK_DEV_LOOP) += loop.o -obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o obj-$(CONFIG_BLK_DEV_XD) += xd.o obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c deleted file mode 100644 index 3c796e236253..000000000000 --- a/drivers/block/ps2esdi.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* ps2esdi driver based on assembler code by Arindam Banerji, - written by Peter De Schrijver */ -/* Reassuring note to IBM : This driver was NOT developed by vice-versa - engineering the PS/2's BIOS */ -/* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those - other lovely fish out there... */ -/* This code was written during the long and boring WINA - elections 1994 */ -/* Thanks to Arindam Banerij for giving me the source of his driver */ -/* This code may be freely distributed and modified in any way, - as long as these notes remain intact */ - -/* Revised: 05/07/94 by Arindam Banerji (axb@cse.nd.edu) */ -/* Revised: 09/08/94 by Peter De Schrijver (stud11@cc4.kuleuven.ac.be) - Thanks to Arindam Banerij for sending me the docs of the adapter */ - -/* BA Modified for ThinkPad 720 by Boris Ashkinazi */ -/* (bash@vnet.ibm.com) 08/08/95 */ - -/* Modified further for ThinkPad-720C by Uri Blumenthal */ -/* (uri@watson.ibm.com) Sep 11, 1995 */ - -/* TODO : - + Timeouts - + Get disk parameters - + DMA above 16MB - + reset after read/write error - */ - -#define DEVICE_NAME "PS/2 ESDI" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define PS2ESDI_IRQ 14 -#define MAX_HD 2 -#define MAX_RETRIES 5 -#define MAX_16BIT 65536 -#define ESDI_TIMEOUT 0xf000 -#define ESDI_STAT_TIMEOUT 4 - -#define TYPE_0_CMD_BLK_LENGTH 2 -#define TYPE_1_CMD_BLK_LENGTH 4 - -static void reset_ctrl(void); - -static int ps2esdi_geninit(void); - -static void do_ps2esdi_request(struct request_queue * q); - -static void ps2esdi_readwrite(int cmd, struct request *req); - -static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, -u_short cyl, u_short head, u_short sector, u_short length, u_char drive); - -static int ps2esdi_out_cmd_blk(u_short * cmd_blk); - -static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode); - -static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id); -static void (*current_int_handler) (u_int) = NULL; -static void ps2esdi_normal_interrupt_handler(u_int); -static void ps2esdi_initial_reset_int_handler(u_int); -static void ps2esdi_geometry_int_handler(u_int); -static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo); - -static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); - -static void dump_cmd_complete_status(u_int int_ret_code); - -static void ps2esdi_get_device_cfg(void); - -static void ps2esdi_reset_timer(unsigned long unused); - -static u_int dma_arb_level; /* DMA arbitration level */ - -static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int); - -static int no_int_yet; -static int ps2esdi_drives; -static u_short io_base; -static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0); -static int reset_status; -static int ps2esdi_slot = -1; -static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */ -static int intg_esdi = 0; /* If integrated adapter */ -struct ps2esdi_i_struct { - unsigned int head, sect, cyl, wpcom, lzone, ctl; -}; -static DEFINE_SPINLOCK(ps2esdi_lock); -static struct request_queue *ps2esdi_queue; -static struct request *current_req; - -#if 0 -#if 0 /* try both - I don't know which one is better... UB */ -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {4, 48, 1553, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; -#else -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {64, 32, 161, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; -#endif -#endif -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; - -static struct block_device_operations ps2esdi_fops = -{ - .owner = THIS_MODULE, - .getgeo = ps2esdi_getgeo, -}; - -static struct gendisk *ps2esdi_gendisk[2]; - -/* initialization routine called by ll_rw_blk.c */ -static int __init ps2esdi_init(void) -{ - - int error = 0; - - /* register the device - pass the name and major number */ - if (register_blkdev(PS2ESDI_MAJOR, "ed")) - return -EBUSY; - - /* set up some global information - indicating device specific info */ - ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock); - if (!ps2esdi_queue) { - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - return -ENOMEM; - } - - /* some minor housekeeping - setup the global gendisk structure */ - error = ps2esdi_geninit(); - if (error) { - printk(KERN_WARNING "PS2ESDI: error initialising" - " device, releasing resources\n"); - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - blk_cleanup_queue(ps2esdi_queue); - return error; - } - return 0; -} /* ps2esdi_init */ - -#ifndef MODULE - -module_init(ps2esdi_init); - -#else - -static int cyl[MAX_HD] = {-1,-1}; -static int head[MAX_HD] = {-1, -1}; -static int sect[MAX_HD] = {-1, -1}; - -module_param(tp720esdi, bool, 0); -module_param_array(cyl, int, NULL, 0); -module_param_array(head, int, NULL, 0); -module_param_array(sect, int, NULL, 0); -MODULE_LICENSE("GPL"); - -int init_module(void) { - int drive; - - for(drive = 0; drive < MAX_HD; drive++) { - struct ps2esdi_i_struct *info = &ps2esdi_info[drive]; - - if (cyl[drive] != -1) { - info->cyl = info->lzone = cyl[drive]; - info->wpcom = 0; - } - if (head[drive] != -1) { - info->head = head[drive]; - info->ctl = (head[drive] > 8 ? 8 : 0); - } - if (sect[drive] != -1) info->sect = sect[drive]; - } - return ps2esdi_init(); -} - -void -cleanup_module(void) { - int i; - if(ps2esdi_slot) { - mca_mark_as_unused(ps2esdi_slot); - mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); - } - release_region(io_base, 4); - free_dma(dma_arb_level); - free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - blk_cleanup_queue(ps2esdi_queue); - for (i = 0; i < ps2esdi_drives; i++) { - del_gendisk(ps2esdi_gendisk[i]); - put_disk(ps2esdi_gendisk[i]); - } -} -#endif /* MODULE */ - -/* handles boot time command line parameters */ -void __init tp720_setup(char *str, int *ints) -{ - /* no params, just sets the tp720esdi flag if it exists */ - - printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME); - tp720esdi = 1; -} - -void __init ed_setup(char *str, int *ints) -{ - int hdind = 0; - - /* handles 3 parameters only - corresponding to - 1. Number of cylinders - 2. Number of heads - 3. Sectors/track - */ - - if (ints[0] != 3) - return; - - /* print out the information - seen at boot time */ - printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n", - DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]); - - /* set the index into device specific information table */ - if (ps2esdi_info[0].head != 0) - hdind = 1; - - /* set up all the device information */ - ps2esdi_info[hdind].head = ints[2]; - ps2esdi_info[hdind].sect = ints[3]; - ps2esdi_info[hdind].cyl = ints[1]; - ps2esdi_info[hdind].wpcom = 0; - ps2esdi_info[hdind].lzone = ints[1]; - ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); -#if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */ - ps2esdi_drives = hdind + 1; /* increment index for the next time */ -#endif -} /* ed_setup */ - -static int ps2esdi_getinfo(char *buf, int slot, void *d) -{ - int len = 0; - - len += sprintf(buf + len, "DMA Arbitration Level: %d\n", - dma_arb_level); - len += sprintf(buf + len, "IO Port: %x\n", io_base); - len += sprintf(buf + len, "IRQ: 14\n"); - len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives); - - return len; -} - -/* ps2 esdi specific initialization - called thru the gendisk chain */ -static int __init ps2esdi_geninit(void) -{ - /* - The first part contains the initialization code - for the ESDI disk subsystem. All we really do - is search for the POS registers of the controller - to do some simple setup operations. First, we - must ensure that the controller is installed, - enabled, and configured as PRIMARY. Then we must - determine the DMA arbitration level being used by - the controller so we can handle data transfer - operations properly. If all of this works, then - we will set the INIT_FLAG to a non-zero value. - */ - - int slot = 0, i, reset_start, reset_end; - u_char status; - unsigned short adapterID; - int error = 0; - - if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) { - adapterID = INTG_ESDI_ID; - printk("%s: integrated ESDI adapter found in slot %d\n", - DEVICE_NAME, slot+1); -#ifndef MODULE - mca_set_adapter_name(slot, "PS/2 Integrated ESDI"); -#endif - } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) { - adapterID = NRML_ESDI_ID; - printk("%s: normal ESDI adapter found in slot %d\n", - DEVICE_NAME, slot+1); - mca_set_adapter_name(slot, "PS/2 ESDI"); - } else { - return -ENODEV; - } - - ps2esdi_slot = slot; - mca_mark_as_used(slot); - mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL); - - /* Found the slot - read the POS register 2 to get the necessary - configuration and status information. POS register 2 has the - following information : - Bit Function - 7 reserved = 0 - 6 arbitration method - 0 - fairness enabled - 1 - fairness disabled, linear priority assignment - 5-2 arbitration level - 1 alternate address - 1 alternate address - 0 - use addresses 0x3510 - 0x3517 - 0 adapter enable - */ - - status = mca_read_stored_pos(slot, 2); - /* is it enabled ? */ - if (!(status & STATUS_ENABLED)) { - printk("%s: ESDI adapter disabled\n", DEVICE_NAME); - error = -ENODEV; - goto err_out1; - } - /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can - share with the SCSI driver */ - if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, - IRQF_DISABLED | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) - && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, - IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) - ) { - printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ); - error = -EBUSY; - goto err_out1; - } - if (status & STATUS_ALTERNATE) - io_base = ALT_IO_BASE; - else - io_base = PRIMARY_IO_BASE; - - if (!request_region(io_base, 4, "ed")) { - printk(KERN_WARNING"Unable to request region 0x%x\n", io_base); - error = -EBUSY; - goto err_out2; - } - /* get the dma arbitration level */ - dma_arb_level = (status >> 2) & 0xf; - - /* BA */ - printk("%s: DMA arbitration level : %d\n", - DEVICE_NAME, dma_arb_level); - - LITE_ON; - current_int_handler = ps2esdi_initial_reset_int_handler; - reset_ctrl(); - reset_status = 0; - reset_start = jiffies; - while (!reset_status) { - init_timer(&esdi_timer); - esdi_timer.expires = jiffies + HZ; - esdi_timer.data = 0; - add_timer(&esdi_timer); - sleep_on(&ps2esdi_int); - } - reset_end = jiffies; - LITE_OFF; - printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n", - DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ, - (reset_end - reset_start) % HZ); - - - /* Integrated ESDI Disk and Controller has only one drive! */ - if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */ - ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1; - } - - - - /* finally this part sets up some global data structures etc. */ - - ps2esdi_get_device_cfg(); - - /* some annoyance in the above routine returns TWO drives? - Is something else happining in the background? - Regaurdless we fix the # of drives again. AJK */ - /* Integrated ESDI Disk and Controller has only one drive! */ - if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */ - ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */ - - current_int_handler = ps2esdi_normal_interrupt_handler; - - if (request_dma(dma_arb_level, "ed") !=0) { - printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n" - ,(int) dma_arb_level); - error = -EBUSY; - goto err_out3; - } - blk_queue_max_sectors(ps2esdi_queue, 128); - - error = -ENOMEM; - for (i = 0; i < ps2esdi_drives; i++) { - struct gendisk *disk = alloc_disk(64); - if (!disk) - goto err_out4; - disk->major = PS2ESDI_MAJOR; - disk->first_minor = i<<6; - sprintf(disk->disk_name, "ed%c", 'a'+i); - disk->fops = &ps2esdi_fops; - ps2esdi_gendisk[i] = disk; - } - - for (i = 0; i < ps2esdi_drives; i++) { - struct gendisk *disk = ps2esdi_gendisk[i]; - set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect * - ps2esdi_info[i].cyl); - disk->queue = ps2esdi_queue; - disk->private_data = &ps2esdi_info[i]; - add_disk(disk); - } - return 0; -err_out4: - while (i--) - put_disk(ps2esdi_gendisk[i]); -err_out3: - release_region(io_base, 4); -err_out2: - free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); -err_out1: - if(ps2esdi_slot) { - mca_mark_as_unused(ps2esdi_slot); - mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); - } - return error; -} - -static void __init ps2esdi_get_device_cfg(void) -{ - u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH]; - - /*BA */ printk("%s: Drive 0\n", DEVICE_NAME); - current_int_handler = ps2esdi_geometry_int_handler; - cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600; - cmd_blk[1] = 0; - no_int_yet = TRUE; - ps2esdi_out_cmd_blk(cmd_blk); - if (no_int_yet) - sleep_on(&ps2esdi_int); - - if (ps2esdi_drives > 1) { - printk("%s: Drive 1\n", DEVICE_NAME); /*BA */ - cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600; - cmd_blk[1] = 0; - no_int_yet = TRUE; - ps2esdi_out_cmd_blk(cmd_blk); - if (no_int_yet) - sleep_on(&ps2esdi_int); - } /* if second physical drive is present */ - return; -} - -/* strategy routine that handles most of the IO requests */ -static void do_ps2esdi_request(struct request_queue * q) -{ - struct request *req; - /* since, this routine is called with interrupts cleared - they - must be before it finishes */ - - req = elv_next_request(q); - if (!req) - return; - -#if 0 - printk("%s:got request. device : %s command : %d sector : %ld count : %ld, buffer: %p\n", - DEVICE_NAME, - req->rq_disk->disk_name, - req->cmd, req->sector, - req->current_nr_sectors, req->buffer); -#endif - - /* check for above 16Mb dmas */ - if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) { - printk("%s: DMA above 16MB not supported\n", DEVICE_NAME); - end_request(req, FAIL); - return; - } - - if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) { - printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n", - ps2esdi_drives, req->sector, - (unsigned long long)get_capacity(req->rq_disk)); - end_request(req, FAIL); - return; - } - - switch (rq_data_dir(req)) { - case READ: - ps2esdi_readwrite(READ, req); - break; - case WRITE: - ps2esdi_readwrite(WRITE, req); - break; - default: - printk("%s: Unknown command\n", req->rq_disk->disk_name); - end_request(req, FAIL); - break; - } /* handle different commands */ -} /* main strategy routine */ - -/* resets the ESDI adapter */ -static void reset_ctrl(void) -{ - - u_long expire; - u_short status; - - /* enable interrupts on the controller */ - status = inb(ESDI_INTRPT); - outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have - any interrupt pending... */ - outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL); - - /* read the ESDI status port - if the controller is not busy, - simply do a soft reset (fast) - otherwise we'll have to do a - hard (slow) reset. */ - if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) { - /*BA */ printk("%s: soft reset...\n", DEVICE_NAME); - outb_p(CTRL_SOFT_RESET, ESDI_ATTN); - } - /* soft reset */ - else { - /*BA */ - printk("%s: hard reset...\n", DEVICE_NAME); - outb_p(CTRL_HARD_RESET, ESDI_CONTROL); - expire = jiffies + 2*HZ; - while (time_before(jiffies, expire)); - outb_p(1, ESDI_CONTROL); - } /* hard reset */ - - -} /* reset the controller */ - -/* called by the strategy routine to handle read and write requests */ -static void ps2esdi_readwrite(int cmd, struct request *req) -{ - struct ps2esdi_i_struct *p = req->rq_disk->private_data; - unsigned block = req->sector; - unsigned count = req->current_nr_sectors; - int drive = p - ps2esdi_info; - u_short track, head, cylinder, sector; - u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH]; - - /* do some relevant arithmatic */ - track = block / p->sect; - head = track % p->head; - cylinder = track / p->head; - sector = block % p->sect; - -#if 0 - printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector); -#endif - /* call the routine that actually fills out a command block */ - ps2esdi_fill_cmd_block - (cmd_blk, - (cmd == READ) ? CMD_READ : CMD_WRITE, - cylinder, head, sector, count, drive); - - /* send the command block to the controller */ - current_req = req; - spin_unlock_irq(&ps2esdi_lock); - if (ps2esdi_out_cmd_blk(cmd_blk)) { - spin_lock_irq(&ps2esdi_lock); - printk("%s: Controller failed\n", DEVICE_NAME); - if ((++req->errors) >= MAX_RETRIES) - end_request(req, FAIL); - } - /* check for failure to put out the command block */ - else { - spin_lock_irq(&ps2esdi_lock); -#if 0 - printk("%s: waiting for xfer\n", DEVICE_NAME); -#endif - /* turn disk lights on */ - LITE_ON; - } - -} /* ps2esdi_readwrite */ - -/* fill out the command block */ -static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, - u_short cyl, u_short head, u_short sector, u_short length, u_char drive) -{ - - cmd_blk[0] = (drive << 5) | cmd; - cmd_blk[1] = length; - cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector; - cmd_blk[3] = (cyl & 0x3E0) >> 5; - -} /* fill out the command block */ - -/* write a command block to the controller */ -static int ps2esdi_out_cmd_blk(u_short * cmd_blk) -{ - - int i; - unsigned long jif; - u_char status; - - /* enable interrupts */ - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - - /* do not write to the controller, if it is busy */ - for (jif = jiffies + ESDI_STAT_TIMEOUT; - time_after(jif, jiffies) && - (inb(ESDI_STATUS) & STATUS_BUSY); ) - ; - -#if 0 - printk("%s: i(1)=%ld\n", DEVICE_NAME, jif); -#endif - - /* if device is still busy - then just time out */ - if (inb(ESDI_STATUS) & STATUS_BUSY) { - printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME); - return ERROR; - } /* timeout ??? */ - /* Set up the attention register in the controller */ - outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN); - -#if 0 - printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1); -#endif - - /* one by one send each word out */ - for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) { - status = inb(ESDI_STATUS); - for (jif = jiffies + ESDI_STAT_TIMEOUT; - time_after(jif, jiffies) && (status & STATUS_BUSY) && - (status & STATUS_CMD_INF); status = inb(ESDI_STATUS)); - if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) { -#if 0 - printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk); -#endif - outw(*cmd_blk++, ESDI_CMD_INT); - } else { - printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n", - DEVICE_NAME, status); - return ERROR; - } - } /* send all words out */ - return OK; -} /* send out the commands */ - - -/* prepare for dma - do all the necessary setup */ -static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode) -{ - unsigned long flags = claim_dma_lock(); - - mca_disable_dma(dma_arb_level); - - mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer)); - - mca_set_dma_count(dma_arb_level, length * 512 / 2); - - mca_set_dma_mode(dma_arb_level, dma_xmode); - - mca_enable_dma(dma_arb_level); - - release_dma_lock(flags); - -} /* prepare for dma */ - - - -static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id) -{ - u_int int_ret_code; - - if (inb(ESDI_STATUS) & STATUS_INTR) { - int_ret_code = inb(ESDI_INTRPT); - if (current_int_handler) { - /* Disable adapter interrupts till processing is finished */ - outb(CTRL_DISABLE_INTR, ESDI_CONTROL); - current_int_handler(int_ret_code); - } else - printk("%s: help ! No interrupt handler.\n", DEVICE_NAME); - } else { - return IRQ_NONE; - } - return IRQ_HANDLED; -} - -static void ps2esdi_initial_reset_int_handler(u_int int_ret_code) -{ - - switch (int_ret_code & 0xf) { - case INT_RESET: - /*BA */ - printk("%s: initial reset completed.\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - wake_up(&ps2esdi_int); - break; - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS)); - break; - default: - printk("%s: initial reset handler received interrupt: %02X\n", - DEVICE_NAME, int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); -} - - -static void ps2esdi_geometry_int_handler(u_int int_ret_code) -{ - u_int status, drive_num; - unsigned long rba; - int i; - - drive_num = int_ret_code >> 5; - switch (int_ret_code & 0xf) { - case INT_CMD_COMPLETE: - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - status = inw(ESDI_STT_INT); - if ((status & 0x1F) == CMD_GET_DEV_CONFIG) { -#define REPLY_WORDS 5 /* we already read word 0 */ - u_short reply[REPLY_WORDS]; - - if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) { - /*BA */ - printk("%s: Device Configuration Status for drive %u\n", - DEVICE_NAME, drive_num); - - printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8); - - printk - ("Config bits: %s%s%s%s%s\n", - (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "", - ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS)) - ? "Zero Defect, " : "Defects Present, ", - (reply[0] & CONFIG_SF) ? "Skewed Format, " : "", - (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ", - (reply[0] & CONFIG_RT) ? "No Retries" : "Retries"); - - rba = reply[1] | ((unsigned long) reply[2] << 16); - printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba); - - printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n", - DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff); - - if (!ps2esdi_info[drive_num].head) { - ps2esdi_info[drive_num].head = 64; - ps2esdi_info[drive_num].sect = 32; - ps2esdi_info[drive_num].cyl = rba / (64 * 32); - ps2esdi_info[drive_num].wpcom = 0; - ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl; - ps2esdi_info[drive_num].ctl = 8; - if (tp720esdi) { /* store the retrieved parameters */ - ps2esdi_info[0].head = reply[4] & 0Xff; - ps2esdi_info[0].sect = reply[4] >> 8; - ps2esdi_info[0].cyl = reply[3]; - ps2esdi_info[0].wpcom = 0; - ps2esdi_info[0].lzone = reply[3]; - } else { - if (!intg_esdi) - ps2esdi_drives++; - } - } -#ifdef OBSOLETE - if (!ps2esdi_info[drive_num].head) { - ps2esdi_info[drive_num].head = reply[4] & 0Xff; - ps2esdi_info[drive_num].sect = reply[4] >> 8; - ps2esdi_info[drive_num].cyl = reply[3]; - ps2esdi_info[drive_num].wpcom = 0; - ps2esdi_info[drive_num].lzone = reply[3]; - if (tp720esdi) { /* store the retrieved parameters */ - ps2esdi_info[0].head = reply[4] & 0Xff; - ps2esdi_info[0].sect = reply[4] >> 8; - ps2esdi_info[0].cyl = reply[3]; - ps2esdi_info[0].wpcom = 0; - ps2esdi_info[0].lzone = reply[3]; - } else { - ps2esdi_drives++; - } - } -#endif - - } else - printk("%s: failed while getting device config\n", DEVICE_NAME); -#undef REPLY_WORDS - } else - printk("%s: command %02X unknown by geometry handler\n", - DEVICE_NAME, status & 0x1f); - - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - printk("%s: Device not available\n", DEVICE_NAME); - break; - case INT_CMD_ECC: - case INT_CMD_RETRY: - case INT_CMD_ECC_RETRY: - case INT_CMD_WARNING: - case INT_CMD_ABORT: - case INT_CMD_FAILED: - case INT_DMA_ERR: - case INT_CMD_BLK_ERR: - /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME); - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - default: - printk("%s: Unknown interrupt reason: %02X\n", - DEVICE_NAME, int_ret_code & 0xf); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - - wake_up(&ps2esdi_int); - no_int_yet = FALSE; - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - -} - -static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) -{ - unsigned long flags; - u_int status; - u_int ending; - int i; - - switch (int_ret_code & 0x0f) { - case INT_TRANSFER_REQ: - ps2esdi_prep_dma(current_req->buffer, - current_req->current_nr_sectors, - (rq_data_dir(current_req) == READ) - ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER - : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ); - outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = FAIL; - break; - - case INT_CMD_COMPLETE: - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - if ((++current_req->errors) >= MAX_RETRIES) - ending = FAIL; - else - ending = -1; - break; - } - status = inw(ESDI_STT_INT); - switch (status & 0x1F) { - case (CMD_READ & 0xff): - case (CMD_WRITE & 0xff): - LITE_OFF; - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = SUCCES; - break; - default: - printk("%s: interrupt for unknown command %02X\n", - DEVICE_NAME, status & 0x1f); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - } - break; - case INT_CMD_ECC: - case INT_CMD_RETRY: - case INT_CMD_ECC_RETRY: - LITE_OFF; - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = SUCCES; - break; - case INT_CMD_WARNING: - case INT_CMD_ABORT: - case INT_CMD_FAILED: - case INT_DMA_ERR: - LITE_OFF; - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - if ((++current_req->errors) >= MAX_RETRIES) - ending = FAIL; - else - ending = -1; - break; - - case INT_CMD_BLK_ERR: - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = FAIL; - break; - - case INT_CMD_FORMAT: - printk("%s: huh ? Who issued this format command ?\n" - ,DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - case INT_RESET: - /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ; - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - default: - printk("%s: Unknown interrupt reason: %02X\n", - DEVICE_NAME, int_ret_code & 0xf); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - } - if(ending != -1) { - spin_lock_irqsave(&ps2esdi_lock, flags); - end_request(current_req, ending); - current_req = NULL; - do_ps2esdi_request(ps2esdi_queue); - spin_unlock_irqrestore(&ps2esdi_lock, flags); - } -} /* handle interrupts */ - - - -static int ps2esdi_read_status_words(int num_words, - int max_words, - u_short * buffer) -{ - int i; - - for (; max_words && num_words; max_words--, num_words--, buffer++) { - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - return FAIL; - } - *buffer = inw(ESDI_STT_INT); - } - return SUCCES; -} - - - - -static void dump_cmd_complete_status(u_int int_ret_code) -{ -#define WAIT_FOR_STATUS \ - for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \ - if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \ - printk("%s: timeout reading status word\n",DEVICE_NAME); \ - return; \ - } - - int i, word_count; - u_short stat_word; - u_long rba; - - printk("%s: Device: %u, interrupt ID: %02X\n", - DEVICE_NAME, int_ret_code >> 5, - int_ret_code & 0xf); - - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - word_count = (stat_word >> 8) - 1; - printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count, - stat_word & 0xff); - - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: command status code: %02X, command error code: %02X\n", - DEVICE_NAME, stat_word >> 8, stat_word & 0xff); - } - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME, - (stat_word & 0x1000) ? "Ready, " : "Not Ready, ", - (stat_word & 0x0800) ? "Selected, " : "Not Selected, ", - (stat_word & 0x0400) ? "Write Fault, " : "", - (stat_word & 0x0200) ? "Track 0, " : "", - (stat_word & 0x0100) ? "Seek or command complete, " : "", - stat_word >> 8); - } - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word); - } - if (word_count -= 2) { - WAIT_FOR_STATUS; - rba = inw(ESDI_STT_INT); - WAIT_FOR_STATUS; - rba |= inw(ESDI_STT_INT) << 16; - printk(", Last Cyl: %u Head: %u Sector: %u\n", - (u_short) ((rba & 0x1ff80000) >> 11), - (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f)); - } else - printk("\n"); - - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word); - } - printk("\n"); - -#undef WAIT_FOR_STATUS - -} - -static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct ps2esdi_i_struct *p = bdev->bd_disk->private_data; - - geo->heads = p->head; - geo->sectors = p->sect; - geo->cylinders = p->cyl; - return 0; -} - -static void ps2esdi_reset_timer(unsigned long unused) -{ - - int status; - - status = inb(ESDI_INTRPT); - if ((status & 0xf) == INT_RESET) { - outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - reset_status = 1; - } - wake_up(&ps2esdi_int); -} diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 0fac822c1157..4108b38ebb16 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -127,7 +127,6 @@ header-y += pkt_sched.h header-y += posix_types.h header-y += ppdev.h header-y += prctl.h -header-y += ps2esdi.h header-y += qnxtypes.h header-y += quotaio_v1.h header-y += quotaio_v2.h diff --git a/include/linux/ps2esdi.h b/include/linux/ps2esdi.h deleted file mode 100644 index c0e050b1dfe9..000000000000 --- a/include/linux/ps2esdi.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _PS2ESDI_H_ -#define _PS2ESDI_H_ - -#define NRML_ESDI_ID 0xddff -#define INTG_ESDI_ID 0xdf9f - -#define PRIMARY_IO_BASE 0x3510 -#define ALT_IO_BASE 0x3518 - -#define ESDI_CMD_INT (io_base+0) -#define ESDI_STT_INT (io_base+0) -#define ESDI_CONTROL (io_base+2) -#define ESDI_STATUS (io_base+2) -#define ESDI_ATTN (io_base+3) -#define ESDI_INTRPT (io_base+3) - -#define STATUS_ENABLED 0x01 -#define STATUS_ALTERNATE 0x02 -#define STATUS_BUSY 0x10 -#define STATUS_STAT_AVAIL 0x08 -#define STATUS_INTR 0x01 -#define STATUS_RESET_FAIL 0xea -#define STATUS_CMD_INF 0x04 - -#define CTRL_SOFT_RESET 0xe4 -#define CTRL_HARD_RESET 0x80 -#define CTRL_EOI 0xe2 -#define CTRL_ENABLE_DMA 0x02 -#define CTRL_ENABLE_INTR 0x01 -#define CTRL_DISABLE_INTR 0x00 - -#define ATT_EOI 0x02 - -/* bits of word 0 of configuration status block. more info see p.38 of tech ref */ -#define CONFIG_IS 0x10 /* Invalid Secondary */ -#define CONFIG_ZD 0x08 /* Zero Defect */ -#define CONFIG_SF 0x04 /* Skewed Format */ -#define CONFIG_FR 0x02 /* Removable */ -#define CONFIG_RT 0x01 /* Retries */ - -#define PORT_SYS_A 0x92 -#define PORT_DMA_FN 0x18 -#define PORT_DMA_EX 0x1a - -#define ON (unsigned char)0x40 -#define OFF (unsigned char)~ON -#define LITE_ON outb(inb(PORT_SYS_A) | ON,PORT_SYS_A) -#define LITE_OFF outb((inb(PORT_SYS_A) & OFF),PORT_SYS_A) - -#define FAIL 0 -#define SUCCES 1 - -#define INT_CMD_COMPLETE 0x01 -#define INT_CMD_ECC 0x03 -#define INT_CMD_RETRY 0x05 -#define INT_CMD_FORMAT 0x06 -#define INT_CMD_ECC_RETRY 0x07 -#define INT_CMD_WARNING 0x08 -#define INT_CMD_ABORT 0x09 -#define INT_RESET 0x0A -#define INT_TRANSFER_REQ 0x0B -#define INT_CMD_FAILED 0x0C -#define INT_DMA_ERR 0x0D -#define INT_CMD_BLK_ERR 0x0E -#define INT_ATTN_ERROR 0x0F - -#define DMA_MASK_CHAN 0x90 -#define DMA_UNMASK_CHAN 0xA0 -#define DMA_WRITE_ADDR 0x20 -#define DMA_WRITE_TC 0x40 -#define DMA_WRITE_MODE 0x70 - -#define CMD_GET_DEV_CONFIG 0x09 -#define CMD_READ 0x4601 -#define CMD_WRITE 0x4602 -#define DMA_READ_16 0x4C -#define DMA_WRITE_16 0x44 - - -#define MB 1024*1024 -#define SECT_SIZE 512 - -#define ERROR 1 -#define OK 0 - -#define HDIO_GETGEO 0x0301 - -#define FALSE 0 -#define TRUE !FALSE - -struct ps2esdi_geometry { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - unsigned long start; -}; - -#endif /* _PS2ESDI_H_ */ -- cgit v1.2.3-55-g7522 From 4265f161b6bb7b31163671329b1142b9023bf4e3 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Fri, 14 Mar 2008 14:17:05 +0100 Subject: virtio: fix race in enable_cb There is a race in virtio_net, dealing with disabling/enabling the callback. I saw the following oops: kernel BUG at /space/kvm/drivers/virtio/virtio_ring.c:218! illegal operation: 0001 [#1] SMP Modules linked in: sunrpc dm_mod CPU: 2 Not tainted 2.6.25-rc1zlive-host-10623-gd358142-dirty #99 Process swapper (pid: 0, task: 000000000f85a610, ksp: 000000000f873c60) Krnl PSW : 0404300180000000 00000000002b81a6 (vring_disable_cb+0x16/0x20) R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:0 CC:3 PM:0 EA:3 Krnl GPRS: 0000000000000001 0000000000000001 0000000010005800 0000000000000001 000000000f3a0900 000000000f85a610 0000000000000000 0000000000000000 0000000000000000 000000000f870000 0000000000000000 0000000000001237 000000000f3a0920 000000000010ff74 00000000002846f6 000000000fa0bcd8 Krnl Code: 00000000002b819a: a7110001 tmll %r1,1 00000000002b819e: a7840004 brc 8,2b81a6 00000000002b81a2: a7f40001 brc 15,2b81a4 >00000000002b81a6: a51b0001 oill %r1,1 00000000002b81aa: 40102000 sth %r1,0(%r2) 00000000002b81ae: 07fe bcr 15,%r14 00000000002b81b0: eb7ff0380024 stmg %r7,%r15,56(%r15) 00000000002b81b6: a7f13e00 tmll %r15,15872 Call Trace: ([<000000000fa0bcd0>] 0xfa0bcd0) [<00000000002b8350>] vring_interrupt+0x5c/0x6c [<000000000010ab08>] do_extint+0xb8/0xf0 [<0000000000110716>] ext_no_vtime+0x16/0x1a [<0000000000107e72>] cpu_idle+0x1c2/0x1e0 The problem can be triggered with a high amount of host->guest traffic. I think its the following race: poll says netif_rx_complete poll calls enable_cb enable_cb opens the interrupt mask a new packet comes, an interrupt is triggered----\ enable_cb sees that there is more work | enable_cb disables the interrupt | . V . interrupt is delivered . skb_recv_done does atomic napi test, ok some waiting disable_cb is called->check fails->bang! . poll would do napi check poll would do disable_cb The fix is to let enable_cb not disable the interrupt again, but expect the caller to do the cleanup if it returns false. In that case, the interrupt is only disabled, if the napi test_set_bit was successful. Signed-off-by: Christian Borntraeger Signed-off-by: Rusty Russell (cleaned up doco) --- drivers/net/virtio_net.c | 10 +++++++--- drivers/virtio/virtio_ring.c | 1 - include/linux/virtio.h | 5 +++-- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e575df83e5c2..b58472cf76f8 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -203,8 +203,11 @@ again: if (received < budget) { netif_rx_complete(vi->dev, napi); if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) - && netif_rx_reschedule(vi->dev, napi)) + && napi_schedule_prep(napi)) { + vi->rvq->vq_ops->disable_cb(vi->rvq); + __netif_rx_schedule(vi->dev, napi); goto again; + } } return received; @@ -278,10 +281,11 @@ again: pr_debug("%s: virtio not prepared to send\n", dev->name); netif_stop_queue(dev); - /* Activate callback for using skbs: if this fails it + /* Activate callback for using skbs: if this returns false it * means some were used in the meantime. */ if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { - printk("Unlikely: restart svq failed\n"); + printk("Unlikely: restart svq race\n"); + vi->svq->vq_ops->disable_cb(vi->svq); netif_start_queue(dev); goto again; } diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 3a28c1382131..aa714028641e 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -232,7 +232,6 @@ static bool vring_enable_cb(struct virtqueue *_vq) vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; mb(); if (unlikely(more_used(vq))) { - vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; END_USE(vq); return false; } diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 260d1fcf29a4..12c18ac1b973 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -43,8 +43,9 @@ struct virtqueue * vq: the struct virtqueue we're talking about. * @enable_cb: restart callbacks after disable_cb. * vq: the struct virtqueue we're talking about. - * This returns "false" (and doesn't re-enable) if there are pending - * buffers in the queue, to avoid a race. + * This re-enables callbacks; it returns "false" if there are pending + * buffers in the queue, to detect a possible race between the driver + * checking for more work, and enabling callbacks. * * Locking rules are straightforward: the driver is responsible for * locking. No two operations may be invoked simultaneously. -- cgit v1.2.3-55-g7522 From 916fbfb7ae5f8c8f86399794d89e6d273df8826b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 12 Mar 2008 15:26:34 +0900 Subject: devres: implement pcim_iomap_regions_request_all() Some drivers need to reserve all PCI BARs to prevent other drivers misusing unoccupied BARs. pcim_iomap_regions_request_all() requests all BARs and iomap specified BARs. Signed-off-by: Tejun Heo Cc: Greg Kroah-Hartman Cc: Alan Cox Cc: Jeff Garzik Signed-off-by: Jeff Garzik --- include/linux/pci.h | 2 ++ lib/devres.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'include') diff --git a/include/linux/pci.h b/include/linux/pci.h index 9010f5458767..b7e4b633c69b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1045,6 +1045,8 @@ void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr); void __iomem * const *pcim_iomap_table(struct pci_dev *pdev); int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name); +int pcim_iomap_regions_request_all(struct pci_dev *pdev, u16 mask, + const char *name); void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask); extern int pci_pci_problems; diff --git a/lib/devres.c b/lib/devres.c index b1d336ce7f3d..edc27a5d1b73 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -297,6 +297,31 @@ int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name) } EXPORT_SYMBOL(pcim_iomap_regions); +/** + * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones + * @pdev: PCI device to map IO resources for + * @mask: Mask of BARs to iomap + * @name: Name used when requesting regions + * + * Request all PCI BARs and iomap regions specified by @mask. + */ +int pcim_iomap_regions_request_all(struct pci_dev *pdev, u16 mask, + const char *name) +{ + int request_mask = ((1 << 6) - 1) & ~mask; + int rc; + + rc = pci_request_selected_regions(pdev, request_mask, name); + if (rc) + return rc; + + rc = pcim_iomap_regions(pdev, mask, name); + if (rc) + pci_release_selected_regions(pdev, request_mask); + return rc; +} +EXPORT_SYMBOL(pcim_iomap_regions_request_all); + /** * pcim_iounmap_regions - Unmap and release PCI BARs * @pdev: PCI device to map IO resources for -- cgit v1.2.3-55-g7522 From 4ae7d5cefd4aa3560e359a3b0f03e12adc8b5c86 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 19 Mar 2008 01:42:00 +0100 Subject: sched: improve affine wakeups improve affine wakeups. Maintain the 'overlap' metric based on CFS's sum_exec_runtime - which means the amount of time a task executes after it wakes up some other task. Use the 'overlap' for the wakeup decisions: if the 'overlap' is short, it means there's strong workload coupling between this task and the woken up task. If the 'overlap' is large then the workload is decoupled and the scheduler will move them to separate CPUs more easily. ( Also slightly move the preempt_check within try_to_wake_up() - this has no effect on functionality but allows 'early wakeups' (for still-on-rq tasks) to be correctly accounted as well.) Signed-off-by: Ingo Molnar --- include/linux/sched.h | 3 +++ kernel/sched.c | 5 ++++- kernel/sched_debug.c | 1 + kernel/sched_fair.c | 58 +++++++++++++++++++++++++++++++++++++-------------- 4 files changed, 50 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index 11d8e9a74eff..3625fcaf5d0f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -929,6 +929,9 @@ struct sched_entity { u64 vruntime; u64 prev_sum_exec_runtime; + u64 last_wakeup; + u64 avg_overlap; + #ifdef CONFIG_SCHEDSTATS u64 wait_start; u64 wait_max; diff --git a/kernel/sched.c b/kernel/sched.c index d1ad69b270ca..adbd475cfd25 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1855,10 +1855,11 @@ out_activate: schedstat_inc(p, se.nr_wakeups_remote); update_rq_clock(rq); activate_task(rq, p, 1); - check_preempt_curr(rq, p); success = 1; out_running: + check_preempt_curr(rq, p); + p->state = TASK_RUNNING; #ifdef CONFIG_SMP if (p->sched_class->task_wake_up) @@ -1892,6 +1893,8 @@ static void __sched_fork(struct task_struct *p) p->se.exec_start = 0; p->se.sum_exec_runtime = 0; p->se.prev_sum_exec_runtime = 0; + p->se.last_wakeup = 0; + p->se.avg_overlap = 0; #ifdef CONFIG_SCHEDSTATS p->se.wait_start = 0; diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 4b5e24cf2f4a..ef358ba07683 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -288,6 +288,7 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) PN(se.exec_start); PN(se.vruntime); PN(se.sum_exec_runtime); + PN(se.avg_overlap); nr_switches = p->nvcsw + p->nivcsw; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index b5a357396b49..87c9d3a2aafa 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -556,6 +556,21 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) account_entity_enqueue(cfs_rq, se); } +static void update_avg(u64 *avg, u64 sample) +{ + s64 diff = sample - *avg; + *avg += diff >> 3; +} + +static void update_avg_stats(struct cfs_rq *cfs_rq, struct sched_entity *se) +{ + if (!se->last_wakeup) + return; + + update_avg(&se->avg_overlap, se->sum_exec_runtime - se->last_wakeup); + se->last_wakeup = 0; +} + static void dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) { @@ -566,6 +581,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) update_stats_dequeue(cfs_rq, se); if (sleep) { + update_avg_stats(cfs_rq, se); #ifdef CONFIG_SCHEDSTATS if (entity_is_task(se)) { struct task_struct *tsk = task_of(se); @@ -981,12 +997,15 @@ static inline int wake_idle(int cpu, struct task_struct *p) #ifdef CONFIG_SMP +static const struct sched_class fair_sched_class; + static int -wake_affine(struct rq *rq, struct sched_domain *this_sd, struct task_struct *p, - int prev_cpu, int this_cpu, int sync, int idx, - unsigned long load, unsigned long this_load, +wake_affine(struct rq *rq, struct sched_domain *this_sd, struct rq *this_rq, + struct task_struct *p, int prev_cpu, int this_cpu, int sync, + int idx, unsigned long load, unsigned long this_load, unsigned int imbalance) { + struct task_struct *curr = this_rq->curr; unsigned long tl = this_load; unsigned long tl_per_task; @@ -994,10 +1013,15 @@ wake_affine(struct rq *rq, struct sched_domain *this_sd, struct task_struct *p, return 0; /* - * Attract cache-cold tasks on sync wakeups: + * If the currently running task will sleep within + * a reasonable amount of time then attract this newly + * woken task: */ - if (sync && !task_hot(p, rq->clock, this_sd)) - return 1; + if (sync && curr->sched_class == &fair_sched_class) { + if (curr->se.avg_overlap < sysctl_sched_migration_cost && + p->se.avg_overlap < sysctl_sched_migration_cost) + return 1; + } schedstat_inc(p, se.nr_wakeups_affine_attempts); tl_per_task = cpu_avg_load_per_task(this_cpu); @@ -1030,18 +1054,16 @@ static int select_task_rq_fair(struct task_struct *p, int sync) struct sched_domain *sd, *this_sd = NULL; int prev_cpu, this_cpu, new_cpu; unsigned long load, this_load; + struct rq *rq, *this_rq; unsigned int imbalance; - struct rq *rq; int idx; prev_cpu = task_cpu(p); rq = task_rq(p); this_cpu = smp_processor_id(); + this_rq = cpu_rq(this_cpu); new_cpu = prev_cpu; - if (prev_cpu == this_cpu) - goto out; - /* * 'this_sd' is the first domain that both * this_cpu and prev_cpu are present in: @@ -1069,11 +1091,12 @@ static int select_task_rq_fair(struct task_struct *p, int sync) load = source_load(prev_cpu, idx); this_load = target_load(this_cpu, idx); - if (wake_affine(rq, this_sd, p, prev_cpu, this_cpu, sync, idx, - load, this_load, imbalance)) { - new_cpu = this_cpu; + if (wake_affine(rq, this_sd, this_rq, p, prev_cpu, this_cpu, sync, idx, + load, this_load, imbalance)) + return this_cpu; + + if (prev_cpu == this_cpu) goto out; - } /* * Start passive balancing when half the imbalance_pct @@ -1083,8 +1106,7 @@ static int select_task_rq_fair(struct task_struct *p, int sync) if (imbalance*this_load <= 100*load) { schedstat_inc(this_sd, ttwu_move_balance); schedstat_inc(p, se.nr_wakeups_passive); - new_cpu = this_cpu; - goto out; + return this_cpu; } } @@ -1111,6 +1133,10 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) return; } + se->last_wakeup = se->sum_exec_runtime; + if (unlikely(se == pse)) + return; + cfs_rq_of(pse)->next = pse; /* -- cgit v1.2.3-55-g7522 From 33b0c4217dcd67b788318c3192a2912b530e4eef Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 16 Mar 2008 11:14:30 +0100 Subject: sched: tune multi-core idle balancing WAKE_IDLE is too agressive on multi-core CPUs with the new wake-affine code, keep it on for SMT/HT balancing alone (where there's no cache affinity at all between logical CPUs). Signed-off-by: Ingo Molnar --- include/linux/topology.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/topology.h b/include/linux/topology.h index 2352f46160d3..2d8dac8799cf 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -138,7 +138,6 @@ | SD_BALANCE_FORK \ | SD_BALANCE_EXEC \ | SD_WAKE_AFFINE \ - | SD_WAKE_IDLE \ | SD_SHARE_PKG_RESOURCES\ | BALANCE_FOR_MC_POWER, \ .last_balance = jiffies, \ -- cgit v1.2.3-55-g7522