From cb2c0233755429037462e16ea0d5497a0092738c Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 7 Jul 2005 17:56:03 -0700 Subject: [PATCH] export generic_drop_inode() to modules OCFS2 wants to mark an inode which has been orphaned by another node so that during final iput it takes the correct path through the VFS and can pass through the OCFS2 delete_inode callback. Since i_nlink can get out of date with other nodes, the best way I see to accomplish this is by clearing i_nlink on those inodes at drop_inode time. Other than this small amount of work, nothing different needs to happen, so I think it would be cleanest to be able to just call generic_drop_inode at the end of the OCFS2 drop_inode callback. Signed-off-by: Mark Fasheh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index 047bde30836a..302ec20838ca 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1435,6 +1435,7 @@ extern struct inode * igrab(struct inode *); extern ino_t iunique(struct super_block *, ino_t); extern int inode_needs_sync(struct inode *inode); extern void generic_delete_inode(struct inode *inode); +extern void generic_drop_inode(struct inode *inode); extern struct inode *ilookup5(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), void *data); -- cgit v1.3-14-g43fede From 79b9ce311e192e9a31fd9f3cf1ee4a4edf9e2650 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 7 Jul 2005 17:56:04 -0700 Subject: [PATCH] print order information when OOM killing Dump the current allocation order when OOM killing. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/sysrq.c | 2 +- include/linux/swap.h | 2 +- mm/oom_kill.c | 4 ++-- mm/page_alloc.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index af79805b5576..12d563c648f7 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -228,7 +228,7 @@ static struct sysrq_key_op sysrq_term_op = { static void moom_callback(void *ignored) { - out_of_memory(GFP_KERNEL); + out_of_memory(GFP_KERNEL, 0); } static DECLARE_WORK(moom_work, moom_callback, NULL); diff --git a/include/linux/swap.h b/include/linux/swap.h index 2343f999e6e1..c75954f2d868 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -148,7 +148,7 @@ struct swap_list_t { #define vm_swap_full() (nr_swap_pages*2 < total_swap_pages) /* linux/mm/oom_kill.c */ -extern void out_of_memory(unsigned int __nocast gfp_mask); +extern void out_of_memory(unsigned int __nocast gfp_mask, int order); /* linux/mm/memory.c */ extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *); diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 59666d905f19..e20d559edbaf 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -253,12 +253,12 @@ static struct mm_struct *oom_kill_process(struct task_struct *p) * OR try to be smart about which process to kill. Note that we * don't have to be perfect here, we just have to be good. */ -void out_of_memory(unsigned int __nocast gfp_mask) +void out_of_memory(unsigned int __nocast gfp_mask, int order) { struct mm_struct *mm = NULL; task_t * p; - printk("oom-killer: gfp_mask=0x%x\n", gfp_mask); + printk("oom-killer: gfp_mask=0x%x, order=%d\n", gfp_mask, order); /* print memory stats */ show_mem(); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3c9f7f881125..7fbd3ea8765c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -936,7 +936,7 @@ rebalance: goto got_pg; } - out_of_memory(gfp_mask); + out_of_memory(gfp_mask, order); goto restart; } -- cgit v1.3-14-g43fede From a2f7a9ce2a5c3d21cc0eb37a03da603b44ba4b09 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 7 Jul 2005 17:56:11 -0700 Subject: [PATCH] ppc64: Fix runlatch code to work on pseries machines Not all ppc64 CPUs have the CTRL SPR, so we need a cputable feature for it. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/cputable.c | 8 ++++---- include/asm-ppc64/cputable.h | 3 ++- include/asm-ppc64/processor.h | 17 +++++++++++------ 3 files changed, 17 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c index c301366176ef..8d4c46f6f0b6 100644 --- a/arch/ppc64/kernel/cputable.c +++ b/arch/ppc64/kernel/cputable.c @@ -81,7 +81,7 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "RS64-II (northstar)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -94,7 +94,7 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "RS64-III (pulsar)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -107,7 +107,7 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "RS64-III (icestar)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, @@ -120,7 +120,7 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "RS64-IV (sstar)", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | - CPU_FTR_PMC8 | CPU_FTR_MMCRA, + CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL, .cpu_user_features = COMMON_USER_PPC64, .icache_bsize = 128, .dcache_bsize = 128, diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h index cbbfbec78b6b..d67fa9e26079 100644 --- a/include/asm-ppc64/cputable.h +++ b/include/asm-ppc64/cputable.h @@ -138,6 +138,7 @@ extern firmware_feature_t firmware_features_table[]; #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) +#define CPU_FTR_CTRL ASM_CONST(0x0000100000000000) /* Platform firmware features */ #define FW_FTR_ ASM_CONST(0x0000000000000001) @@ -148,7 +149,7 @@ extern firmware_feature_t firmware_features_table[]; #define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ - CPU_FTR_NODSISRALIGN) + CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL) /* iSeries doesn't support large pages */ #ifdef CONFIG_PPC_ISERIES diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h index af28aa55d8c1..06aa07c2c71d 100644 --- a/include/asm-ppc64/processor.h +++ b/include/asm-ppc64/processor.h @@ -20,6 +20,7 @@ #include #include #include +#include /* Machine State Register (MSR) Fields */ #define MSR_SF_LG 63 /* Enable 64 bit mode */ @@ -501,18 +502,22 @@ static inline void ppc64_runlatch_on(void) { unsigned long ctrl; - ctrl = mfspr(SPRN_CTRLF); - ctrl |= CTRL_RUNLATCH; - mtspr(SPRN_CTRLT, ctrl); + if (cpu_has_feature(CPU_FTR_CTRL)) { + ctrl = mfspr(SPRN_CTRLF); + ctrl |= CTRL_RUNLATCH; + mtspr(SPRN_CTRLT, ctrl); + } } static inline void ppc64_runlatch_off(void) { unsigned long ctrl; - ctrl = mfspr(SPRN_CTRLF); - ctrl &= ~CTRL_RUNLATCH; - mtspr(SPRN_CTRLT, ctrl); + if (cpu_has_feature(CPU_FTR_CTRL)) { + ctrl = mfspr(SPRN_CTRLF); + ctrl &= ~CTRL_RUNLATCH; + mtspr(SPRN_CTRLT, ctrl); + } } #endif /* __KERNEL__ */ -- cgit v1.3-14-g43fede From 8dc4fd87f229414fc38648508aad7def2275fe81 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 7 Jul 2005 17:56:12 -0700 Subject: [PATCH] ppc64: Turn runlatch on in exception entry Enable the runlatch at the start of each exception. Unfortunately we are out of space in the 0x300 handler, so I added it a bit later. The SPR write is fairly expensive, perhaps we should cache the runlatch state in the paca and avoid the write when possible. We don't need to turn the runlatch off, we do that in the idle loop. Better to take the hit in the idle loop than for each exception exit. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/head.S | 10 ++++++++++ include/asm-ppc64/processor.h | 9 +++++++++ 2 files changed, 19 insertions(+) (limited to 'include') diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 675c2708588f..93ebcac0d5a2 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -308,6 +308,7 @@ exception_marker: label##_pSeries: \ HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ + RUNLATCH_ON(r13); \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) #define STD_EXCEPTION_ISERIES(n, label, area) \ @@ -315,6 +316,7 @@ label##_pSeries: \ label##_iSeries: \ HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ + RUNLATCH_ON(r13); \ EXCEPTION_PROLOG_ISERIES_1(area); \ EXCEPTION_PROLOG_ISERIES_2; \ b label##_common @@ -324,6 +326,7 @@ label##_iSeries: \ label##_iSeries: \ HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ + RUNLATCH_ON(r13); \ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ lbz r10,PACAPROCENABLED(r13); \ cmpwi 0,r10,0; \ @@ -393,6 +396,7 @@ __start_interrupts: _machine_check_pSeries: HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ + RUNLATCH_ON(r13) EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) . = 0x300 @@ -419,6 +423,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) data_access_slb_pSeries: HMT_MEDIUM mtspr SPRG1,r13 + RUNLATCH_ON(r13) mfspr r13,SPRG3 /* get paca address into r13 */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ std r10,PACA_EXSLB+EX_R10(r13) @@ -439,6 +444,7 @@ data_access_slb_pSeries: instruction_access_slb_pSeries: HMT_MEDIUM mtspr SPRG1,r13 + RUNLATCH_ON(r13) mfspr r13,SPRG3 /* get paca address into r13 */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ std r10,PACA_EXSLB+EX_R10(r13) @@ -464,6 +470,7 @@ instruction_access_slb_pSeries: .globl system_call_pSeries system_call_pSeries: HMT_MEDIUM + RUNLATCH_ON(r9) mr r9,r13 mfmsr r10 mfspr r13,SPRG3 @@ -707,11 +714,13 @@ fwnmi_data_area: system_reset_fwnmi: HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ + RUNLATCH_ON(r13) EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) .globl machine_check_fwnmi machine_check_fwnmi: HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ + RUNLATCH_ON(r13) EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) /* @@ -848,6 +857,7 @@ unrecov_fer: .align 7 .globl data_access_common data_access_common: + RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */ mfspr r10,DAR std r10,PACA_EXGEN+EX_DAR(r13) mfspr r10,DSISR diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h index 06aa07c2c71d..352306cfb579 100644 --- a/include/asm-ppc64/processor.h +++ b/include/asm-ppc64/processor.h @@ -524,6 +524,15 @@ static inline void ppc64_runlatch_off(void) #endif /* __ASSEMBLY__ */ +#ifdef __KERNEL__ +#define RUNLATCH_ON(REG) \ +BEGIN_FTR_SECTION \ + mfspr (REG),SPRN_CTRLF; \ + ori (REG),(REG),CTRL_RUNLATCH; \ + mtspr SPRN_CTRLT,(REG); \ +END_FTR_SECTION_IFSET(CPU_FTR_CTRL) +#endif + /* * Number of entries in the SLB. If this ever changes we should handle * it with a use a cpu feature fixup. -- cgit v1.3-14-g43fede From cf36680887d6d942d2119c1ff1dfb2428b0f21f4 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 7 Jul 2005 17:56:13 -0700 Subject: [PATCH] move ioprio syscalls into syscalls.h - Make ioprio syscalls return long, like set/getpriority syscalls. - Move function prototypes into syscalls.h so we can pick them up in the 32/64bit compat code. Signed-off-by: Anton Blanchard Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ioprio.c | 4 ++-- include/linux/ioprio.h | 3 --- include/linux/syscalls.h | 3 +++ 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/fs/ioprio.c b/fs/ioprio.c index 663e420636d6..97e1f088ba00 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -43,7 +43,7 @@ static int set_task_ioprio(struct task_struct *task, int ioprio) return 0; } -asmlinkage int sys_ioprio_set(int which, int who, int ioprio) +asmlinkage long sys_ioprio_set(int which, int who, int ioprio) { int class = IOPRIO_PRIO_CLASS(ioprio); int data = IOPRIO_PRIO_DATA(ioprio); @@ -115,7 +115,7 @@ asmlinkage int sys_ioprio_set(int which, int who, int ioprio) return ret; } -asmlinkage int sys_ioprio_get(int which, int who) +asmlinkage long sys_ioprio_get(int which, int who) { struct task_struct *g, *p; struct user_struct *user; diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h index 8a453a0b5e4b..88d5961f7a3f 100644 --- a/include/linux/ioprio.h +++ b/include/linux/ioprio.h @@ -34,9 +34,6 @@ enum { */ #define IOPRIO_BE_NR (8) -asmlinkage int sys_ioprio_set(int, int, int); -asmlinkage int sys_ioprio_get(int, int); - enum { IOPRIO_WHO_PROCESS = 1, IOPRIO_WHO_PGRP, diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 52830b6d94e5..425f58c8ea4a 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -506,4 +506,7 @@ asmlinkage long sys_request_key(const char __user *_type, asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); +asmlinkage long sys_ioprio_set(int which, int who, int ioprio); +asmlinkage long sys_ioprio_get(int which, int who); + #endif -- cgit v1.3-14-g43fede From 79c2cc7b6d2cc31cff6a3d8e966a890f0a0d5f7a Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 7 Jul 2005 17:56:15 -0700 Subject: [PATCH] ppc64: add ioprio syscalls - Clean up sys32_getpriority comment. - Add ioprio syscalls, and sign extend 32bit versions. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/misc.S | 6 +++++- arch/ppc64/kernel/sys_ppc32.c | 27 +++++++++++++++++---------- include/asm-ppc64/unistd.h | 4 +++- 3 files changed, 25 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index f3dea0c5a88c..59f4f9973818 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -1124,9 +1124,11 @@ _GLOBAL(sys_call_table32) .llong .compat_sys_mq_getsetattr .llong .compat_sys_kexec_load .llong .sys32_add_key - .llong .sys32_request_key + .llong .sys32_request_key /* 270 */ .llong .compat_sys_keyctl .llong .compat_sys_waitid + .llong .sys32_ioprio_set + .llong .sys32_ioprio_get .balign 8 _GLOBAL(sys_call_table) @@ -1403,3 +1405,5 @@ _GLOBAL(sys_call_table) .llong .sys_request_key /* 270 */ .llong .sys_keyctl .llong .sys_waitid + .llong .sys_ioprio_set + .llong .sys_ioprio_get diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c index 9bd16cef0ed4..206619080e66 100644 --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c @@ -822,16 +822,6 @@ asmlinkage long sys32_getpgid(u32 pid) } -/* Note: it is necessary to treat which and who as unsigned ints, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_getpriority(u32 which, u32 who) -{ - return sys_getpriority((int)which, (int)who); -} - /* Note: it is necessary to treat pid as an unsigned int, * with the corresponding cast to a signed int to insure that the @@ -1023,6 +1013,11 @@ asmlinkage long sys32_setpgid(u32 pid, u32 pgid) return sys_setpgid((int)pid, (int)pgid); } +long sys32_getpriority(u32 which, u32 who) +{ + /* sign extend which and who */ + return sys_getpriority((int)which, (int)who); +} long sys32_setpriority(u32 which, u32 who, u32 niceval) { @@ -1030,6 +1025,18 @@ long sys32_setpriority(u32 which, u32 who, u32 niceval) return sys_setpriority((int)which, (int)who, (int)niceval); } +long sys32_ioprio_get(u32 which, u32 who) +{ + /* sign extend which and who */ + return sys_ioprio_get((int)which, (int)who); +} + +long sys32_ioprio_set(u32 which, u32 who, u32 ioprio) +{ + /* sign extend which, who and ioprio */ + return sys_ioprio_set((int)which, (int)who, (int)ioprio); +} + /* Note: it is necessary to treat newmask as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h index 605d91e011ec..53fc662d8009 100644 --- a/include/asm-ppc64/unistd.h +++ b/include/asm-ppc64/unistd.h @@ -283,8 +283,10 @@ #define __NR_request_key 270 #define __NR_keyctl 271 #define __NR_waitid 272 +#define __NR_ioprio_set 273 +#define __NR_ioprio_get 274 -#define __NR_syscalls 273 +#define __NR_syscalls 275 #ifdef __KERNEL__ #define NR_syscalls __NR_syscalls #endif -- cgit v1.3-14-g43fede From 5cee73fa04758f52b7404b93a02edf74649370ab Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 7 Jul 2005 17:56:15 -0700 Subject: [PATCH] ppc64: remove duplicate syscall reservation We already have a prototype for sys_remap_file_pages (239) so there is no need to reserve it twice. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ppc/unistd.h | 2 +- include/asm-ppc64/unistd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h index e8b79220b29c..a7894e0fbbb1 100644 --- a/include/asm-ppc/unistd.h +++ b/include/asm-ppc/unistd.h @@ -262,7 +262,7 @@ #define __NR_rtas 255 #define __NR_sys_debug_setcontext 256 /* Number 257 is reserved for vserver */ -/* Number 258 is reserved for new sys_remap_file_pages */ +/* 258 currently unused */ /* Number 259 is reserved for new sys_mbind */ /* Number 260 is reserved for new sys_get_mempolicy */ /* Number 261 is reserved for new sys_set_mempolicy */ diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h index 53fc662d8009..4a94acf6bfed 100644 --- a/include/asm-ppc64/unistd.h +++ b/include/asm-ppc64/unistd.h @@ -268,7 +268,7 @@ #define __NR_rtas 255 /* Number 256 is reserved for sys_debug_setcontext */ /* Number 257 is reserved for vserver */ -/* Number 258 is reserved for new sys_remap_file_pages */ +/* 258 currently unused */ #define __NR_mbind 259 #define __NR_get_mempolicy 260 #define __NR_set_mempolicy 261 -- cgit v1.3-14-g43fede From d5ee257c3342185ba8ab642d125d192eb99ea8f2 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Thu, 7 Jul 2005 17:56:24 -0700 Subject: [PATCH] hvc_console: Separate hvc_console and vio code Separate the console setup routines of the hvc_console and the vio layer. Remove the call to find_init_vty from hvc_console.c. Fail the setup routine if the console doesn't exist, but register the console again when the specified channel is instantiated. This scheme maintains the print buffer semantics while eliminating callout and call back for the console code. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/hvconsole.c | 3 ++- drivers/char/hvc_console.c | 24 ++++++++++++++++++++++-- include/asm-ppc64/hvconsole.h | 5 +---- 3 files changed, 25 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/ppc64/kernel/hvconsole.c index c72fb8ffe974..94fb06198ea2 100644 --- a/arch/ppc64/kernel/hvconsole.c +++ b/arch/ppc64/kernel/hvconsole.c @@ -93,7 +93,7 @@ EXPORT_SYMBOL(hvc_put_chars); * We hope/assume that the first vty found corresponds to the first console * device. */ -int hvc_find_vtys(void) +static int hvc_find_vtys(void) { struct device_node *vty; int num_found = 0; @@ -119,3 +119,4 @@ int hvc_find_vtys(void) return num_found; } +console_initcall(hvc_find_vtys); diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 7bc65a76dfc4..d59c642f9654 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -219,10 +219,23 @@ struct console hvc_con_driver = { .index = -1, }; -/* Early console initialization. Preceeds driver initialization. */ +/* + * Early console initialization. Preceeds driver initialization. + * + * (1) we are first, and the user specified another driver + * -- index will remain -1 + * (2) we are first and the user specified no driver + * -- index will be set to 0, then we will fail setup. + * (3) we are first and the user specified our driver + * -- index will be set to user specified driver, and we will fail + * (4) we are after driver, and this initcall will register us + * -- if the user didn't specify a driver then the console will match + * + * Note that for cases 2 and 3, we will match later when the io driver + * calls hvc_instantiate() and call register again. + */ static int __init hvc_console_init(void) { - hvc_find_vtys(); register_console(&hvc_con_driver); return 0; } @@ -257,6 +270,13 @@ int hvc_instantiate(uint32_t vtermno, int index) if (last_hvc < index) last_hvc = index; + /* if this index is what the user requested, then register + * now (setup won't fail at this point). It's ok to just + * call register again if previously .setup failed. + */ + if (index == hvc_con_driver.index) + register_console(&hvc_con_driver); + return 0; } diff --git a/include/asm-ppc64/hvconsole.h b/include/asm-ppc64/hvconsole.h index d89d94c91815..91c2414ac00b 100644 --- a/include/asm-ppc64/hvconsole.h +++ b/include/asm-ppc64/hvconsole.h @@ -32,9 +32,6 @@ extern int hvc_get_chars(uint32_t vtermno, char *buf, int count); extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count); -/* Early discovery of console adapters. */ -extern int hvc_find_vtys(void); - -/* Implemented by a console driver */ +/* Register a vterm and a slot index for use as a console */ extern int hvc_instantiate(uint32_t vtermno, int index); #endif /* _PPC64_HVCONSOLE_H */ -- cgit v1.3-14-g43fede From acad9559f1054487292eb10d7bb81f256e9d8f2d Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Thu, 7 Jul 2005 17:56:24 -0700 Subject: [PATCH] hvc_console: Separate hvc_console and vio code 2 Remove all the vio device driver code from hvc_console.c This will allow us to separate hvsi, hvc, and allow hvc_console to be used without the ppc64 vio layer. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/hvconsole.c | 33 ----------- drivers/char/Makefile | 2 +- drivers/char/hvc_console.c | 50 ++++------------- drivers/char/hvc_vio.c | 125 ++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc64/hvconsole.h | 9 ++- 5 files changed, 145 insertions(+), 74 deletions(-) create mode 100644 drivers/char/hvc_vio.c (limited to 'include') diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/ppc64/kernel/hvconsole.c index 94fb06198ea2..9d8876d92eb9 100644 --- a/arch/ppc64/kernel/hvconsole.c +++ b/arch/ppc64/kernel/hvconsole.c @@ -27,7 +27,6 @@ #include #include #include -#include /** * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper @@ -88,35 +87,3 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count) } EXPORT_SYMBOL(hvc_put_chars); - -/* - * We hope/assume that the first vty found corresponds to the first console - * device. - */ -static int hvc_find_vtys(void) -{ - struct device_node *vty; - int num_found = 0; - - for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL; - vty = of_find_node_by_name(vty, "vty")) { - uint32_t *vtermno; - - /* We have statically defined space for only a certain number of - * console adapters. */ - if (num_found >= MAX_NR_HVC_CONSOLES) - break; - - vtermno = (uint32_t *)get_property(vty, "reg", NULL); - if (!vtermno) - continue; - - if (device_is_compatible(vty, "hvterm1")) { - hvc_instantiate(*vtermno, num_found); - ++num_found; - } - } - - return num_found; -} -console_initcall(hvc_find_vtys); diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 1aff819f3832..08f69287ea36 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o -obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o +obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MMTIMER) += mmtimer.o diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index d59c642f9654..df282cc9a7ab 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -41,7 +41,6 @@ #include #include #include -#include #define HVC_MAJOR 229 #define HVC_MINOR 0 @@ -90,7 +89,6 @@ struct hvc_struct { int irq; struct list_head next; struct kobject kobj; /* ref count & hvc_struct lifetime */ - struct vio_dev *vdev; }; /* dynamic list of hvc_struct instances */ @@ -279,6 +277,7 @@ int hvc_instantiate(uint32_t vtermno, int index) return 0; } +EXPORT_SYMBOL(hvc_instantiate); /* Wake the sleeping khvcd */ static void hvc_kick(void) @@ -738,26 +737,19 @@ static struct kobj_type hvc_kobj_type = { .release = destroy_hvc_struct, }; -static int __devinit hvc_probe( - struct vio_dev *dev, - const struct vio_device_id *id) +struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq) { struct hvc_struct *hp; int i; - /* probed with invalid parameters. */ - if (!dev || !id) - return -EPERM; - hp = kmalloc(sizeof(*hp), GFP_KERNEL); if (!hp) - return -ENOMEM; + return ERR_PTR(-ENOMEM); memset(hp, 0x00, sizeof(*hp)); - hp->vtermno = dev->unit_address; - hp->vdev = dev; - hp->vdev->dev.driver_data = hp; - hp->irq = dev->irq; + + hp->vtermno = vtermno; + hp->irq = irq; kobject_init(&hp->kobj); hp->kobj.ktype = &hvc_kobj_type; @@ -782,12 +774,12 @@ static int __devinit hvc_probe( list_add_tail(&(hp->next), &hvc_structs); spin_unlock(&hvc_structs_lock); - return 0; + return hp; } +EXPORT_SYMBOL(hvc_alloc); -static int __devexit hvc_remove(struct vio_dev *dev) +int __devexit hvc_remove(struct hvc_struct *hp) { - struct hvc_struct *hp = dev->dev.driver_data; unsigned long flags; struct kobject *kobjp; struct tty_struct *tty; @@ -820,28 +812,12 @@ static int __devexit hvc_remove(struct vio_dev *dev) tty_hangup(tty); return 0; } - -char hvc_driver_name[] = "hvc_console"; - -static struct vio_device_id hvc_driver_table[] __devinitdata= { - {"serial", "hvterm1"}, - { NULL, } -}; -MODULE_DEVICE_TABLE(vio, hvc_driver_table); - -static struct vio_driver hvc_vio_driver = { - .name = hvc_driver_name, - .id_table = hvc_driver_table, - .probe = hvc_probe, - .remove = hvc_remove, -}; +EXPORT_SYMBOL(hvc_remove); /* Driver initialization. Follow console initialization. This is where the TTY * interfaces start to become available. */ int __init hvc_init(void) { - int rc; - /* We need more than hvc_count adapters due to hotplug additions. */ hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); if (!hvc_driver) @@ -870,10 +846,7 @@ int __init hvc_init(void) return -EIO; } - /* Register as a vio device to receive callbacks */ - rc = vio_register_driver(&hvc_vio_driver); - - return rc; + return 0; } module_init(hvc_init); @@ -884,7 +857,6 @@ static void __exit hvc_exit(void) { kthread_stop(hvc_task); - vio_unregister_driver(&hvc_vio_driver); tty_unregister_driver(hvc_driver); /* return tty_struct instances allocated in hvc_init(). */ put_tty_driver(hvc_driver); diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c new file mode 100644 index 000000000000..d2928f90ab51 --- /dev/null +++ b/drivers/char/hvc_vio.c @@ -0,0 +1,125 @@ +/* + * vio driver interface to hvc_console.c + * + * This code was moved here to allow the remaing code to be reused as a + * generic polling mode with semi-reliable transport driver core to the + * console and tty subsystems. + * + * + * Copyright (C) 2001 Anton Blanchard , IBM + * Copyright (C) 2001 Paul Mackerras , IBM + * Copyright (C) 2004 Benjamin Herrenschmidt , IBM Corp. + * Copyright (C) 2004 IBM Corporation + * + * Additional Author(s): + * Ryan S. Arnold + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +char hvc_driver_name[] = "hvc_console"; + +static struct vio_device_id hvc_driver_table[] __devinitdata = { + {"serial", "hvterm1"}, + { NULL, } +}; +MODULE_DEVICE_TABLE(vio, hvc_driver_table); + +static int __devinit hvc_vio_probe(struct vio_dev *vdev, + const struct vio_device_id *id) +{ + struct hvc_struct *hp; + + /* probed with invalid parameters. */ + if (!vdev || !id) + return -EPERM; + + hp = hvc_alloc(vdev->unit_address, vdev->irq); + if (IS_ERR(hp)) + return PTR_ERR(hp); + dev_set_drvdata(&vdev->dev, hp); + + return 0; +} + +static int __devexit hvc_vio_remove(struct vio_dev *vdev) +{ + struct hvc_struct *hp = dev_get_drvdata(&vdev->dev); + + return hvc_remove(hp); +} + +static struct vio_driver hvc_vio_driver = { + .name = hvc_driver_name, + .id_table = hvc_driver_table, + .probe = hvc_vio_probe, + .remove = hvc_vio_remove, + .driver = { + .owner = THIS_MODULE, + } +}; + +static int hvc_vio_init(void) +{ + int rc; + + /* Register as a vio device to receive callbacks */ + rc = vio_register_driver(&hvc_vio_driver); + + return rc; +} +module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ + +static void hvc_vio_exit(void) +{ + vio_unregister_driver(&hvc_vio_driver); +} +module_exit(hvc_vio_exit); + +/* the device tree order defines our numbering */ +static int hvc_find_vtys(void) +{ + struct device_node *vty; + int num_found = 0; + + for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL; + vty = of_find_node_by_name(vty, "vty")) { + uint32_t *vtermno; + + /* We have statically defined space for only a certain number + * of console adapters. + */ + if (num_found >= MAX_NR_HVC_CONSOLES) + break; + + vtermno = (uint32_t *)get_property(vty, "reg", NULL); + if (!vtermno) + continue; + + if (device_is_compatible(vty, "hvterm1")) { + hvc_instantiate(*vtermno, num_found); + ++num_found; + } + } + + return num_found; +} +console_initcall(hvc_find_vtys); diff --git a/include/asm-ppc64/hvconsole.h b/include/asm-ppc64/hvconsole.h index 91c2414ac00b..14667a78716d 100644 --- a/include/asm-ppc64/hvconsole.h +++ b/include/asm-ppc64/hvconsole.h @@ -29,9 +29,16 @@ */ #define MAX_NR_HVC_CONSOLES 16 +/* implemented by a low level driver */ extern int hvc_get_chars(uint32_t vtermno, char *buf, int count); extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count); -/* Register a vterm and a slot index for use as a console */ +struct hvc_struct; + +/* Register a vterm and a slot index for use as a console (console_init) */ extern int hvc_instantiate(uint32_t vtermno, int index); +/* register a vterm for hvc tty operation (module_init or hotplug add) */ +extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq); +/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ +extern int __devexit hvc_remove(struct hvc_struct *hp); #endif /* _PPC64_HVCONSOLE_H */ -- cgit v1.3-14-g43fede From 030ffad23fb28fc29608a3bc21f0c3b88bf28592 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Thu, 7 Jul 2005 17:56:25 -0700 Subject: [PATCH] hvc_console: Register ops when setting up hvc_console When registering the hvc console port, register a list of ops (read and write) to go with it, instead of calling fixed function names. This allows different ports to encode the data differently. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hvc_console.c | 21 +++++++++++++-------- drivers/char/hvc_vio.c | 9 +++++++-- include/asm-ppc64/hvconsole.h | 9 +++++++-- 3 files changed, 27 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index df282cc9a7ab..cddb789902db 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -85,6 +85,7 @@ struct hvc_struct { char outbuf[N_OUTBUF] __ALIGNED__; int n_outbuf; uint32_t vtermno; + struct hv_ops *ops; int irq_requested; int irq; struct list_head next; @@ -142,6 +143,7 @@ struct hvc_struct *hvc_get_by_index(int index) * console interfaces but can still be used as a tty device. This has to be * static because kmalloc will not work during early console init. */ +static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES]; static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1}; @@ -154,14 +156,14 @@ void hvc_console_print(struct console *co, const char *b, unsigned count) { char c[16] __ALIGNED__; unsigned i = 0, n = 0; - int r, donecr = 0; + int r, donecr = 0, index = co->index; /* Console access attempt outside of acceptable console range. */ - if (co->index >= MAX_NR_HVC_CONSOLES) + if (index >= MAX_NR_HVC_CONSOLES) return; /* This console adapter was removed so it is not useable. */ - if (vtermnos[co->index] < 0) + if (vtermnos[index] < 0) return; while (count > 0 || i > 0) { @@ -175,7 +177,7 @@ void hvc_console_print(struct console *co, const char *b, unsigned count) --count; } } else { - r = hvc_put_chars(vtermnos[co->index], c, i); + r = cons_ops[index]->put_chars(vtermnos[index], c, i); if (r < 0) { /* throw away chars on error */ i = 0; @@ -245,7 +247,7 @@ console_initcall(hvc_console_init); * vty adapters do NOT get an hvc_instantiate() callback since they * appear after early console init. */ -int hvc_instantiate(uint32_t vtermno, int index) +int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) { struct hvc_struct *hp; @@ -263,6 +265,7 @@ int hvc_instantiate(uint32_t vtermno, int index) } vtermnos[index] = vtermno; + cons_ops[index] = ops; /* reserve all indices upto and including this index */ if (last_hvc < index) @@ -466,7 +469,7 @@ static void hvc_push(struct hvc_struct *hp) { int n; - n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf); + n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf); if (n <= 0) { if (n == 0) return; @@ -604,7 +607,7 @@ static int hvc_poll(struct hvc_struct *hp) break; } - n = hvc_get_chars(hp->vtermno, buf, count); + n = hp->ops->get_chars(hp->vtermno, buf, count); if (n <= 0) { /* Hangup the tty when disconnected from host */ if (n == -EPIPE) { @@ -737,7 +740,8 @@ static struct kobj_type hvc_kobj_type = { .release = destroy_hvc_struct, }; -struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq) +struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, + struct hv_ops *ops) { struct hvc_struct *hp; int i; @@ -750,6 +754,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq) hp->vtermno = vtermno; hp->irq = irq; + hp->ops = ops; kobject_init(&hp->kobj); hp->kobj.ktype = &hvc_kobj_type; diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index d2928f90ab51..430a2c284ad2 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -43,6 +43,11 @@ static struct vio_device_id hvc_driver_table[] __devinitdata = { }; MODULE_DEVICE_TABLE(vio, hvc_driver_table); +static struct hv_ops hvc_get_put_ops = { + .get_chars = hvc_get_chars, + .put_chars = hvc_put_chars, +}; + static int __devinit hvc_vio_probe(struct vio_dev *vdev, const struct vio_device_id *id) { @@ -52,7 +57,7 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev, if (!vdev || !id) return -EPERM; - hp = hvc_alloc(vdev->unit_address, vdev->irq); + hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops); if (IS_ERR(hp)) return PTR_ERR(hp); dev_set_drvdata(&vdev->dev, hp); @@ -115,7 +120,7 @@ static int hvc_find_vtys(void) continue; if (device_is_compatible(vty, "hvterm1")) { - hvc_instantiate(*vtermno, num_found); + hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops); ++num_found; } } diff --git a/include/asm-ppc64/hvconsole.h b/include/asm-ppc64/hvconsole.h index 14667a78716d..6da93ce74dc0 100644 --- a/include/asm-ppc64/hvconsole.h +++ b/include/asm-ppc64/hvconsole.h @@ -30,15 +30,20 @@ #define MAX_NR_HVC_CONSOLES 16 /* implemented by a low level driver */ +struct hv_ops { + int (*get_chars)(uint32_t vtermno, char *buf, int count); + int (*put_chars)(uint32_t vtermno, const char *buf, int count); +}; extern int hvc_get_chars(uint32_t vtermno, char *buf, int count); extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count); struct hvc_struct; /* Register a vterm and a slot index for use as a console (console_init) */ -extern int hvc_instantiate(uint32_t vtermno, int index); +extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); /* register a vterm for hvc tty operation (module_init or hotplug add) */ -extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq); +extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, + struct hv_ops *ops); /* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ extern int __devexit hvc_remove(struct hvc_struct *hp); #endif /* _PPC64_HVCONSOLE_H */ -- cgit v1.3-14-g43fede From fd899c0cc725387992ccfc83fb6f70505c36cbeb Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 7 Jul 2005 17:56:28 -0700 Subject: [PATCH] ppc64: Make idle_loop a ppc_md function This patch adds an idle member to the ppc_md structure and calls it from cpu_idle(). If a platform leaves ppc_md.idle as null it will get the default idle loop default_idle(). Signed-off-by: Michael Ellerman Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/idle.c | 8 +++++--- arch/ppc64/kernel/setup.c | 6 +++--- include/asm-ppc64/machdep.h | 5 +++++ 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 08952c7e6216..e270055e73e2 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c @@ -33,6 +33,7 @@ #include #include #include +#include extern void power4_idle(void); @@ -122,7 +123,7 @@ static int iSeries_idle(void) #else -static int default_idle(void) +int default_idle(void) { long oldval; unsigned int cpu = smp_processor_id(); @@ -288,7 +289,7 @@ static int shared_idle(void) #endif /* CONFIG_PPC_PSERIES */ -static int native_idle(void) +int native_idle(void) { while(1) { /* check CPU type here */ @@ -308,7 +309,8 @@ static int native_idle(void) void cpu_idle(void) { - idle_loop(); + BUG_ON(NULL == ppc_md.idle_loop); + ppc_md.idle_loop(); } int powersave_nap; diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index d5e4866e9ac2..a278998ecb44 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c @@ -96,7 +96,6 @@ extern void udbg_init_maple_realmode(void); extern unsigned long klimit; extern void mm_init_ppc64(void); -extern int idle_setup(void); extern void stab_initialize(unsigned long stab); extern void htab_initialize(void); extern void early_init_devtree(void *flat_dt); @@ -1081,8 +1080,9 @@ void __init setup_arch(char **cmdline_p) ppc_md.setup_arch(); - /* Select the correct idle loop for the platform. */ - idle_setup(); + /* Use the default idle loop if the platform hasn't provided one. */ + if (NULL == ppc_md.idle_loop) + ppc_md.idle_loop = default_idle; paging_init(); ppc64_boot_msg(0x15, "Setup Done"); diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h index 9cdad3ed1526..1e6ad4824132 100644 --- a/include/asm-ppc64/machdep.h +++ b/include/asm-ppc64/machdep.h @@ -140,8 +140,13 @@ struct machdep_calls { unsigned long size, pgprot_t vma_prot); + /* Idle loop for this platform, leave empty for default idle loop */ + int (*idle_loop)(void); }; +extern int default_idle(void); +extern int native_idle(void); + extern struct machdep_calls ppc_md; extern char cmd_line[COMMAND_LINE_SIZE]; -- cgit v1.3-14-g43fede From 3b520b238e018ef0e9d11c9115d5e7d9419c4ef9 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 7 Jul 2005 17:56:38 -0700 Subject: [PATCH] MTRR suspend/resume cleanup There has been some discuss about solving the SMP MTRR suspend/resume breakage, but I didn't find a patch for it. This is an intent for it. The basic idea is moving mtrr initializing into cpu_identify for all APs (so it works for cpu hotplug). For BP, restore_processor_state is responsible for restoring MTRR. Signed-off-by: Shaohua Li Acked-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 5 +++ arch/i386/kernel/cpu/mtrr/generic.c | 22 +++++------ arch/i386/kernel/cpu/mtrr/main.c | 76 ++++++++++++++++++++++++++----------- arch/i386/kernel/cpu/mtrr/mtrr.h | 1 - arch/i386/power/cpu.c | 1 + arch/x86_64/kernel/setup.c | 4 ++ arch/x86_64/kernel/suspend.c | 1 + include/asm-i386/processor.h | 8 ++++ include/asm-x86_64/proto.h | 7 ++++ 9 files changed, 90 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 2203a9d20212..4553ffd94b1f 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -435,6 +435,11 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) if (c == &boot_cpu_data) sysenter_setup(); enable_sep_cpu(); + + if (c == &boot_cpu_data) + mtrr_bp_init(); + else + mtrr_ap_init(); } #ifdef CONFIG_X86_HT diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c index 64d91f73a0a4..169ac8e0db68 100644 --- a/arch/i386/kernel/cpu/mtrr/generic.c +++ b/arch/i386/kernel/cpu/mtrr/generic.c @@ -67,13 +67,6 @@ void __init get_mtrr_state(void) mtrr_state.enabled = (lo & 0xc00) >> 10; } -/* Free resources associated with a struct mtrr_state */ -void __init finalize_mtrr_state(void) -{ - kfree(mtrr_state.var_ranges); - mtrr_state.var_ranges = NULL; -} - /* Some BIOS's are fucked and don't set all MTRRs the same! */ void __init mtrr_state_warn(void) { @@ -334,6 +327,9 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base, */ { unsigned long flags; + struct mtrr_var_range *vr; + + vr = &mtrr_state.var_ranges[reg]; local_irq_save(flags); prepare_set(); @@ -342,11 +338,15 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base, /* The invalid bit is kept in the mask, so we simply clear the relevant mask register to disable a range. */ mtrr_wrmsr(MTRRphysMask_MSR(reg), 0, 0); + memset(vr, 0, sizeof(struct mtrr_var_range)); } else { - mtrr_wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type, - (base & size_and_mask) >> (32 - PAGE_SHIFT)); - mtrr_wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800, - (-size & size_and_mask) >> (32 - PAGE_SHIFT)); + vr->base_lo = base << PAGE_SHIFT | type; + vr->base_hi = (base & size_and_mask) >> (32 - PAGE_SHIFT); + vr->mask_lo = -size << PAGE_SHIFT | 0x800; + vr->mask_hi = (-size & size_and_mask) >> (32 - PAGE_SHIFT); + + mtrr_wrmsr(MTRRphysBase_MSR(reg), vr->base_lo, vr->base_hi); + mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi); } post_set(); diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index d66b09e0c820..764cac64e211 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c @@ -332,6 +332,8 @@ int mtrr_add_page(unsigned long base, unsigned long size, error = -EINVAL; + /* No CPU hotplug when we change MTRR entries */ + lock_cpu_hotplug(); /* Search for existing MTRR */ down(&main_lock); for (i = 0; i < num_var_ranges; ++i) { @@ -372,6 +374,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, error = i; out: up(&main_lock); + unlock_cpu_hotplug(); return error; } @@ -461,6 +464,8 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) return -ENXIO; max = num_var_ranges; + /* No CPU hotplug when we change MTRR entries */ + lock_cpu_hotplug(); down(&main_lock); if (reg < 0) { /* Search for existing MTRR */ @@ -501,6 +506,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) error = reg; out: up(&main_lock); + unlock_cpu_hotplug(); return error; } /** @@ -544,21 +550,9 @@ static void __init init_ifs(void) centaur_init_mtrr(); } -static void __init init_other_cpus(void) -{ - if (use_intel()) - get_mtrr_state(); - - /* bring up the other processors */ - set_mtrr(~0U,0,0,0); - - if (use_intel()) { - finalize_mtrr_state(); - mtrr_state_warn(); - } -} - - +/* The suspend/resume methods are only for CPU without MTRR. CPU using generic + * MTRR driver doesn't require this + */ struct mtrr_value { mtrr_type ltype; unsigned long lbase; @@ -611,13 +605,13 @@ static struct sysdev_driver mtrr_sysdev_driver = { /** - * mtrr_init - initialize mtrrs on the boot CPU + * mtrr_bp_init - initialize mtrrs on the boot CPU * * This needs to be called early; before any of the other CPUs are * initialized (i.e. before smp_init()). * */ -static int __init mtrr_init(void) +void __init mtrr_bp_init(void) { init_ifs(); @@ -674,12 +668,48 @@ static int __init mtrr_init(void) if (mtrr_if) { set_num_var_ranges(); init_table(); - init_other_cpus(); - - return sysdev_driver_register(&cpu_sysdev_class, - &mtrr_sysdev_driver); + if (use_intel()) + get_mtrr_state(); } - return -ENXIO; } -subsys_initcall(mtrr_init); +void mtrr_ap_init(void) +{ + unsigned long flags; + + if (!mtrr_if || !use_intel()) + return; + /* + * Ideally we should hold main_lock here to avoid mtrr entries changed, + * but this routine will be called in cpu boot time, holding the lock + * breaks it. This routine is called in two cases: 1.very earily time + * of software resume, when there absolutely isn't mtrr entry changes; + * 2.cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug lock to + * prevent mtrr entry changes + */ + local_irq_save(flags); + + mtrr_if->set_all(); + + local_irq_restore(flags); +} + +static int __init mtrr_init_finialize(void) +{ + if (!mtrr_if) + return 0; + if (use_intel()) + mtrr_state_warn(); + else { + /* The CPUs haven't MTRR and seemes not support SMP. They have + * specific drivers, we use a tricky method to support + * suspend/resume for them. + * TBD: is there any system with such CPU which supports + * suspend/resume? if no, we should remove the code. + */ + sysdev_driver_register(&cpu_sysdev_class, + &mtrr_sysdev_driver); + } + return 0; +} +subsys_initcall(mtrr_init_finialize); diff --git a/arch/i386/kernel/cpu/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h index de1351245599..99c9f2682041 100644 --- a/arch/i386/kernel/cpu/mtrr/mtrr.h +++ b/arch/i386/kernel/cpu/mtrr/mtrr.h @@ -91,7 +91,6 @@ extern struct mtrr_ops * mtrr_if; extern unsigned int num_var_ranges; -void finalize_mtrr_state(void); void mtrr_state_warn(void); char *mtrr_attrib_to_str(int x); void mtrr_wrmsr(unsigned, unsigned, unsigned); diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 0e6b45b61251..c547c1af6fa1 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -137,6 +137,7 @@ void __restore_processor_state(struct saved_context *ctxt) fix_processor_context(); do_fpu_end(); + mtrr_ap_init(); } void restore_processor_state(void) diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index b02d921da4f7..5fd03225058a 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -1076,6 +1076,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) #ifdef CONFIG_X86_MCE mcheck_init(c); #endif + if (c == &boot_cpu_data) + mtrr_bp_init(); + else + mtrr_ap_init(); #ifdef CONFIG_NUMA if (c != &boot_cpu_data) numa_add_cpu(c - cpu_data); diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c index 6c0f402e3a88..0612640d91b1 100644 --- a/arch/x86_64/kernel/suspend.c +++ b/arch/x86_64/kernel/suspend.c @@ -119,6 +119,7 @@ void __restore_processor_state(struct saved_context *ctxt) fix_processor_context(); do_fpu_end(); + mtrr_ap_init(); } void restore_processor_state(void) diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 6f0f93d0d417..5d06e6bd6ba0 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -694,4 +694,12 @@ extern unsigned long boot_option_idle_override; extern void enable_sep_cpu(void); extern int sysenter_setup(void); +#ifdef CONFIG_MTRR +extern void mtrr_ap_init(void); +extern void mtrr_bp_init(void); +#else +#define mtrr_ap_init() do {} while (0) +#define mtrr_bp_init() do {} while (0) +#endif + #endif /* __ASM_I386_PROCESSOR_H */ diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index f2f073642d62..6c813eb521f3 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h @@ -15,6 +15,13 @@ extern void pda_init(int); extern void early_idt_handler(void); extern void mcheck_init(struct cpuinfo_x86 *c); +#ifdef CONFIG_MTRR +extern void mtrr_ap_init(void); +extern void mtrr_bp_init(void); +#else +#define mtrr_ap_init() do {} while (0) +#define mtrr_bp_init() do {} while (0) +#endif extern void init_memory_mapping(unsigned long start, unsigned long end); extern void system_call(void); -- cgit v1.3-14-g43fede From 8ff8b27bb8ebfd863b49653da1b7bbd8609fcd7e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 7 Jul 2005 17:56:39 -0700 Subject: [PATCH] Clean up numa defines in mmzone.h The recent cleanups to asm-i386/mmzone.h were suboptimal nesting an ifdef of the same symbol. This patch removes some of the ifdef'ery to make things more readable again. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/mmzone.h | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h index 33ce5d37e894..08e3cfd86328 100644 --- a/include/asm-i386/mmzone.h +++ b/include/asm-i386/mmzone.h @@ -8,20 +8,15 @@ #include -#if CONFIG_NUMA +#ifdef CONFIG_NUMA extern struct pglist_data *node_data[]; #define NODE_DATA(nid) (node_data[nid]) -#ifdef CONFIG_NUMA - #ifdef CONFIG_X86_NUMAQ - #include - #else /* summit or generic arch */ - #include - #endif -#else /* !CONFIG_NUMA */ - #define get_memcfg_numa get_memcfg_numa_flat - #define get_zholes_size(n) (0) -#endif /* CONFIG_NUMA */ +#ifdef CONFIG_X86_NUMAQ + #include +#else /* summit or generic arch */ + #include +#endif extern int get_memcfg_numa_flat(void ); /* @@ -42,6 +37,9 @@ static inline void get_memcfg_numa(void) get_memcfg_numa_flat(); } +#else /* !CONFIG_NUMA */ +#define get_memcfg_numa get_memcfg_numa_flat +#define get_zholes_size(n) (0) #endif /* CONFIG_NUMA */ #ifdef CONFIG_DISCONTIGMEM -- cgit v1.3-14-g43fede From e8af300c3bd87b2310f1e7a642f37e0fe49a754b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 7 Jul 2005 17:56:39 -0700 Subject: [PATCH] Fix up non-NUMA breakage in mmzone.h If CONFIG_NUMA isn't set, we use the define in for early_pfn_to_nid (which defines it to 0). Because of this, the prototype needs to move inside the CONFIG_NUMA too, or anal gcc's get really confused. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/mmzone.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h index 08e3cfd86328..516421300ea2 100644 --- a/include/asm-i386/mmzone.h +++ b/include/asm-i386/mmzone.h @@ -37,6 +37,8 @@ static inline void get_memcfg_numa(void) get_memcfg_numa_flat(); } +extern int early_pfn_to_nid(unsigned long pfn); + #else /* !CONFIG_NUMA */ #define get_memcfg_numa get_memcfg_numa_flat #define get_zholes_size(n) (0) @@ -149,6 +151,4 @@ static inline int pfn_valid(int pfn) #endif /* CONFIG_NEED_MULTIPLE_NODES */ -extern int early_pfn_to_nid(unsigned long pfn); - #endif /* _ASM_MMZONE_H_ */ -- cgit v1.3-14-g43fede From e00d9967e3addea86dded46deefc5daec5d52e5a Mon Sep 17 00:00:00 2001 From: Bernard Blackham Date: Thu, 7 Jul 2005 17:56:42 -0700 Subject: [PATCH] pm: fix u32 vs. pm_message_t confusion in cpufreq Fix u32 vs pm_message_t confusion in cpufreq. Signed-off-by: Bernard Blackham Signed-off-by: Pavel Machek Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/pmac_cpufreq.c | 2 +- drivers/cpufreq/cpufreq.c | 4 ++-- include/linux/cpufreq.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c index 5fdd4f607a40..c0605244edda 100644 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -452,7 +452,7 @@ static u32 __pmac read_gpio(struct device_node *np) return offset; } -static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state) +static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) { /* Ok, this could be made a bit smarter, but let's be robust for now. We * always force a speed change to high speed before sleep, to make sure diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index bf62dfe4976a..7a7859dd0d98 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -869,7 +869,7 @@ EXPORT_SYMBOL(cpufreq_get); * cpufreq_suspend - let the low level driver prepare for suspend */ -static int cpufreq_suspend(struct sys_device * sysdev, u32 state) +static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) { int cpu = sysdev->id; unsigned int ret = 0; @@ -897,7 +897,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, u32 state) } if (cpufreq_driver->suspend) { - ret = cpufreq_driver->suspend(cpu_policy, state); + ret = cpufreq_driver->suspend(cpu_policy, pmsg); if (ret) { printk(KERN_ERR "cpufreq: suspend failed in ->suspend " "step on CPU %u\n", cpu_policy->cpu); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 927daa86c9b3..ff7f80f48df1 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -201,7 +201,7 @@ struct cpufreq_driver { /* optional */ int (*exit) (struct cpufreq_policy *policy); - int (*suspend) (struct cpufreq_policy *policy, u32 state); + int (*suspend) (struct cpufreq_policy *policy, pm_message_t pmsg); int (*resume) (struct cpufreq_policy *policy); struct freq_attr **attr; }; -- cgit v1.3-14-g43fede From d67b569f5f620c0fb95d5212642746b7ba9d29e4 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 7 Jul 2005 17:56:49 -0700 Subject: [PATCH] uml: skas0 - separate kernel address space on stock hosts UML has had two modes of operation - an insecure, slow mode (tt mode) in which the kernel is mapped into every process address space which requires no host kernel modifications, and a secure, faster mode (skas mode) in which the UML kernel is in a separate host address space, which requires a patch to the host kernel. This patch implements something very close to skas mode for hosts which don't support skas - I'm calling this skas0. It provides the security of the skas host patch, and some of the performance gains. The two main things that are provided by the skas patch, /proc/mm and PTRACE_FAULTINFO, are implemented in a way that require no host patch. For the remote address space changing stuff (mmap, munmap, and mprotect), we set aside two pages in the process above its stack, one of which contains a little bit of code which can call mmap et al. To update the address space, the system call information (system call number and arguments) are written to the stub page above the code. The %esp is set to the beginning of the data, the %eip is set the the start of the stub, and it repeatedly pops the information into its registers and makes the system call until it sees a system call number of zero. This is to amortize the cost of the context switch across multiple address space updates. When the updates are done, it SIGSTOPs itself, and the kernel process continues what it was doing. For a PTRACE_FAULTINFO replacement, we set up a SIGSEGV handler in the child, and let it handle segfaults rather than nullifying them. The handler is in the same page as the mmap stub. The second page is used as the stack. The handler reads cr2 and err from the sigcontext, sticks them at the base of the stack in a faultinfo struct, and SIGSTOPs itself. The kernel then reads the faultinfo and handles the fault. A complication on x86_64 is that this involves resetting the registers to the segfault values when the process is inside the kill system call. This breaks on x86_64 because %rcx will contain %rip because you tell SYSRET where to return to by putting the value in %rcx. So, this corrupts $rcx on return from the segfault. To work around this, I added an arch_finish_segv, which on x86 does nothing, but which on x86_64 ptraces the child back through the sigreturn. This causes %rcx to be restored by sigreturn and avoids the corruption. Ultimately, I think I will replace this with the trick of having it send itself a blocked signal which will be unblocked by the sigreturn. This will allow it to be stopped just after the sigreturn, and PTRACE_SYSCALLed without all the back-and-forth of PTRACE_SYSCALLing it through sigreturn. This runs on a stock host, so theoretically (and hopefully), tt mode isn't needed any more. We need to make sure that this is better in every way than tt mode, though. I'm concerned about the speed of address space updates and page fault handling, since they involve extra round-trips to the child. We can amortize the round-trip cost for large address space updates by writing all of the operations to the data page and having the child execute them all at the same time. This will help fork and exec, but not page faults, since they involve only one page. I can't think of any way to help page faults, except to add something like PTRACE_FAULTINFO to the host. There is PTRACE_SIGINFO, but UML doesn't use siginfo for SIGSEGV (or anything else) because there isn't enough information in the siginfo struct to handle page faults (the faulting operation type is missing). Adding that would make PTRACE_SIGINFO a usable equivalent to PTRACE_FAULTINFO. As for the code itself: - The system call stub is in arch/um/kernel/sys-$(SUBARCH)/stub.S. It is put in its own section of the binary along with stub_segv_handler in arch/um/kernel/skas/process.c. This is manipulated with run_syscall_stub in arch/um/kernel/skas/mem_user.c. syscall_stub will execute any system call at all, but it's only used for mmap, munmap, and mprotect. - The x86_64 stub calls sigreturn by hand rather than allowing the normal sigreturn to happen, because the normal sigreturn is a SA_RESTORER in UML's address space provided by libc. Needless to say, this is not available in the child's address space. Also, it does a couple of odd pops before that which restore the stack to the state it was in at the time the signal handler was called. - There is a new field in the arch mmu_context, which is now a union. This is the pid to be manipulated rather than the /proc/mm file descriptor. Code which deals with this now checks proc_mm to see whether it should use the usual skas code or the new code. - userspace_tramp is now used to create a new host process for every UML process, rather than one per UML processor. It checks proc_mm and ptrace_faultinfo to decide whether to map in the pages above its stack. - start_userspace now makes CLONE_VM conditional on proc_mm since we need separate address spaces now. - switch_mm_skas now just sets userspace_pid[0] to the new pid rather than PTRACE_SWITCH_MM. There is an addition to userspace which updates its idea of the pid being manipulated each time around the loop. This is important on exec, when the pid will change underneath userspace(). - The stub page has a pte, but it can't be mapped in using tlb_flush because it is part of tlb_flush. This is why it's required for it to be mapped in by userspace_tramp. Other random things: - The stub section in uml.lds.S is page aligned. This page is written out to the backing vm file in setup_physmem because it is mapped from there into user processes. - There's some confusion with TASK_SIZE now that there are a couple of extra pages that the process can't use. TASK_SIZE is considered by the elf code to be the usable process memory, which is reasonable, so it is decreased by two pages. This confuses the definition of USER_PGDS_IN_LAST_PML4, making it too small because of the rounding down of the uneven division. So we round it to the nearest PGDIR_SIZE rather than the lower one. - I added a missing PT_SYSCALL_ARG6_OFFSET macro. - um_mmu.h was made into a userspace-usable file. - proc_mm and ptrace_faultinfo are globals which say whether the host supports these features. - There is a bad interaction between the mm.nr_ptes check at the end of exit_mmap, stack randomization, and skas0. exit_mmap will stop freeing pages at the PGDIR_SIZE boundary after the last vma. If the stack isn't on the last page table page, the last pte page won't be freed, as it should be since the stub ptes are there, and exit_mmap will BUG because there is an unfreed page. To get around this, TASK_SIZE is set to the next lowest PGDIR_SIZE boundary and mm->nr_ptes is decremented after the calls to init_stub_pte. This ensures that we know the process stack (and all other process mappings) will be below the top page table page, and thus we know that mm->nr_ptes will be one too many, and can be decremented. Things that need fixing: - We may need better assurrences that the stub code is PIC. - The stub pte is set up in init_new_context_skas. - alloc_pgdir is probably the right place. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig_i386 | 12 ++ arch/um/Kconfig_x86_64 | 12 ++ arch/um/Makefile-i386 | 2 +- arch/um/Makefile-x86_64 | 2 +- arch/um/defconfig | 58 ++++++- arch/um/include/mem.h | 1 + arch/um/include/registers.h | 1 + arch/um/include/sysdep-i386/ptrace_user.h | 13 ++ arch/um/include/sysdep-i386/stub.h | 18 +++ arch/um/include/sysdep-x86_64/ptrace_user.h | 14 ++ arch/um/include/sysdep-x86_64/stub.h | 19 +++ arch/um/include/tlb.h | 30 ++-- arch/um/kernel/dyn.lds.S | 6 + arch/um/kernel/physmem.c | 8 + arch/um/kernel/process.c | 28 ++-- arch/um/kernel/skas/exec_kern.c | 2 +- arch/um/kernel/skas/include/mm_id.h | 17 +++ arch/um/kernel/skas/include/mmu-skas.h | 7 +- arch/um/kernel/skas/include/skas.h | 15 +- arch/um/kernel/skas/mem.c | 6 +- arch/um/kernel/skas/mem_user.c | 225 ++++++++++++++++++---------- arch/um/kernel/skas/mmu.c | 136 ++++++++++++++--- arch/um/kernel/skas/process.c | 153 +++++++++++++++---- arch/um/kernel/skas/process_kern.c | 33 +++- arch/um/kernel/skas/tlb.c | 28 ++-- arch/um/kernel/tlb.c | 132 ++++++++-------- arch/um/kernel/tt/tlb.c | 4 +- arch/um/kernel/uml.lds.S | 7 + arch/um/os-Linux/sys-i386/registers.c | 5 + arch/um/os-Linux/sys-x86_64/registers.c | 5 + arch/um/scripts/Makefile.rules | 5 + arch/um/sys-i386/Makefile | 12 +- arch/um/sys-i386/stub.S | 8 + arch/um/sys-i386/stub_segv.c | 30 ++++ arch/um/sys-x86_64/Makefile | 12 +- arch/um/sys-x86_64/stub.S | 15 ++ arch/um/sys-x86_64/stub_segv.c | 31 ++++ include/asm-um/mmu_context.h | 6 +- 38 files changed, 853 insertions(+), 265 deletions(-) create mode 100644 arch/um/include/sysdep-i386/stub.h create mode 100644 arch/um/include/sysdep-x86_64/stub.h create mode 100644 arch/um/kernel/skas/include/mm_id.h create mode 100644 arch/um/sys-i386/stub.S create mode 100644 arch/um/sys-i386/stub_segv.c create mode 100644 arch/um/sys-x86_64/stub.S create mode 100644 arch/um/sys-x86_64/stub_segv.c (limited to 'include') diff --git a/arch/um/Kconfig_i386 b/arch/um/Kconfig_i386 index e41f3748d30f..27c18a8d9d17 100644 --- a/arch/um/Kconfig_i386 +++ b/arch/um/Kconfig_i386 @@ -19,6 +19,18 @@ config 3_LEVEL_PGTABLES memory. All the memory that can't be mapped directly will be treated as high memory. +config STUB_CODE + hex + default 0xbfffe000 + +config STUB_DATA + hex + default 0xbffff000 + +config STUB_START + hex + default STUB_CODE + config ARCH_HAS_SC_SIGNALS bool default y diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64 index f162f50f0b17..735a047c890c 100644 --- a/arch/um/Kconfig_x86_64 +++ b/arch/um/Kconfig_x86_64 @@ -14,6 +14,18 @@ config 3_LEVEL_PGTABLES bool default y +config STUB_CODE + hex + default 0x7fbfffe000 + +config STUB_DATA + hex + default 0x7fbffff000 + +config STUB_START + hex + default STUB_CODE + config ARCH_HAS_SC_SIGNALS bool default n diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 29e182d5a83a..301059062a3e 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -8,7 +8,7 @@ ifeq ($(CONFIG_MODE_SKAS),y) endif endif -CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) +CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) $(STUB_CFLAGS) ARCH_USER_CFLAGS := ifneq ($(CONFIG_GPROF),y) diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index 32144562c279..d80bd0052e6b 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -4,7 +4,7 @@ SUBARCH_LIBS := arch/um/sys-x86_64/ START := 0x60000000 -CFLAGS += -U__$(SUBARCH)__ -fno-builtin +CFLAGS += -U__$(SUBARCH)__ -fno-builtin $(STUB_CFLAGS) ARCH_USER_CFLAGS := -D__x86_64__ ELF_ARCH := i386:x86-64 diff --git a/arch/um/defconfig b/arch/um/defconfig index 4067c3aa5b60..80d30d19d750 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc3-skas3-v9-pre2 -# Sun Apr 24 19:46:10 2005 +# Linux kernel version: 2.6.12-rc6-mm1 +# Tue Jun 14 18:22:21 2005 # CONFIG_GENERIC_HARDIRQS=y CONFIG_UML=y @@ -13,23 +13,32 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y # # UML-specific options # -CONFIG_MODE_TT=y +# CONFIG_MODE_TT is not set +# CONFIG_STATIC_LINK is not set CONFIG_MODE_SKAS=y CONFIG_UML_X86=y # CONFIG_64BIT is not set CONFIG_TOP_ADDR=0xc0000000 # CONFIG_3_LEVEL_PGTABLES is not set +CONFIG_STUB_CODE=0xbfffe000 +CONFIG_STUB_DATA=0xbffff000 +CONFIG_STUB_START=0xbfffe000 CONFIG_ARCH_HAS_SC_SIGNALS=y CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y -CONFIG_LD_SCRIPT_STATIC=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_LD_SCRIPT_DYN=y CONFIG_NET=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m -CONFIG_HOSTFS=y +# CONFIG_HOSTFS is not set CONFIG_MCONSOLE=y # CONFIG_MAGIC_SYSRQ is not set # CONFIG_HOST_2G_2G is not set -# CONFIG_SMP is not set CONFIG_NEST_LEVEL=0 CONFIG_KERNEL_HALF_GIGS=1 # CONFIG_HIGHMEM is not set @@ -63,6 +72,8 @@ CONFIG_IKCONFIG_PROC=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_PRINTK=y +CONFIG_BUG=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -81,6 +92,7 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y @@ -115,6 +127,7 @@ CONFIG_UML_SOUND=m CONFIG_SOUND=m CONFIG_HOSTAUDIO=m CONFIG_UML_RANDOM=y +# CONFIG_MMAPPER is not set # # Block devices @@ -176,6 +189,17 @@ CONFIG_INET=y # CONFIG_INET_TUNNEL is not set CONFIG_IP_TCPDIAG=y # CONFIG_IP_TCPDIAG_IPV6 is not set + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_SCALABLE is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -206,11 +230,15 @@ CONFIG_IP_TCPDIAG=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_KGDBOE is not set # CONFIG_NETPOLL is not set +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -227,6 +255,7 @@ CONFIG_PPP=m # CONFIG_PPP_SYNC_TTY is not set # CONFIG_PPP_DEFLATE is not set # CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_MPPE is not set # CONFIG_PPPOE is not set CONFIG_SLIP=m # CONFIG_SLIP_COMPRESSED is not set @@ -240,10 +269,12 @@ CONFIG_SLIP=m # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set +# CONFIG_REISER4_FS is not set CONFIG_REISERFS_FS=y # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set @@ -256,6 +287,7 @@ CONFIG_REISERFS_FS=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set # CONFIG_QFMT_V2 is not set @@ -264,6 +296,12 @@ CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m +# +# Caches +# +# CONFIG_FSCACHE is not set +# CONFIG_FUSE_FS is not set + # # CD-ROM/DVD Filesystems # @@ -291,6 +329,8 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -319,6 +359,7 @@ CONFIG_RAMFS=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -404,14 +445,15 @@ CONFIG_CRC32=m # CONFIG_PRINTK_TIME is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_SLAB=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y -CONFIG_PT_PROXY=y +# CONFIG_GPROF is not set # CONFIG_GCOV is not set # CONFIG_SYSCALL_DEBUG is not set diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h index 10c46c38949a..99d3ad4a03e5 100644 --- a/arch/um/include/mem.h +++ b/arch/um/include/mem.h @@ -13,6 +13,7 @@ extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); extern int is_remapped(void *virt); extern int physmem_remove_mapping(void *virt); extern void physmem_forget_descriptor(int fd); +extern unsigned long to_phys(void *virt); #endif diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index 8744abb5224f..0a35e6d0baa0 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h @@ -14,6 +14,7 @@ extern int restore_fp_registers(int pid, unsigned long *fp_regs); extern void save_registers(int pid, union uml_pt_regs *regs); extern void restore_registers(int pid, union uml_pt_regs *regs); extern void init_registers(int pid); +extern void get_safe_registers(unsigned long * regs); #endif diff --git a/arch/um/include/sysdep-i386/ptrace_user.h b/arch/um/include/sysdep-i386/ptrace_user.h index eca8066e7a43..899aa4b2a78d 100644 --- a/arch/um/include/sysdep-i386/ptrace_user.h +++ b/arch/um/include/sysdep-i386/ptrace_user.h @@ -20,11 +20,24 @@ #define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX) #define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI) #define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI) +#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP) #define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX) +#define REGS_SYSCALL_NR EAX /* This is used before a system call */ +#define REGS_SYSCALL_ARG1 EBX +#define REGS_SYSCALL_ARG2 ECX +#define REGS_SYSCALL_ARG3 EDX +#define REGS_SYSCALL_ARG4 ESI +#define REGS_SYSCALL_ARG5 EDI +#define REGS_SYSCALL_ARG6 EBP + +#define REGS_IP_INDEX EIP +#define REGS_SP_INDEX UESP + #define PT_IP_OFFSET PT_OFFSET(EIP) #define PT_IP(regs) ((regs)[EIP]) +#define PT_SP_OFFSET PT_OFFSET(UESP) #define PT_SP(regs) ((regs)[UESP]) #ifndef FRAME_SIZE diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h new file mode 100644 index 000000000000..fed9ff1cea52 --- /dev/null +++ b/arch/um/include/sysdep-i386/stub.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#ifndef __SYSDEP_STUB_H +#define __SYSDEP_STUB_H + +#include +#include + +extern void stub_segv_handler(int sig); + +#define STUB_SYSCALL_RET EAX +#define STUB_MMAP_NR __NR_mmap2 +#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) + +#endif diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h index 31729973fb14..128faf027364 100644 --- a/arch/um/include/sysdep-x86_64/ptrace_user.h +++ b/arch/um/include/sysdep-x86_64/ptrace_user.h @@ -55,6 +55,20 @@ #define PTRACE_OLDSETOPTIONS 21 #endif +/* These are before the system call, so the the system call number is RAX + * rather than ORIG_RAX, and arg4 is R10 rather than RCX + */ +#define REGS_SYSCALL_NR PT_INDEX(RAX) +#define REGS_SYSCALL_ARG1 PT_INDEX(RDI) +#define REGS_SYSCALL_ARG2 PT_INDEX(RSI) +#define REGS_SYSCALL_ARG3 PT_INDEX(RDX) +#define REGS_SYSCALL_ARG4 PT_INDEX(R10) +#define REGS_SYSCALL_ARG5 PT_INDEX(R8) +#define REGS_SYSCALL_ARG6 PT_INDEX(R9) + +#define REGS_IP_INDEX PT_INDEX(RIP) +#define REGS_SP_INDEX PT_INDEX(RSP) + #endif /* diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h new file mode 100644 index 000000000000..6b5447ad590d --- /dev/null +++ b/arch/um/include/sysdep-x86_64/stub.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#ifndef __SYSDEP_STUB_H +#define __SYSDEP_STUB_H + +#include +#include +#include + +extern void stub_segv_handler(int sig); + +#define STUB_SYSCALL_RET PT_INDEX(RAX) +#define STUB_MMAP_NR __NR_mmap +#define MMAP_OFFSET(o) (o) + +#endif diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h index da1097285b8c..c6f9628f39bf 100644 --- a/arch/um/include/tlb.h +++ b/arch/um/include/tlb.h @@ -37,31 +37,25 @@ struct host_vm_op { extern void mprotect_kernel_vm(int w); extern void force_flush_all(void); extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr, - unsigned long end_addr, int force, int data, - void (*do_ops)(int, struct host_vm_op *, int)); + unsigned long end_addr, int force, + void (*do_ops)(union mm_context *, + struct host_vm_op *, int)); extern int flush_tlb_kernel_range_common(unsigned long start, unsigned long end); extern int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, int r, int w, int x, struct host_vm_op *ops, int index, - int last_filled, int data, - void (*do_ops)(int, struct host_vm_op *, int)); + int last_filled, union mm_context *mmu, + void (*do_ops)(union mm_context *, struct host_vm_op *, + int)); extern int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops, int index, int last_filled, - int data, void (*do_ops)(int, struct host_vm_op *, int)); + union mm_context *mmu, + void (*do_ops)(union mm_context *, struct host_vm_op *, + int)); extern int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x, struct host_vm_op *ops, int index, - int last_filled, int data, - void (*do_ops)(int, struct host_vm_op *, int)); + int last_filled, union mm_context *mmu, + void (*do_ops)(union mm_context *, struct host_vm_op *, + int)); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 715b0838a68c..3942a5f245de 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -67,6 +67,12 @@ SECTIONS *(.stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) + + . = ALIGN(4096); + __syscall_stub_start = .; + *(.__syscall_stub*) + __syscall_stub_end = .; + . = ALIGN(4096); } =0x90909090 .fini : { KEEP (*(.fini)) diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 420e6d51fa0f..a24e3b7f4bf0 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -353,6 +353,8 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +extern int __syscall_stub_start, __binary_start; + void setup_physmem(unsigned long start, unsigned long reserve_end, unsigned long len, unsigned long highmem) { @@ -371,6 +373,12 @@ void setup_physmem(unsigned long start, unsigned long reserve_end, exit(1); } + /* Special kludge - This page will be mapped in to userspace processes + * from physmem_fd, so it needs to be written out there. + */ + os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); + os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE); + bootmap_size = init_bootmem(pfn, pfn + delta); free_bootmem(__pa(reserve_end) + bootmap_size, len - bootmap_size - reserve); diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 1b5ef3e96c71..c45a60e9c92d 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -32,6 +32,7 @@ #include "uml-config.h" #include "choose-mode.h" #include "mode.h" +#include "tempfile.h" #ifdef UML_CONFIG_MODE_SKAS #include "skas.h" #include "skas_ptrace.h" @@ -358,11 +359,16 @@ void forward_pending_sigio(int target) kill(target, SIGIO); } +int ptrace_faultinfo = 0; +int proc_mm = 1; + +extern void *__syscall_stub_start, __syscall_stub_end; + #ifdef UML_CONFIG_MODE_SKAS -static inline int check_skas3_ptrace_support(void) +static inline void check_skas3_ptrace_support(void) { struct ptrace_faultinfo fi; - int pid, n, ret = 1; + int pid, n; printf("Checking for the skas3 patch in the host..."); pid = start_ptraced_child(); @@ -374,33 +380,31 @@ static inline int check_skas3_ptrace_support(void) else { perror("not found"); } - ret = 0; - } else { + } + else { + ptrace_faultinfo = 1; printf("found\n"); } init_registers(pid); stop_ptraced_child(pid, 1, 1); - - return(ret); } int can_do_skas(void) { - int ret = 1; - printf("Checking for /proc/mm..."); if (os_access("/proc/mm", OS_ACC_W_OK) < 0) { + proc_mm = 0; printf("not found\n"); - ret = 0; goto out; - } else { + } + else { printf("found\n"); } - ret = check_skas3_ptrace_support(); out: - return ret; + check_skas3_ptrace_support(); + return 1; } #else int can_do_skas(void) diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c index c6b4d5dba789..77ed7bbab219 100644 --- a/arch/um/kernel/skas/exec_kern.c +++ b/arch/um/kernel/skas/exec_kern.c @@ -18,7 +18,7 @@ void flush_thread_skas(void) { force_flush_all(); - switch_mm_skas(current->mm->context.skas.mm_fd); + switch_mm_skas(¤t->mm->context.skas.id); } void start_thread_skas(struct pt_regs *regs, unsigned long eip, diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/kernel/skas/include/mm_id.h new file mode 100644 index 000000000000..48dd0989ddaa --- /dev/null +++ b/arch/um/kernel/skas/include/mm_id.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2005 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MM_ID_H +#define __MM_ID_H + +struct mm_id { + union { + int mm_fd; + int pid; + } u; + unsigned long stack; +}; + +#endif diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h index 4cd60d7213f3..278b72f1d9ad 100644 --- a/arch/um/kernel/skas/include/mmu-skas.h +++ b/arch/um/kernel/skas/include/mmu-skas.h @@ -6,10 +6,15 @@ #ifndef __SKAS_MMU_H #define __SKAS_MMU_H +#include "mm_id.h" + struct mmu_context_skas { - int mm_fd; + struct mm_id id; + unsigned long last_page_table; }; +extern void switch_mm_skas(struct mm_id * mm_idp); + #endif /* diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h index 96b51dba3471..d91a60f3830a 100644 --- a/arch/um/kernel/skas/include/skas.h +++ b/arch/um/kernel/skas/include/skas.h @@ -6,9 +6,11 @@ #ifndef __SKAS_H #define __SKAS_H +#include "mm_id.h" #include "sysdep/ptrace.h" extern int userspace_pid[]; +extern int proc_mm, ptrace_faultinfo; extern void switch_threads(void *me, void *next); extern void thread_wait(void *sw, void *fb); @@ -22,16 +24,17 @@ extern void new_thread_proc(void *stack, void (*handler)(int sig)); extern void remove_sigstack(void); extern void new_thread_handler(int sig); extern void handle_syscall(union uml_pt_regs *regs); -extern void map(int fd, unsigned long virt, unsigned long len, int r, int w, - int x, int phys_fd, unsigned long long offset); -extern int unmap(int fd, void *addr, unsigned long len); -extern int protect(int fd, unsigned long addr, unsigned long len, - int r, int w, int x); +extern int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, + int r, int w, int x, int phys_fd, unsigned long long offset); +extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len); +extern int protect(struct mm_id * mm_idp, unsigned long addr, + unsigned long len, int r, int w, int x); extern void user_signal(int sig, union uml_pt_regs *regs, int pid); extern int new_mm(int from); -extern void start_userspace(int cpu); +extern int start_userspace(unsigned long stub_stack); extern void get_skas_faultinfo(int pid, struct faultinfo * fi); extern long execute_syscall_skas(void *r); +extern unsigned long current_stub_stack(void); #endif diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c index 438db2f43456..147466d7ff4f 100644 --- a/arch/um/kernel/skas/mem.c +++ b/arch/um/kernel/skas/mem.c @@ -5,7 +5,9 @@ #include "linux/config.h" #include "linux/mm.h" +#include "asm/pgtable.h" #include "mem_user.h" +#include "skas.h" unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, unsigned long *task_size_out) @@ -18,7 +20,9 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, *task_size_out = CONFIG_HOST_TASK_SIZE; #else *host_size_out = top; - *task_size_out = top; + if (proc_mm && ptrace_faultinfo) + *task_size_out = top; + else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; #endif return(((unsigned long) set_task_sizes_skas) & ~0xffffff); } diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c index 1310bf1e88d1..b0980ff3bd95 100644 --- a/arch/um/kernel/skas/mem_user.c +++ b/arch/um/kernel/skas/mem_user.c @@ -3,100 +3,171 @@ * Licensed under the GPL */ +#include #include #include +#include +#include +#include #include "mem_user.h" #include "mem.h" +#include "mm_id.h" #include "user.h" #include "os.h" #include "proc_mm.h" - -void map(int fd, unsigned long virt, unsigned long len, int r, int w, - int x, int phys_fd, unsigned long long offset) +#include "ptrace_user.h" +#include "user_util.h" +#include "kern_util.h" +#include "task.h" +#include "registers.h" +#include "uml-config.h" +#include "sysdep/ptrace.h" +#include "sysdep/stub.h" +#include "skas.h" + +extern unsigned long syscall_stub, __syscall_stub_start; + +extern void wait_stub_done(int pid, int sig, char * fname); + +static long run_syscall_stub(struct mm_id * mm_idp, int syscall, + unsigned long *args) { - struct proc_mm_op map; - int prot, n; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - - map = ((struct proc_mm_op) { .op = MM_MMAP, - .u = - { .mmap = - { .addr = virt, - .len = len, - .prot = prot, - .flags = MAP_SHARED | - MAP_FIXED, - .fd = phys_fd, - .offset = offset - } } } ); - n = os_write_file(fd, &map, sizeof(map)); - if(n != sizeof(map)) - printk("map : /proc/mm map failed, err = %d\n", -n); + int n, pid = mm_idp->u.pid; + unsigned long regs[MAX_REG_NR]; + + get_safe_registers(regs); + regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + + ((unsigned long) &syscall_stub - + (unsigned long) &__syscall_stub_start); + /* XXX Don't have a define for starting a syscall */ + regs[REGS_SYSCALL_NR] = syscall; + regs[REGS_SYSCALL_ARG1] = args[0]; + regs[REGS_SYSCALL_ARG2] = args[1]; + regs[REGS_SYSCALL_ARG3] = args[2]; + regs[REGS_SYSCALL_ARG4] = args[3]; + regs[REGS_SYSCALL_ARG5] = args[4]; + regs[REGS_SYSCALL_ARG6] = args[5]; + n = ptrace_setregs(pid, regs); + if(n < 0){ + printk("run_syscall_stub : PTRACE_SETREGS failed, " + "errno = %d\n", n); + return(n); + } + + wait_stub_done(pid, 0, "run_syscall_stub"); + + return(*((unsigned long *) mm_idp->stack)); } -int unmap(int fd, void *addr, unsigned long len) +int map(struct mm_id *mm_idp, unsigned long virt, unsigned long len, + int r, int w, int x, int phys_fd, unsigned long long offset) { - struct proc_mm_op unmap; - int n; - - unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, - .u = - { .munmap = - { .addr = (unsigned long) addr, - .len = len } } } ); - n = os_write_file(fd, &unmap, sizeof(unmap)); - if(n != sizeof(unmap)) { - if(n < 0) - return(n); - else if(n > 0) - return(-EIO); - } - - return(0); + int prot, n; + + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + (x ? PROT_EXEC : 0); + + if(proc_mm){ + struct proc_mm_op map; + int fd = mm_idp->u.mm_fd; + map = ((struct proc_mm_op) { .op = MM_MMAP, + .u = + { .mmap = + { .addr = virt, + .len = len, + .prot = prot, + .flags = MAP_SHARED | + MAP_FIXED, + .fd = phys_fd, + .offset= offset + } } } ); + n = os_write_file(fd, &map, sizeof(map)); + if(n != sizeof(map)) + printk("map : /proc/mm map failed, err = %d\n", -n); + } + else { + long res; + unsigned long args[] = { virt, len, prot, + MAP_SHARED | MAP_FIXED, phys_fd, + MMAP_OFFSET(offset) }; + + res = run_syscall_stub(mm_idp, STUB_MMAP_NR, args); + if((void *) res == MAP_FAILED) + printk("mmap stub failed, errno = %d\n", res); + } + + return 0; } -int protect(int fd, unsigned long addr, unsigned long len, int r, int w, - int x, int must_succeed) +int unmap(struct mm_id *mm_idp, void *addr, unsigned long len) { - struct proc_mm_op protect; - int prot, n; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - - protect = ((struct proc_mm_op) { .op = MM_MPROTECT, - .u = - { .mprotect = - { .addr = (unsigned long) addr, - .len = len, - .prot = prot } } } ); - - n = os_write_file(fd, &protect, sizeof(protect)); - if(n != sizeof(protect)) { - if(n == 0) return(0); - - if(must_succeed) - panic("protect failed, err = %d", -n); - - return(-EIO); - } + int n; + + if(proc_mm){ + struct proc_mm_op unmap; + int fd = mm_idp->u.mm_fd; + unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, + .u = + { .munmap = + { .addr = + (unsigned long) addr, + .len = len } } } ); + n = os_write_file(fd, &unmap, sizeof(unmap)); + if(n != sizeof(unmap)) { + if(n < 0) + return(n); + else if(n > 0) + return(-EIO); + } + } + else { + int res; + unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, + 0 }; + + res = run_syscall_stub(mm_idp, __NR_munmap, args); + if(res < 0) + printk("munmap stub failed, errno = %d\n", res); + } + + return(0); +} - return(0); +int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len, + int r, int w, int x) +{ + struct proc_mm_op protect; + int prot, n; + + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + (x ? PROT_EXEC : 0); + + if(proc_mm){ + int fd = mm_idp->u.mm_fd; + protect = ((struct proc_mm_op) { .op = MM_MPROTECT, + .u = + { .mprotect = + { .addr = + (unsigned long) addr, + .len = len, + .prot = prot } } } ); + + n = os_write_file(fd, &protect, sizeof(protect)); + if(n != sizeof(protect)) + panic("protect failed, err = %d", -n); + } + else { + int res; + unsigned long args[] = { addr, len, prot, 0, 0, 0 }; + + res = run_syscall_stub(mm_idp, __NR_mprotect, args); + if(res < 0) + panic("mprotect stub failed, errno = %d\n", res); + } + + return(0); } void before_mem_skas(unsigned long unused) { } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 6cb9a6d028a9..511a855c9ec0 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -3,46 +3,138 @@ * Licensed under the GPL */ +#include "linux/config.h" #include "linux/sched.h" #include "linux/list.h" #include "linux/spinlock.h" #include "linux/slab.h" +#include "linux/errno.h" +#include "linux/mm.h" #include "asm/current.h" #include "asm/segment.h" #include "asm/mmu.h" +#include "asm/pgalloc.h" +#include "asm/pgtable.h" #include "os.h" #include "skas.h" +extern int __syscall_stub_start; + +static int init_stub_pte(struct mm_struct *mm, unsigned long proc, + unsigned long kernel) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + spin_lock(&mm->page_table_lock); + pgd = pgd_offset(mm, proc); + pud = pud_alloc(mm, pgd, proc); + if (!pud) + goto out; + + pmd = pmd_alloc(mm, pud, proc); + if (!pmd) + goto out_pmd; + + pte = pte_alloc_map(mm, pmd, proc); + if (!pte) + goto out_pte; + + /* There's an interaction between the skas0 stub pages, stack + * randomization, and the BUG at the end of exit_mmap. exit_mmap + * checks that the number of page tables freed is the same as had + * been allocated. If the stack is on the last page table page, + * then the stack pte page will be freed, and if not, it won't. To + * avoid having to know where the stack is, or if the process mapped + * something at the top of its address space for some other reason, + * we set TASK_SIZE to end at the start of the last page table. + * This keeps exit_mmap off the last page, but introduces a leak + * of that page. So, we hang onto it here and free it in + * destroy_context_skas. + */ + + mm->context.skas.last_page_table = pmd_page_kernel(*pmd); + + *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); + *pte = pte_mkexec(*pte); + *pte = pte_wrprotect(*pte); + spin_unlock(&mm->page_table_lock); + return(0); + + out_pmd: + pud_free(pud); + out_pte: + pmd_free(pmd); + out: + spin_unlock(&mm->page_table_lock); + return(-ENOMEM); +} + int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) { - int from; + struct mm_struct *cur_mm = current->mm; + struct mm_id *mm_id = &mm->context.skas.id; + unsigned long stack; + int from, ret; - if((current->mm != NULL) && (current->mm != &init_mm)) - from = current->mm->context.skas.mm_fd; - else from = -1; + if(proc_mm){ + if((cur_mm != NULL) && (cur_mm != &init_mm)) + from = cur_mm->context.skas.id.u.mm_fd; + else from = -1; - mm->context.skas.mm_fd = new_mm(from); - if(mm->context.skas.mm_fd < 0){ - printk("init_new_context_skas - new_mm failed, errno = %d\n", - mm->context.skas.mm_fd); - return(mm->context.skas.mm_fd); + ret = new_mm(from); + if(ret < 0){ + printk("init_new_context_skas - new_mm failed, " + "errno = %d\n", ret); + return ret; + } + mm_id->u.mm_fd = ret; } + else { + /* This zeros the entry that pgd_alloc didn't, needed since + * we are about to reinitialize it, and want mm.nr_ptes to + * be accurate. + */ + mm->pgd[USER_PTRS_PER_PGD] = __pgd(0); - return(0); + ret = init_stub_pte(mm, CONFIG_STUB_CODE, + (unsigned long) &__syscall_stub_start); + if(ret) + goto out; + + ret = -ENOMEM; + stack = get_zeroed_page(GFP_KERNEL); + if(stack == 0) + goto out; + mm_id->stack = stack; + + ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack); + if(ret) + goto out_free; + + mm->nr_ptes--; + mm_id->u.pid = start_userspace(stack); + } + + return 0; + + out_free: + free_page(mm_id->stack); + out: + return ret; } void destroy_context_skas(struct mm_struct *mm) { - os_close_file(mm->context.skas.mm_fd); -} + struct mmu_context_skas *mmu = &mm->context.skas; -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ + if(proc_mm) + os_close_file(mmu->id.u.mm_fd); + else { + os_kill_ptraced_process(mmu->id.u.pid, 1); + free_page(mmu->id.stack); + free_page(mmu->last_page_table); + } +} diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 773cd2b525fc..1647abb0d1aa 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -14,6 +14,7 @@ #include #include #include +#include #include "user.h" #include "ptrace_user.h" #include "time_user.h" @@ -21,13 +22,17 @@ #include "user_util.h" #include "kern_util.h" #include "skas.h" +#include "mm_id.h" #include "sysdep/sigcontext.h" +#include "sysdep/stub.h" #include "os.h" #include "proc_mm.h" #include "skas_ptrace.h" #include "chan_user.h" #include "signal_user.h" #include "registers.h" +#include "mem.h" +#include "uml-config.h" #include "process.h" int is_skas_winch(int pid, int fd, void *data) @@ -39,20 +44,55 @@ int is_skas_winch(int pid, int fd, void *data) return(1); } -void get_skas_faultinfo(int pid, struct faultinfo * fi) +void wait_stub_done(int pid, int sig, char * fname) { - int err; - - err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); - if(err) - panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " - "errno = %d\n", errno); + int n, status, err; + + do { + if ( sig != -1 ) { + err = ptrace(PTRACE_CONT, pid, 0, sig); + if(err) + panic("%s : continue failed, errno = %d\n", + fname, errno); + } + sig = 0; + + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); + } while((n >= 0) && WIFSTOPPED(status) && + (WSTOPSIG(status) == SIGVTALRM)); + + if((n < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status != SIGTRAP))){ + panic("%s : failed to wait for SIGUSR1/SIGTRAP, " + "pid = %d, n = %d, errno = %d, status = 0x%x\n", + fname, pid, n, errno, status); + } +} - /* Special handling for i386, which has different structs */ - if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) - memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, - sizeof(struct faultinfo) - - sizeof(struct ptrace_faultinfo)); +void get_skas_faultinfo(int pid, struct faultinfo * fi) +{ + int err; + + if(ptrace_faultinfo){ + err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); + if(err) + panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " + "errno = %d\n", errno); + + /* Special handling for i386, which has different structs */ + if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) + memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, + sizeof(struct faultinfo) - + sizeof(struct ptrace_faultinfo)); + } + else { + wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); + + /* faultinfo is prepared by the stub-segv-handler at start of + * the stub stack page. We just have to copy it. + */ + memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); + } } static void handle_segv(int pid, union uml_pt_regs * regs) @@ -91,11 +131,56 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu handle_syscall(regs); } -static int userspace_tramp(void *arg) +extern int __syscall_stub_start; + +static int userspace_tramp(void *stack) { - init_new_thread_signals(0); - enable_timer(); + void *addr; + ptrace(PTRACE_TRACEME, 0, 0, 0); + + init_new_thread_signals(1); + enable_timer(); + + if(!proc_mm){ + /* This has a pte, but it can't be mapped in with the usual + * tlb_flush mechanism because this is part of that mechanism + */ + int fd; + __u64 offset; + + fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); + addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), + PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); + if(addr == MAP_FAILED){ + printk("mapping mmap stub failed, errno = %d\n", + errno); + exit(1); + } + + if(stack != NULL){ + fd = phys_mapping(to_phys(stack), &offset); + addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd, offset); + if(addr == MAP_FAILED){ + printk("mapping segfault stack failed, " + "errno = %d\n", errno); + exit(1); + } + } + } + if(!ptrace_faultinfo && (stack != NULL)){ + unsigned long v = UML_CONFIG_STUB_CODE + + (unsigned long) stub_segv_handler - + (unsigned long) &__syscall_stub_start; + + set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); + set_handler(SIGSEGV, (void *) v, SA_ONSTACK, + SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, + SIGUSR1, -1); + } + os_stop_process(os_getpid()); return(0); } @@ -105,11 +190,11 @@ static int userspace_tramp(void *arg) #define NR_CPUS 1 int userspace_pid[NR_CPUS]; -void start_userspace(int cpu) +int start_userspace(unsigned long stub_stack) { void *stack; unsigned long sp; - int pid, status, n; + int pid, status, n, flags; stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -117,8 +202,9 @@ void start_userspace(int cpu) panic("start_userspace : mmap failed, errno = %d", errno); sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); - pid = clone(userspace_tramp, (void *) sp, - CLONE_FILES | CLONE_VM | SIGCHLD, NULL); + flags = CLONE_FILES | SIGCHLD; + if(proc_mm) flags |= CLONE_VM; + pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); if(pid < 0) panic("start_userspace : clone failed, errno = %d", errno); @@ -140,7 +226,7 @@ void start_userspace(int cpu) if(munmap(stack, PAGE_SIZE) < 0) panic("start_userspace : munmap failed, errno = %d\n", errno); - userspace_pid[cpu] = pid; + return(pid); } void userspace(union uml_pt_regs *regs) @@ -174,7 +260,9 @@ void userspace(union uml_pt_regs *regs) if(WIFSTOPPED(status)){ switch(WSTOPSIG(status)){ case SIGSEGV: - handle_segv(pid, regs); + if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) + user_signal(SIGSEGV, regs, pid); + else handle_segv(pid, regs); break; case SIGTRAP + 0x80: handle_trap(pid, regs, local_using_sysemu); @@ -194,6 +282,7 @@ void userspace(union uml_pt_regs *regs) printk("userspace - child stopped with signal " "%d\n", WSTOPSIG(status)); } + pid = userspace_pid[0]; interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ @@ -334,21 +423,19 @@ void reboot_skas(void) siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); } -void switch_mm_skas(int mm_fd) +void switch_mm_skas(struct mm_id *mm_idp) { int err; #warning need cpu pid in switch_mm_skas - err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); - if(err) - panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", - errno); -} - -void kill_off_processes_skas(void) -{ -#warning need to loop over userspace_pids in kill_off_processes_skas - os_kill_ptraced_process(userspace_pid[0], 1); + if(proc_mm){ + err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, + mm_idp->u.mm_fd); + if(err) + panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " + "errno = %d\n", errno); + } + else userspace_pid[0] = mm_idp->u.pid; } /* diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 0a7b8aa55db8..cbabab104ac3 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -175,9 +175,12 @@ static int start_kernel_proc(void *unused) return(0); } +extern int userspace_pid[]; + int start_uml_skas(void) { - start_userspace(0); + if(proc_mm) + userspace_pid[0] = start_userspace(0); init_new_thread_signals(1); @@ -199,3 +202,31 @@ int thread_pid_skas(struct task_struct *task) #warning Need to look up userspace_pid by cpu return(userspace_pid[0]); } + +void kill_off_processes_skas(void) +{ + if(proc_mm) +#warning need to loop over userspace_pids in kill_off_processes_skas + os_kill_ptraced_process(userspace_pid[0], 1); + else { + struct task_struct *p; + int pid, me; + + me = os_getpid(); + for_each_process(p){ + if(p->mm == NULL) + continue; + + pid = p->mm->context.skas.id.u.pid; + os_kill_ptraced_process(pid, 1); + } + } +} + +unsigned long current_stub_stack(void) +{ + if(current->mm == NULL) + return(0); + + return(current->mm->context.skas.id.stack); +} diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 18f9a7711de1..6230999c672c 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c @@ -6,6 +6,7 @@ #include "linux/stddef.h" #include "linux/sched.h" +#include "linux/config.h" #include "linux/mm.h" #include "asm/page.h" #include "asm/pgtable.h" @@ -17,7 +18,7 @@ #include "os.h" #include "tlb.h" -static void do_ops(int fd, struct host_vm_op *ops, int last) +static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last) { struct host_vm_op *op; int i; @@ -26,18 +27,18 @@ static void do_ops(int fd, struct host_vm_op *ops, int last) op = &ops[i]; switch(op->type){ case MMAP: - map(fd, op->u.mmap.addr, op->u.mmap.len, + map(&mmu->skas.id, op->u.mmap.addr, op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, op->u.mmap.x, op->u.mmap.fd, op->u.mmap.offset); break; case MUNMAP: - unmap(fd, (void *) op->u.munmap.addr, + unmap(&mmu->skas.id, (void *) op->u.munmap.addr, op->u.munmap.len); break; case MPROTECT: - protect(fd, op->u.mprotect.addr, op->u.mprotect.len, - op->u.mprotect.r, op->u.mprotect.w, - op->u.mprotect.x); + protect(&mmu->skas.id, op->u.mprotect.addr, + op->u.mprotect.len, op->u.mprotect.r, + op->u.mprotect.w, op->u.mprotect.x); break; default: printk("Unknown op type %d in do_ops\n", op->type); @@ -46,12 +47,15 @@ static void do_ops(int fd, struct host_vm_op *ops, int last) } } +extern int proc_mm; + static void fix_range(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr, int force) { - int fd = mm->context.skas.mm_fd; + if(!proc_mm && (end_addr > CONFIG_STUB_START)) + end_addr = CONFIG_STUB_START; - fix_range_common(mm, start_addr, end_addr, force, fd, do_ops); + fix_range_common(mm, start_addr, end_addr, force, do_ops); } void __flush_tlb_one_skas(unsigned long addr) @@ -69,16 +73,20 @@ void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start, void flush_tlb_mm_skas(struct mm_struct *mm) { + unsigned long end; + /* Don't bother flushing if this address space is about to be * destroyed. */ if(atomic_read(&mm->mm_users) == 0) return; - fix_range(mm, 0, host_task_size, 0); + end = proc_mm ? task_size : CONFIG_STUB_START; + fix_range(mm, 0, end, 0); } void force_flush_all_skas(void) { - fix_range(current->mm, 0, host_task_size, 1); + unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; + fix_range(current->mm, 0, end, 1); } diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index eda477edfdf5..83ec8d4747fd 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -18,13 +18,15 @@ #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) void fix_range_common(struct mm_struct *mm, unsigned long start_addr, - unsigned long end_addr, int force, int data, - void (*do_ops)(int, struct host_vm_op *, int)) + unsigned long end_addr, int force, + void (*do_ops)(union mm_context *, struct host_vm_op *, + int)) { pgd_t *npgd; pud_t *npud; pmd_t *npmd; pte_t *npte; + union mm_context *mmu = &mm->context; unsigned long addr, end; int r, w, x; struct host_vm_op ops[16]; @@ -40,7 +42,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, end = end_addr; if(force || pgd_newpage(*npgd)){ op_index = add_munmap(addr, end - addr, ops, - op_index, last_op, data, + op_index, last_op, mmu, do_ops); pgd_mkuptodate(*npgd); } @@ -55,7 +57,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, end = end_addr; if(force || pud_newpage(*npud)){ op_index = add_munmap(addr, end - addr, ops, - op_index, last_op, data, + op_index, last_op, mmu, do_ops); pud_mkuptodate(*npud); } @@ -70,7 +72,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, end = end_addr; if(force || pmd_newpage(*npmd)){ op_index = add_munmap(addr, end - addr, ops, - op_index, last_op, data, + op_index, last_op, mmu, do_ops); pmd_mkuptodate(*npmd); } @@ -93,21 +95,21 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, op_index = add_mmap(addr, pte_val(*npte) & PAGE_MASK, PAGE_SIZE, r, w, x, ops, - op_index, last_op, data, + op_index, last_op, mmu, do_ops); else op_index = add_munmap(addr, PAGE_SIZE, ops, - op_index, last_op, data, + op_index, last_op, mmu, do_ops); } else if(pte_newprot(*npte)) op_index = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, - op_index, last_op, data, + op_index, last_op, mmu, do_ops); *npte = pte_mkuptodate(*npte); addr += PAGE_SIZE; } - (*do_ops)(data, ops, op_index); + (*do_ops)(mmu, ops, op_index); } int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) @@ -195,51 +197,6 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) return(updated); } -void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) -{ - address &= PAGE_MASK; - flush_tlb_range(vma, address, address + PAGE_SIZE); -} - -void flush_tlb_all(void) -{ - flush_tlb_mm(current->mm); -} - -void flush_tlb_kernel_range(unsigned long start, unsigned long end) -{ - CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, - flush_tlb_kernel_range_common, start, end); -} - -void flush_tlb_kernel_vm(void) -{ - CHOOSE_MODE(flush_tlb_kernel_vm_tt(), - flush_tlb_kernel_range_common(start_vm, end_vm)); -} - -void __flush_tlb_one(unsigned long addr) -{ - CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); -} - -void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, - end); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); -} - -void force_flush_all(void) -{ - CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); -} - pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) { return(pgd_offset(mm, address)); @@ -270,9 +227,9 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr) } int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, - int r, int w, int x, struct host_vm_op *ops, int index, - int last_filled, int data, - void (*do_ops)(int, struct host_vm_op *, int)) + int r, int w, int x, struct host_vm_op *ops, int index, + int last_filled, union mm_context *mmu, + void (*do_ops)(union mm_context *, struct host_vm_op *, int)) { __u64 offset; struct host_vm_op *last; @@ -292,7 +249,7 @@ int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, } if(index == last_filled){ - (*do_ops)(data, ops, last_filled); + (*do_ops)(mmu, ops, last_filled); index = -1; } @@ -310,8 +267,8 @@ int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, } int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops, - int index, int last_filled, int data, - void (*do_ops)(int, struct host_vm_op *, int)) + int index, int last_filled, union mm_context *mmu, + void (*do_ops)(union mm_context *, struct host_vm_op *, int)) { struct host_vm_op *last; @@ -325,7 +282,7 @@ int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops, } if(index == last_filled){ - (*do_ops)(data, ops, last_filled); + (*do_ops)(mmu, ops, last_filled); index = -1; } @@ -337,8 +294,9 @@ int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops, } int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x, - struct host_vm_op *ops, int index, int last_filled, int data, - void (*do_ops)(int, struct host_vm_op *, int)) + struct host_vm_op *ops, int index, int last_filled, + union mm_context *mmu, + void (*do_ops)(union mm_context *, struct host_vm_op *, int)) { struct host_vm_op *last; @@ -354,7 +312,7 @@ int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x, } if(index == last_filled){ - (*do_ops)(data, ops, last_filled); + (*do_ops)(mmu, ops, last_filled); index = -1; } @@ -367,3 +325,49 @@ int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x, .x = x } } }); return(index); } + +void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) +{ + address &= PAGE_MASK; + flush_tlb_range(vma, address, address + PAGE_SIZE); +} + +void flush_tlb_all(void) +{ + flush_tlb_mm(current->mm); +} + +void flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, + flush_tlb_kernel_range_common, start, end); +} + +void flush_tlb_kernel_vm(void) +{ + CHOOSE_MODE(flush_tlb_kernel_vm_tt(), + flush_tlb_kernel_range_common(start_vm, end_vm)); +} + +void __flush_tlb_one(unsigned long addr) +{ + CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); +} + +void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, + end); +} + +void flush_tlb_mm(struct mm_struct *mm) +{ + CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); +} + +void force_flush_all(void) +{ + CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); +} + diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c index 203216ad86f1..2eefb43bc9c2 100644 --- a/arch/um/kernel/tt/tlb.c +++ b/arch/um/kernel/tt/tlb.c @@ -17,7 +17,7 @@ #include "os.h" #include "tlb.h" -static void do_ops(int unused, struct host_vm_op *ops, int last) +static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last) { struct host_vm_op *op; int i; @@ -55,7 +55,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, panic("fix_range fixing wrong address space, current = 0x%p", current); - fix_range_common(mm, start_addr, end_addr, force, 0, do_ops); + fix_range_common(mm, start_addr, end_addr, force, do_ops); } atomic_t vmchange_seq = ATOMIC_INIT(1); diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 61dfd4fef752..163476a8cb1b 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -30,6 +30,7 @@ SECTIONS _einittext = .; } . = ALIGN(4096); + .text : { *(.text) @@ -39,6 +40,12 @@ SECTIONS /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) *(.gnu.linkonce.t*) + + . = ALIGN(4096); + __syscall_stub_start = .; + *(.__syscall_stub*) + __syscall_stub_end = .; + . = ALIGN(4096); } #include "asm/common.lds.S" diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 9a0ad094d926..3125d320722c 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -121,6 +121,11 @@ void init_registers(int pid) err); } +void get_safe_registers(unsigned long *regs) +{ + memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index 6286c974bbeb..44438d15c3d6 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -69,6 +69,11 @@ void init_registers(int pid) err); } +void get_safe_registers(unsigned long *regs) +{ + memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index 7459d09c233e..17f305b6bade 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -16,6 +16,11 @@ define unprofile endef +# The stubs and unmap.o can't try to call mcount or update basic block data +define unprofile + $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) +endef + quiet_cmd_make_link = SYMLINK $@ cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@ diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 095bcdb0b9cc..77c3c4d29f55 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -1,6 +1,6 @@ obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ - ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \ - sys_call_table.o + ptrace_user.o semaphore.o signal.o sigcontext.o stub.o stub_segv.o \ + syscalls.o sysrq.o sys_call_table.o obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_MODULES) += module.o @@ -16,6 +16,14 @@ semaphore.c-dir = kernel highmem.c-dir = mm module.c-dir = kernel +STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) + +# _cflags works with kernel files, not with userspace ones, but c_flags does, +# why ask why? +$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS) + +$(obj)/stub.o : a_flags = $(STUB_CFLAGS) + subdir- := util include arch/um/scripts/Makefile.unmap diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S new file mode 100644 index 000000000000..2f2c70a8f043 --- /dev/null +++ b/arch/um/sys-i386/stub.S @@ -0,0 +1,8 @@ +#include "uml-config.h" + + .globl syscall_stub +.section .__syscall_stub, "x" +syscall_stub: + int $0x80 + mov %eax, UML_CONFIG_STUB_DATA + int3 diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c new file mode 100644 index 000000000000..b251442ad0b1 --- /dev/null +++ b/arch/um/sys-i386/stub_segv.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include "uml-config.h" +#include "sysdep/sigcontext.h" +#include "sysdep/faultinfo.h" + +void __attribute__ ((__section__ (".__syscall_stub"))) +stub_segv_handler(int sig) +{ + struct sigcontext *sc = (struct sigcontext *) (&sig + 1); + + GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), + sc); + + __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid)); + __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;" + "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1)); + /* Pop the frame pointer and return address since we need to leave + * the stack in its original form when we do the sigreturn here, by + * hand. + */ + __asm__("popl %%eax ; popl %%eax ; popl %%eax ; movl %0, %%eax ; " + "int $0x80" : : "g" (__NR_sigreturn)); +} diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index 2bc6f6849010..7488206ce6f4 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -6,8 +6,8 @@ #XXX: why into lib-y? lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \ - ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \ - syscalls.o sysrq.o thunk.o syscall_table.o + ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o stub.o \ + stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o obj-y := ksyms.o obj-$(CONFIG_MODULES) += module.o um_module.o @@ -28,6 +28,14 @@ semaphore.c-dir = kernel thunk.S-dir = lib module.c-dir = kernel +STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) + +# _cflags works with kernel files, not with userspace ones, but c_flags does, +# why ask why? +$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS) + +$(obj)/stub.o : a_flags = $(STUB_CFLAGS) + subdir- := util include arch/um/scripts/Makefile.unmap diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S new file mode 100644 index 000000000000..31c14925716b --- /dev/null +++ b/arch/um/sys-x86_64/stub.S @@ -0,0 +1,15 @@ +#include "uml-config.h" + + .globl syscall_stub +.section .__syscall_stub, "x" +syscall_stub: + syscall + /* We don't have 64-bit constants, so this constructs the address + * we need. + */ + movq $(UML_CONFIG_STUB_DATA >> 32), %rbx + salq $32, %rbx + movq $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx + or %rcx, %rbx + movq %rax, (%rbx) + int3 diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c new file mode 100644 index 000000000000..161d1fe9c034 --- /dev/null +++ b/arch/um/sys-x86_64/stub_segv.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include "uml-config.h" +#include "sysdep/sigcontext.h" +#include "sysdep/faultinfo.h" + +void __attribute__ ((__section__ (".__syscall_stub"))) +stub_segv_handler(int sig) +{ + struct ucontext *uc; + + __asm__("movq %%rdx, %0" : "=g" (uc) :); + GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), + &uc->uc_mcontext); + + __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); + __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" + "syscall": : "g" (__NR_kill), "g" (SIGUSR1)); + /* Two popqs to restore the stack to the state just before entering + * the handler, one pops the return address, the other pops the frame + * pointer. + */ + __asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g" + (__NR_rt_sigreturn)); +} diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h index 89bff310b7a9..7529c9c853dd 100644 --- a/include/asm-um/mmu_context.h +++ b/include/asm-um/mmu_context.h @@ -7,7 +7,9 @@ #define __UM_MMU_CONTEXT_H #include "linux/sched.h" +#include "linux/config.h" #include "choose-mode.h" +#include "um_mmu.h" #define get_mmu_context(task) do ; while(0) #define activate_context(tsk) do ; while(0) @@ -18,8 +20,6 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) { } -extern void switch_mm_skas(int mm_fd); - static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { @@ -30,7 +30,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, cpu_set(cpu, next->cpu_vm_mask); if(next != &init_mm) CHOOSE_MODE((void) 0, - switch_mm_skas(next->context.skas.mm_fd)); + switch_mm_skas(&next->context.skas.id)); } } -- cgit v1.3-14-g43fede From 8759145114f72857bcaeed338db21620a6619b26 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 7 Jul 2005 17:56:53 -0700 Subject: [PATCH] xtensa: remove old syscalls xtensa is now in -rc1, with the obsolete syscalls still in there, so I guess this about the last chance to correct the ABI. Applying the patch obviously breaks all sorts of user space binaries and probably also requires the appropriate changes to be made to libc. On the other hand, if a decision is made to keep the broken interface, it should at least be a conscious one instead of an oversight. Signed-off-by: Arnd Bergmann Cc: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/xtensa/kernel/syscalls.c | 152 +----------------------------------------- arch/xtensa/kernel/syscalls.h | 57 ++++++++-------- include/asm-xtensa/unistd.h | 98 --------------------------- 3 files changed, 30 insertions(+), 277 deletions(-) (limited to 'include') diff --git a/arch/xtensa/kernel/syscalls.c b/arch/xtensa/kernel/syscalls.c index abc8ed6c7026..3540d8b119f3 100644 --- a/arch/xtensa/kernel/syscalls.c +++ b/arch/xtensa/kernel/syscalls.c @@ -46,8 +46,6 @@ extern void do_syscall_trace(void); typedef int (*syscall_t)(void *a0,...); -extern int (*do_syscalls)(struct pt_regs *regs, syscall_t fun, - int narg); extern syscall_t sys_call_table[]; extern unsigned char sys_narg_table[]; @@ -72,10 +70,8 @@ int sys_pipe(int __user *userfds) /* * Common code for old and new mmaps. */ - -static inline long do_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) +long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, unsigned long pgoff) { int error = -EBADF; struct file * file = NULL; @@ -97,29 +93,6 @@ out: return error; } -unsigned long old_mmap(unsigned long addr, size_t len, int prot, - int flags, int fd, off_t offset) -{ - return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); -} - -long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - -int sys_fork(struct pt_regs *regs) -{ - return do_fork(SIGCHLD, regs->areg[1], regs, 0, NULL, NULL); -} - -int sys_vfork(struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK|CLONE_VM|SIGCHLD, regs->areg[1], - regs, 0, NULL, NULL); -} - int sys_clone(struct pt_regs *regs) { unsigned long clone_flags; @@ -162,30 +135,6 @@ int sys_uname(struct old_utsname * name) return -EFAULT; } -int sys_olduname(struct oldold_utsname * name) -{ - int error; - - if (!name) - return -EFAULT; - if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) - return -EFAULT; - - error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); - error -= __put_user(0,name->sysname+__OLD_UTS_LEN); - error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); - error -= __put_user(0,name->nodename+__OLD_UTS_LEN); - error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); - error -= __put_user(0,name->release+__OLD_UTS_LEN); - error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); - error -= __put_user(0,name->version+__OLD_UTS_LEN); - error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); - error -= __put_user(0,name->machine+__OLD_UTS_LEN); - - return error ? -EFAULT : 0; -} - - /* * Build the string table for the builtin "poor man's strace". */ @@ -319,100 +268,3 @@ void system_call (struct pt_regs *regs) regs->areg[2] = res; do_syscall_trace(); } - -/* - * sys_ipc() is the de-multiplexer for the SysV IPC calls.. - * - * This is really horribly ugly. - */ - -int sys_ipc (uint call, int first, int second, - int third, void __user *ptr, long fifth) -{ - int version, ret; - - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; - ret = -ENOSYS; - - switch (call) { - case SEMOP: - ret = sys_semtimedop (first, (struct sembuf __user *)ptr, - second, NULL); - break; - - case SEMTIMEDOP: - ret = sys_semtimedop (first, (struct sembuf __user *)ptr, - second, (const struct timespec *) fifth); - break; - - case SEMGET: - ret = sys_semget (first, second, third); - break; - - case SEMCTL: { - union semun fourth; - - if (ptr && !get_user(fourth.__pad, (void *__user *) ptr)) - ret = sys_semctl (first, second, third, fourth); - break; - } - - case MSGSND: - ret = sys_msgsnd (first, (struct msgbuf __user*) ptr, - second, third); - break; - - case MSGRCV: - switch (version) { - case 0: { - struct ipc_kludge tmp; - - if (ptr && !copy_from_user(&tmp, - (struct ipc_kludge *) ptr, - sizeof (tmp))) - ret = sys_msgrcv (first, tmp.msgp, second, - tmp.msgtyp, third); - break; - } - - default: - ret = sys_msgrcv (first, (struct msgbuf __user *) ptr, - second, 0, third); - break; - } - break; - - case MSGGET: - ret = sys_msgget ((key_t) first, second); - break; - - case MSGCTL: - ret = sys_msgctl (first, second, (struct msqid_ds __user*) ptr); - break; - - case SHMAT: { - ulong raddr; - ret = do_shmat (first, (char __user *) ptr, second, &raddr); - - if (!ret) - ret = put_user (raddr, (ulong __user *) third); - - break; - } - - case SHMDT: - ret = sys_shmdt ((char __user *)ptr); - break; - - case SHMGET: - ret = sys_shmget (first, second, third); - break; - - case SHMCTL: - ret = sys_shmctl (first, second, (struct shmid_ds __user*) ptr); - break; - } - return ret; -} - diff --git a/arch/xtensa/kernel/syscalls.h b/arch/xtensa/kernel/syscalls.h index 5b3f75f50feb..07580696b602 100644 --- a/arch/xtensa/kernel/syscalls.h +++ b/arch/xtensa/kernel/syscalls.h @@ -25,20 +25,19 @@ */ SYSCALL(0, 0) /* 00 */ - SYSCALL(sys_exit, 1) -SYSCALL(sys_fork, 0) +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_read, 3) SYSCALL(sys_write, 3) SYSCALL(sys_open, 3) /* 05 */ SYSCALL(sys_close, 1) -SYSCALL(sys_waitpid, 3) +SYSCALL(sys_ni_syscall, 3) SYSCALL(sys_creat, 2) SYSCALL(sys_link, 2) SYSCALL(sys_unlink, 1) /* 10 */ SYSCALL(sys_execve, 0) SYSCALL(sys_chdir, 1) -SYSCALL(sys_time, 1) +SYSCALL(sys_ni_syscall, 1) SYSCALL(sys_mknod, 3) SYSCALL(sys_chmod, 2) /* 15 */ SYSCALL(sys_lchown, 3) @@ -47,19 +46,19 @@ SYSCALL(sys_stat, 2) SYSCALL(sys_lseek, 3) SYSCALL(sys_getpid, 0) /* 20 */ SYSCALL(sys_mount, 5) -SYSCALL(sys_oldumount, 1) +SYSCALL(sys_ni_syscall, 1) SYSCALL(sys_setuid, 1) SYSCALL(sys_getuid, 0) -SYSCALL(sys_stime, 1) /* 25 */ +SYSCALL(sys_ni_syscall, 1) /* 25 */ SYSCALL(sys_ptrace, 4) -SYSCALL(sys_alarm, 1) +SYSCALL(sys_ni_syscall, 1) SYSCALL(sys_fstat, 2) -SYSCALL(sys_pause, 0) +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_utime, 2) /* 30 */ SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_access, 2) -SYSCALL(sys_nice, 1) +SYSCALL(sys_ni_syscall, 1) SYSCALL(sys_ni_syscall, 0) /* 35 */ SYSCALL(sys_sync, 0) SYSCALL(sys_kill, 2) @@ -73,7 +72,7 @@ SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_brk, 1) /* 45 */ SYSCALL(sys_setgid, 1) SYSCALL(sys_getgid, 0) -SYSCALL(sys_ni_syscall, 0) /* was signal(2) */ +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_geteuid, 0) SYSCALL(sys_getegid, 0) /* 50 */ SYSCALL(sys_acct, 1) @@ -84,21 +83,21 @@ SYSCALL(sys_fcntl, 3) /* 55 */ SYSCALL(sys_ni_syscall, 2) SYSCALL(sys_setpgid, 2) SYSCALL(sys_ni_syscall, 0) -SYSCALL(sys_olduname, 1) +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_umask, 1) /* 60 */ SYSCALL(sys_chroot, 1) SYSCALL(sys_ustat, 2) SYSCALL(sys_dup2, 2) SYSCALL(sys_getppid, 0) -SYSCALL(sys_getpgrp, 0) /* 65 */ +SYSCALL(sys_ni_syscall, 0) /* 65 */ SYSCALL(sys_setsid, 0) SYSCALL(sys_sigaction, 3) -SYSCALL(sys_sgetmask, 0) -SYSCALL(sys_ssetmask, 1) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_ni_syscall, 1) SYSCALL(sys_setreuid, 2) /* 70 */ SYSCALL(sys_setregid, 2) SYSCALL(sys_sigsuspend, 0) -SYSCALL(sys_sigpending, 1) +SYSCALL(sys_ni_syscall, 1) SYSCALL(sys_sethostname, 2) SYSCALL(sys_setrlimit, 2) /* 75 */ SYSCALL(sys_getrlimit, 2) @@ -107,15 +106,15 @@ SYSCALL(sys_gettimeofday, 2) SYSCALL(sys_settimeofday, 2) SYSCALL(sys_getgroups, 2) /* 80 */ SYSCALL(sys_setgroups, 2) -SYSCALL(sys_ni_syscall, 0) /* old_select */ +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_symlink, 2) SYSCALL(sys_lstat, 2) SYSCALL(sys_readlink, 3) /* 85 */ SYSCALL(sys_uselib, 1) SYSCALL(sys_swapon, 2) SYSCALL(sys_reboot, 3) -SYSCALL(old_readdir, 3) -SYSCALL(old_mmap, 6) /* 90 */ +SYSCALL(sys_ni_syscall, 3) +SYSCALL(sys_ni_syscall, 6) /* 90 */ SYSCALL(sys_munmap, 2) SYSCALL(sys_truncate, 2) SYSCALL(sys_ftruncate, 2) @@ -127,7 +126,7 @@ SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_statfs, 2) SYSCALL(sys_fstatfs, 2) /* 100 */ SYSCALL(sys_ni_syscall, 3) -SYSCALL(sys_socketcall, 2) +SYSCALL(sys_ni_syscall, 2) SYSCALL(sys_syslog, 3) SYSCALL(sys_setitimer, 3) SYSCALL(sys_getitimer, 2) /* 105 */ @@ -137,32 +136,32 @@ SYSCALL(sys_newfstat, 2) SYSCALL(sys_uname, 1) SYSCALL(sys_ni_syscall, 0) /* 110 */ SYSCALL(sys_vhangup, 0) -SYSCALL(sys_ni_syscall, 0) /* was sys_idle() */ +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_wait4, 4) SYSCALL(sys_swapoff, 1) /* 115 */ SYSCALL(sys_sysinfo, 1) -SYSCALL(sys_ipc, 5) /* 6 really, but glibc uses only 5) */ +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_fsync, 1) SYSCALL(sys_sigreturn, 0) SYSCALL(sys_clone, 0) /* 120 */ SYSCALL(sys_setdomainname, 2) SYSCALL(sys_newuname, 1) -SYSCALL(sys_ni_syscall, 0) /* sys_modify_ldt */ +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_adjtimex, 1) SYSCALL(sys_mprotect, 3) /* 125 */ -SYSCALL(sys_sigprocmask, 3) -SYSCALL(sys_ni_syscall, 2) /* old sys_create_module */ +SYSCALL(sys_ni_syscall, 3) +SYSCALL(sys_ni_syscall, 2) SYSCALL(sys_init_module, 2) SYSCALL(sys_delete_module, 1) -SYSCALL(sys_ni_syscall, 1) /* old sys_get_kernel_sysm */ /* 130 */ +SYSCALL(sys_ni_syscall, 1) /* 130 */ SYSCALL(sys_quotactl, 0) SYSCALL(sys_getpgid, 1) SYSCALL(sys_fchdir, 1) SYSCALL(sys_bdflush, 2) SYSCALL(sys_sysfs, 3) /* 135 */ SYSCALL(sys_personality, 1) -SYSCALL(sys_ni_syscall, 0) /* for afs_syscall */ +SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_setfsuid, 1) SYSCALL(sys_setfsgid, 1) SYSCALL(sys_llseek, 5) /* 140 */ @@ -212,7 +211,7 @@ SYSCALL(sys_socket, 3) SYSCALL(sys_socketpair, 4) SYSCALL(sys_setresuid, 3) /* 185 */ SYSCALL(sys_getresuid, 3) -SYSCALL(sys_ni_syscall, 5) /* old sys_query_module */ +SYSCALL(sys_ni_syscall, 5) SYSCALL(sys_poll, 3) SYSCALL(sys_nfsservctl, 3) SYSCALL(sys_setresgid, 3) /* 190 */ @@ -235,7 +234,7 @@ SYSCALL(sys_sigaltstack, 0) SYSCALL(sys_sendfile, 4) SYSCALL(sys_ni_syscall, 0) SYSCALL(sys_ni_syscall, 0) -SYSCALL(sys_mmap2, 6) /* 210 */ +SYSCALL(sys_mmap, 6) /* 210 */ SYSCALL(sys_truncate64, 2) SYSCALL(sys_ftruncate64, 2) SYSCALL(sys_stat64, 2) @@ -245,4 +244,4 @@ SYSCALL(sys_pivot_root, 2) SYSCALL(sys_mincore, 3) SYSCALL(sys_madvise, 3) SYSCALL(sys_getdents64, 3) -SYSCALL(sys_vfork, 0) /* 220 */ +SYSCALL(sys_ni_syscall, 0) /* 220 */ diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h index 64c64dd83ba4..6b39d6609d9c 100644 --- a/include/asm-xtensa/unistd.h +++ b/include/asm-xtensa/unistd.h @@ -13,42 +13,31 @@ #include -//#define __NR_setup 0 /* used only by init, to get system going */ #define __NR_spill 0 #define __NR_exit 1 -#define __NR_fork 2 #define __NR_read 3 #define __NR_write 4 #define __NR_open 5 #define __NR_close 6 -#define __NR_waitpid 7 #define __NR_creat 8 #define __NR_link 9 #define __NR_unlink 10 #define __NR_execve 11 #define __NR_chdir 12 -#define __NR_time 13 #define __NR_mknod 14 #define __NR_chmod 15 #define __NR_lchown 16 #define __NR_break 17 -#define __NR_oldstat 18 #define __NR_lseek 19 #define __NR_getpid 20 #define __NR_mount 21 -#define __NR_oldumount 22 #define __NR_setuid 23 #define __NR_getuid 24 -#define __NR_stime 25 #define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_oldfstat 28 -#define __NR_pause 29 #define __NR_utime 30 #define __NR_stty 31 #define __NR_gtty 32 #define __NR_access 33 -#define __NR_nice 34 #define __NR_ftime 35 #define __NR_sync 36 #define __NR_kill 37 @@ -66,24 +55,18 @@ #define __NR_geteuid 49 #define __NR_getegid 50 #define __NR_acct 51 -#define __NR_umount 52 #define __NR_lock 53 #define __NR_ioctl 54 #define __NR_fcntl 55 -#define __NR_mpx 56 #define __NR_setpgid 57 #define __NR_ulimit 58 -#define __NR_oldolduname 59 #define __NR_umask 60 #define __NR_chroot 61 #define __NR_ustat 62 #define __NR_dup2 63 #define __NR_getppid 64 -#define __NR_getpgrp 65 #define __NR_setsid 66 #define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 #define __NR_setreuid 70 #define __NR_setregid 71 #define __NR_sigsuspend 72 @@ -98,13 +81,10 @@ #define __NR_setgroups 81 #define __NR_select 82 #define __NR_symlink 83 -#define __NR_oldlstat 84 #define __NR_readlink 85 #define __NR_uselib 86 #define __NR_swapon 87 #define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 #define __NR_munmap 91 #define __NR_truncate 92 #define __NR_ftruncate 93 @@ -116,22 +96,18 @@ #define __NR_statfs 99 #define __NR_fstatfs 100 #define __NR_ioperm 101 -#define __NR_socketcall 102 #define __NR_syslog 103 #define __NR_setitimer 104 #define __NR_getitimer 105 #define __NR_stat 106 #define __NR_lstat 107 #define __NR_fstat 108 -#define __NR_olduname 109 #define __NR_iopl 110 #define __NR_vhangup 111 #define __NR_idle 112 -#define __NR_vm86 113 #define __NR_wait4 114 #define __NR_swapoff 115 #define __NR_sysinfo 116 -#define __NR_ipc 117 #define __NR_fsync 118 #define __NR_sigreturn 119 #define __NR_clone 120 @@ -140,18 +116,15 @@ #define __NR_modify_ldt 123 #define __NR_adjtimex 124 #define __NR_mprotect 125 -#define __NR_sigprocmask 126 #define __NR_create_module 127 #define __NR_init_module 128 #define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 #define __NR_quotactl 131 #define __NR_getpgid 132 #define __NR_fchdir 133 #define __NR_bdflush 134 #define __NR_sysfs 135 #define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ #define __NR_setfsuid 138 #define __NR_setfsgid 139 #define __NR__llseek 140 @@ -222,8 +195,6 @@ #define __NR_capset 205 #define __NR_sigaltstack 206 #define __NR_sendfile 207 -#define __NR_streams1 208 /* some people actually want it */ -#define __NR_streams2 209 /* some people actually want it */ #define __NR_mmap2 210 #define __NR_truncate64 211 #define __NR_ftruncate64 212 @@ -234,7 +205,6 @@ #define __NR_mincore 217 #define __NR_madvise 218 #define __NR_getdents64 219 -#define __NR_vfork 220 /* Keep this last; should always equal the last valid call number. */ #define __NR_Linux_syscalls 220 @@ -448,55 +418,7 @@ __syscall_return(type,__res); \ #ifdef __KERNEL_SYSCALLS__ - -#include -#include -#include - -/* - * we need this inline - forking from kernel space will result - * in NO COPY ON WRITE (!!!), until an execve is executed. This - * is no problem, but for the stack. This is handled by not letting - * main() use the stack at all after fork(). Thus, no function - * calls - which means inline code for fork too, as otherwise we - * would use the stack upon exit from 'fork()'. - * - * Actually only pause and fork are needed inline, so that there - * won't be any messing with the stack from main(), but we define - * some others too. - */ - -#define __NR__exit __NR_exit - -static __inline__ _syscall0(int,pause) -//static __inline__ _syscall1(int,setup,int,magic) FIXME -static __inline__ _syscall0(int,sync) -static __inline__ _syscall0(pid_t,setsid) -static __inline__ _syscall3(int,write,int,fd,const char *,buf,off_t,count) -static __inline__ _syscall3(int,read,int,fd,char *,buf,off_t,count) -static __inline__ _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) -static __inline__ _syscall1(int,dup,int,fd) static __inline__ _syscall3(int,execve,const char*,file,char**,argv,char**,envp) -static __inline__ _syscall3(int,open,const char *,file,int,flag,int,mode) -static __inline__ _syscall1(int,close,int,fd) -static __inline__ _syscall1(int,_exit,int,exitcode) -static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) -static __inline__ _syscall1(int,delete_module,const char *,name) - -struct stat; -static __inline__ _syscall2(int,fstat,int,fd,struct stat *,buf) -static __inline__ _syscall0(pid_t,getpid) -static __inline__ _syscall2(int,kill,int,pid,int,sig) -static __inline__ _syscall2(int,stat,const char *, path,struct stat *,buf) -static __inline__ _syscall1(int,unlink,char *,pathname) - - - -extern pid_t waitpid(int, int*, int ); -static __inline__ pid_t wait(int * wait_stat) -{ - return waitpid(-1,wait_stat,0); -} #endif /* @@ -508,30 +430,10 @@ static __inline__ pid_t wait(int * wait_stat) #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall"); #ifdef __KERNEL__ -#define __ARCH_WANT_IPC_PARSE_VERSION -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL -#define __ARCH_WANT_SYS_TIME #define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLD_GETRLIMIT -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION #endif - - #endif /* _XTENSA_UNISTD_H */ -- cgit v1.3-14-g43fede From a39722034ae37f80a1803bf781fe3fe1b03e20bc Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 7 Jul 2005 17:56:56 -0700 Subject: [PATCH] page_uptodate locking scalability Use a bit spin lock in the first buffer of the page to synchronise asynch IO buffer completions, instead of the global page_uptodate_lock, which is showing some scalabilty problems. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 25 +++++++++++++++++-------- include/linux/buffer_head.h | 3 +++ 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/fs/buffer.c b/fs/buffer.c index 561e63a14966..6a25d7df89b1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -513,8 +513,8 @@ static void free_more_memory(void) */ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) { - static DEFINE_SPINLOCK(page_uptodate_lock); unsigned long flags; + struct buffer_head *first; struct buffer_head *tmp; struct page *page; int page_uptodate = 1; @@ -536,7 +536,9 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) * two buffer heads end IO at almost the same time and both * decide that the page is now completely done. */ - spin_lock_irqsave(&page_uptodate_lock, flags); + first = page_buffers(page); + local_irq_save(flags); + bit_spin_lock(BH_Uptodate_Lock, &first->b_state); clear_buffer_async_read(bh); unlock_buffer(bh); tmp = bh; @@ -549,7 +551,8 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) } tmp = tmp->b_this_page; } while (tmp != bh); - spin_unlock_irqrestore(&page_uptodate_lock, flags); + bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); + local_irq_restore(flags); /* * If none of the buffers had errors and they are all @@ -561,7 +564,8 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) return; still_busy: - spin_unlock_irqrestore(&page_uptodate_lock, flags); + bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); + local_irq_restore(flags); return; } @@ -572,8 +576,8 @@ still_busy: void end_buffer_async_write(struct buffer_head *bh, int uptodate) { char b[BDEVNAME_SIZE]; - static DEFINE_SPINLOCK(page_uptodate_lock); unsigned long flags; + struct buffer_head *first; struct buffer_head *tmp; struct page *page; @@ -594,7 +598,10 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate) SetPageError(page); } - spin_lock_irqsave(&page_uptodate_lock, flags); + first = page_buffers(page); + local_irq_save(flags); + bit_spin_lock(BH_Uptodate_Lock, &first->b_state); + clear_buffer_async_write(bh); unlock_buffer(bh); tmp = bh->b_this_page; @@ -605,12 +612,14 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate) } tmp = tmp->b_this_page; } - spin_unlock_irqrestore(&page_uptodate_lock, flags); + bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); + local_irq_restore(flags); end_page_writeback(page); return; still_busy: - spin_unlock_irqrestore(&page_uptodate_lock, flags); + bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); + local_irq_restore(flags); return; } diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 802c91e9b3da..90828493791f 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -19,6 +19,9 @@ enum bh_state_bits { BH_Dirty, /* Is dirty */ BH_Lock, /* Is locked */ BH_Req, /* Has been submitted for I/O */ + BH_Uptodate_Lock,/* Used by the first bh in a page, to serialise + * IO completion of other buffers in the page + */ BH_Mapped, /* Has a disk mapping */ BH_New, /* Disk mapping was newly created by get_block */ -- cgit v1.3-14-g43fede From 0db925af1db5f3dfe1691c35b39496e2baaff9c9 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 7 Jul 2005 17:56:58 -0700 Subject: [PATCH] propagate __nocast annotations Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/gfp.h | 4 ++-- include/linux/slab.h | 4 ++-- include/linux/string.h | 2 +- mm/mempool.c | 2 +- mm/slab.c | 12 +++++++----- 5 files changed, 13 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 8d6bf608b199..7c7400137e97 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -12,8 +12,8 @@ struct vm_area_struct; * GFP bitmasks.. */ /* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */ -#define __GFP_DMA 0x01 -#define __GFP_HIGHMEM 0x02 +#define __GFP_DMA 0x01u +#define __GFP_HIGHMEM 0x02u /* * Action modifiers - doesn't change the zoning diff --git a/include/linux/slab.h b/include/linux/slab.h index 76cf7e60216c..4c8e552471b0 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -65,7 +65,7 @@ extern void *kmem_cache_alloc(kmem_cache_t *, unsigned int __nocast); extern void kmem_cache_free(kmem_cache_t *, void *); extern unsigned int kmem_cache_size(kmem_cache_t *); extern const char *kmem_cache_name(kmem_cache_t *); -extern kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags); +extern kmem_cache_t *kmem_find_general_cachep(size_t size, unsigned int __nocast gfpflags); /* Size description struct for general caches. */ struct cache_sizes { @@ -105,7 +105,7 @@ extern unsigned int ksize(const void *); #ifdef CONFIG_NUMA extern void *kmem_cache_alloc_node(kmem_cache_t *, int flags, int node); -extern void *kmalloc_node(size_t size, int flags, int node); +extern void *kmalloc_node(size_t size, unsigned int __nocast flags, int node); #else static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node) { diff --git a/include/linux/string.h b/include/linux/string.h index 93994c613095..dab2652acbd8 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -88,7 +88,7 @@ extern int memcmp(const void *,const void *,__kernel_size_t); extern void * memchr(const void *,int,__kernel_size_t); #endif -extern char *kstrdup(const char *s, int gfp); +extern char *kstrdup(const char *s, unsigned int __nocast gfp); #ifdef __cplusplus } diff --git a/mm/mempool.c b/mm/mempool.c index 9a72f7d918fa..65f2957b8d51 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -205,7 +205,7 @@ void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask) void *element; unsigned long flags; wait_queue_t wait; - int gfp_temp; + unsigned int gfp_temp; might_sleep_if(gfp_mask & __GFP_WAIT); diff --git a/mm/slab.c b/mm/slab.c index e57abd45eede..c9e706db4634 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -584,7 +584,8 @@ static inline struct array_cache *ac_data(kmem_cache_t *cachep) return cachep->array[smp_processor_id()]; } -static inline kmem_cache_t *__find_general_cachep(size_t size, int gfpflags) +static inline kmem_cache_t *__find_general_cachep(size_t size, + unsigned int __nocast gfpflags) { struct cache_sizes *csizep = malloc_sizes; @@ -608,7 +609,8 @@ static inline kmem_cache_t *__find_general_cachep(size_t size, int gfpflags) return csizep->cs_cachep; } -kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags) +kmem_cache_t *kmem_find_general_cachep(size_t size, + unsigned int __nocast gfpflags) { return __find_general_cachep(size, gfpflags); } @@ -2100,7 +2102,7 @@ cache_alloc_debugcheck_before(kmem_cache_t *cachep, unsigned int __nocast flags) #if DEBUG static void * cache_alloc_debugcheck_after(kmem_cache_t *cachep, - unsigned long flags, void *objp, void *caller) + unsigned int __nocast flags, void *objp, void *caller) { if (!objp) return objp; @@ -2442,7 +2444,7 @@ got_slabp: } EXPORT_SYMBOL(kmem_cache_alloc_node); -void *kmalloc_node(size_t size, int flags, int node) +void *kmalloc_node(size_t size, unsigned int __nocast flags, int node) { kmem_cache_t *cachep; @@ -3094,7 +3096,7 @@ unsigned int ksize(const void *objp) * @s: the string to duplicate * @gfp: the GFP mask used in the kmalloc() call when allocating memory */ -char *kstrdup(const char *s, int gfp) +char *kstrdup(const char *s, unsigned int __nocast gfp) { size_t len; char *buf; -- cgit v1.3-14-g43fede From 6c036527a630720063b67d9a65455e8caca2c8fa Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Thu, 7 Jul 2005 17:56:59 -0700 Subject: [PATCH] mostly_read data section Add a new section called ".data.read_mostly" for data items that are read frequently and rarely written to like cpumaps etc. If these maps are placed in the .data section then these frequenly read items may end up in cachelines with data is is frequently updated. In that case all processors in an SMP system must needlessly reload the cachelines again and again containing elements of those frequently used variables. The ability to share these cachelines will allow each cpu in an SMP system to keep local copies of those shared cachelines thereby optimizing performance. Signed-off-by: Alok N Kataria Signed-off-by: Shobhit Dayal Signed-off-by: Christoph Lameter Signed-off-by: Shai Fultheim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/intel.c | 2 +- arch/i386/kernel/smpboot.c | 18 +++++++++--------- arch/i386/kernel/time.c | 2 +- arch/i386/kernel/timers/timer_hpet.c | 4 ++-- arch/i386/kernel/vmlinux.lds.S | 3 +++ arch/x86_64/kernel/vmlinux.lds.S | 4 ++++ drivers/char/random.c | 2 +- fs/bio.c | 2 +- include/linux/cache.h | 6 ++++++ kernel/profile.c | 4 ++-- lib/radix-tree.c | 2 +- 11 files changed, 31 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index 96a75d045835..a2c33c1a46c5 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c @@ -25,7 +25,7 @@ extern int trap_init_f00f_bug(void); /* * Alignment at which movsl is preferred for bulk memory copies. */ -struct movsl_mask movsl_mask; +struct movsl_mask movsl_mask __read_mostly; #endif void __devinit early_intel_workaround(struct cpuinfo_x86 *c) diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index d66bf489a2e9..8ac8e9fd5614 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -68,21 +68,21 @@ EXPORT_SYMBOL(smp_num_siblings); #endif /* Package ID of each logical CPU */ -int phys_proc_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID}; +int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; EXPORT_SYMBOL(phys_proc_id); /* Core ID of each logical CPU */ -int cpu_core_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID}; +int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; EXPORT_SYMBOL(cpu_core_id); -cpumask_t cpu_sibling_map[NR_CPUS]; +cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_sibling_map); -cpumask_t cpu_core_map[NR_CPUS]; +cpumask_t cpu_core_map[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_core_map); /* bitmap of online cpus */ -cpumask_t cpu_online_map; +cpumask_t cpu_online_map __read_mostly; EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_callin_map; @@ -100,7 +100,7 @@ static int __devinitdata tsc_sync_disabled; struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; EXPORT_SYMBOL(cpu_data); -u8 x86_cpu_to_apicid[NR_CPUS] = +u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0xff }; EXPORT_SYMBOL(x86_cpu_to_apicid); @@ -550,10 +550,10 @@ extern struct { #ifdef CONFIG_NUMA /* which logical CPUs are on which nodes */ -cpumask_t node_2_cpu_mask[MAX_NUMNODES] = +cpumask_t node_2_cpu_mask[MAX_NUMNODES] __read_mostly = { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE }; /* which node each logical CPU is on */ -int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 }; +int cpu_2_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 }; EXPORT_SYMBOL(cpu_2_node); /* set up a mapping between cpu and node. */ @@ -581,7 +581,7 @@ static inline void unmap_cpu_to_node(int cpu) #endif /* CONFIG_NUMA */ -u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; +u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; static void map_cpu_to_logical_apicid(void) { diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 2854c357377f..0ee9dee8af06 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -91,7 +91,7 @@ EXPORT_SYMBOL(rtc_lock); DEFINE_SPINLOCK(i8253_lock); EXPORT_SYMBOL(i8253_lock); -struct timer_opts *cur_timer = &timer_none; +struct timer_opts *cur_timer __read_mostly = &timer_none; /* * This is a special lock that is owned by the CPU and holds the index diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c index d766e0963ac1..ef8dac5dd33b 100644 --- a/arch/i386/kernel/timers/timer_hpet.c +++ b/arch/i386/kernel/timers/timer_hpet.c @@ -18,7 +18,7 @@ #include "mach_timer.h" #include -static unsigned long hpet_usec_quotient; /* convert hpet clks to usec */ +static unsigned long __read_mostly hpet_usec_quotient; /* convert hpet clks to usec */ static unsigned long tsc_hpet_quotient; /* convert tsc to hpet clks */ static unsigned long hpet_last; /* hpet counter value at last tick*/ static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ @@ -180,7 +180,7 @@ static int __init init_hpet(char* override) /************************************************************/ /* tsc timer_opts struct */ -static struct timer_opts timer_hpet = { +static struct timer_opts timer_hpet __read_mostly = { .name = "hpet", .mark_offset = mark_offset_hpet, .get_offset = get_offset_hpet, diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index 7e01a528a83a..761972f8cb6c 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -57,6 +57,9 @@ SECTIONS *(.data.cacheline_aligned) } + /* rarely changed data like cpu maps */ + . = ALIGN(32); + .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) } _edata = .; /* End of data section */ . = ALIGN(THREAD_SIZE); /* init_task */ diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index 73389f51c4e5..61c12758ca70 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -56,6 +56,10 @@ SECTIONS .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { *(.data.cacheline_aligned) } + . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); + .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { + *(.data.read_mostly) + } #define VSYSCALL_ADDR (-10*1024*1024) #define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095)) diff --git a/drivers/char/random.c b/drivers/char/random.c index 460b5d475edd..6b11d6b2129f 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -271,7 +271,7 @@ static int random_write_wakeup_thresh = 128; * samples to avoid wasting CPU time and reduce lock contention. */ -static int trickle_thresh = INPUT_POOL_WORDS * 28; +static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28; static DEFINE_PER_CPU(int, trickle_count) = 0; diff --git a/fs/bio.c b/fs/bio.c index 3a1472acc361..ca8f7a850fe3 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -52,7 +52,7 @@ struct biovec_slab { */ #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } -static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] = { +static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), }; #undef BV diff --git a/include/linux/cache.h b/include/linux/cache.h index 4d767b93738a..2b66a36d85f0 100644 --- a/include/linux/cache.h +++ b/include/linux/cache.h @@ -13,6 +13,12 @@ #define SMP_CACHE_BYTES L1_CACHE_BYTES #endif +#ifdef CONFIG_X86 +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) +#else +#define __read_mostly +#endif + #ifndef ____cacheline_aligned #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES))) #endif diff --git a/kernel/profile.c b/kernel/profile.c index ad8cbb75ffa2..f89248e6d704 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -35,11 +35,11 @@ struct profile_hit { #define NR_PROFILE_GRP (NR_PROFILE_HIT/PROFILE_GRPSZ) /* Oprofile timer tick hook */ -int (*timer_hook)(struct pt_regs *); +int (*timer_hook)(struct pt_regs *) __read_mostly; static atomic_t *prof_buffer; static unsigned long prof_len, prof_shift; -static int prof_on; +static int prof_on __read_mostly; static cpumask_t prof_cpu_mask = CPU_MASK_ALL; #ifdef CONFIG_SMP static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 04d664377f2c..10bed1c8c3c3 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -58,7 +58,7 @@ struct radix_tree_path { #define RADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) #define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2) -static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH]; +static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH] __read_mostly; /* * Radix tree node cache. -- cgit v1.3-14-g43fede From 404865516ce6b6d7ee37c4eb4ee77d78b38e669a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 7 Jul 2005 17:57:09 -0700 Subject: [PATCH] alpha(): pgprot_noncached The infiniband code expects that the arch implements pgprot_noncached(). We're mapping PCI areas anyway, so this probabyl wasn't needed and we should make infiniband stop doing that.. Cc: Roland Dreier Cc: Richard Henderson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/pgtable.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 408aea55e0cc..e139463d9a0e 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -132,6 +132,8 @@ #define __S110 _PAGE_S(0) #define __S111 _PAGE_S(0) +#define pgprot_noncached(prot) (prot) + /* * BAD_PAGETABLE is used when we need a bogus page-table, while * BAD_PAGE is used for a bogus page. -- cgit v1.3-14-g43fede From 1ce88cf466f7b6078b14d67d186a3d7c19dd5609 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 7 Jul 2005 17:57:24 -0700 Subject: [PATCH] namespace.c: fix race in mark_mounts_for_expiry() This patch fixes a race found by Ram in mark_mounts_for_expiry() in fs/namespace.c. The bug can only be triggered with simultaneous exiting of a process having a private namespace, and expiry of a mount from within that namespace. It's practically impossible to trigger, and I haven't even tried. But still, a bug is a bug. The race happens when put_namespace() is called by another task, while mark_mounts_for_expiry() is between atomic_read() and get_namespace(). In that case get_namespace() will be called on an already dead namespace with unforeseeable results. The solution was suggested by Al Viro, with his own words: Instead of screwing with atomic_read() in there, why don't we simply do the following: a) atomic_dec_and_lock() in put_namespace() b) __put_namespace() called without dropping lock c) the first thing done by __put_namespace would be struct vfsmount *root = namespace->root; namespace->root = NULL; spin_unlock(...); .... umount_tree(root); ... d) check in mark_... would be simply namespace && namespace->root. And we are all set; no screwing around with atomic_read(), no magic at all. Dying namespace gets NULL ->root. All changes of ->root happen under spinlock. If under a spinlock we see non-NULL ->mnt_namespace, it won't be freed until we drop the lock (we will set ->mnt_namespace to NULL under that lock before we get to freeing namespace). If under a spinlock we see non-NULL ->mnt_namespace and ->mnt_namespace->root, we can grab a reference to namespace and be sure that it won't go away. Signed-off-by: Miklos Szeredi Acked-by: Al Viro Acked-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namespace.c | 7 +++++-- include/linux/namespace.h | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index a0d0ef1f1a48..9d17541ebafa 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -869,7 +869,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) /* don't do anything if the namespace is dead - all the * vfsmounts from it are going away anyway */ namespace = mnt->mnt_namespace; - if (!namespace || atomic_read(&namespace->count) <= 0) + if (!namespace || !namespace->root) continue; get_namespace(namespace); @@ -1450,9 +1450,12 @@ void __init mnt_init(unsigned long mempages) void __put_namespace(struct namespace *namespace) { + struct vfsmount *root = namespace->root; + namespace->root = NULL; + spin_unlock(&vfsmount_lock); down_write(&namespace->sem); spin_lock(&vfsmount_lock); - umount_tree(namespace->root); + umount_tree(root); spin_unlock(&vfsmount_lock); up_write(&namespace->sem); kfree(namespace); diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 697991b69f9b..0e5a86f13b2f 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -17,7 +17,8 @@ extern void __put_namespace(struct namespace *namespace); static inline void put_namespace(struct namespace *namespace) { - if (atomic_dec_and_test(&namespace->count)) + if (atomic_dec_and_lock(&namespace->count, &vfsmount_lock)) + /* releases vfsmount_lock */ __put_namespace(namespace); } -- cgit v1.3-14-g43fede From 55e700b924f9e0ba24e3a071d1097d050b05abe6 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 7 Jul 2005 17:57:30 -0700 Subject: [PATCH] namespace: rename mnt_fslink to mnt_expire This patch renames vfsmount->mnt_fslink to something a little more descriptive: vfsmount->mnt_expire. Signed-off-by: Mike Waychison Signed-off-by: Miklos Szeredi Acked-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namespace.c | 24 ++++++++++++------------ include/linux/mount.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index b168dc37eaab..587eb0d707ee 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -61,7 +61,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); - INIT_LIST_HEAD(&mnt->mnt_fslink); + INIT_LIST_HEAD(&mnt->mnt_expire); if (name) { int size = strlen(name)+1; char *newname = kmalloc(size, GFP_KERNEL); @@ -165,8 +165,8 @@ clone_mnt(struct vfsmount *old, struct dentry *root) /* stick the duplicate mount on the same expiry list * as the original if that was on one */ spin_lock(&vfsmount_lock); - if (!list_empty(&old->mnt_fslink)) - list_add(&mnt->mnt_fslink, &old->mnt_fslink); + if (!list_empty(&old->mnt_expire)) + list_add(&mnt->mnt_expire, &old->mnt_expire); spin_unlock(&vfsmount_lock); } return mnt; @@ -351,7 +351,7 @@ static void umount_tree(struct vfsmount *mnt) while (!list_empty(&kill)) { mnt = list_entry(kill.next, struct vfsmount, mnt_list); list_del_init(&mnt->mnt_list); - list_del_init(&mnt->mnt_fslink); + list_del_init(&mnt->mnt_expire); if (mnt->mnt_parent == mnt) { spin_unlock(&vfsmount_lock); } else { @@ -645,7 +645,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) if (mnt) { /* stop bind mounts from expiring */ spin_lock(&vfsmount_lock); - list_del_init(&mnt->mnt_fslink); + list_del_init(&mnt->mnt_expire); spin_unlock(&vfsmount_lock); err = graft_tree(mnt, nd); @@ -744,7 +744,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) /* if the mount is moved, it should no longer be expire * automatically */ - list_del_init(&old_nd.mnt->mnt_fslink); + list_del_init(&old_nd.mnt->mnt_expire); out2: spin_unlock(&vfsmount_lock); out1: @@ -814,7 +814,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, if (err == 0 && fslist) { /* add to the specified expiration list */ spin_lock(&vfsmount_lock); - list_add_tail(&newmnt->mnt_fslink, fslist); + list_add_tail(&newmnt->mnt_expire, fslist); spin_unlock(&vfsmount_lock); } @@ -869,7 +869,7 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) * Someone brought it back to life whilst we didn't have any * locks held so return it to the expiration list */ - list_add_tail(&mnt->mnt_fslink, mounts); + list_add_tail(&mnt->mnt_expire, mounts); spin_unlock(&vfsmount_lock); } } @@ -896,13 +896,13 @@ void mark_mounts_for_expiry(struct list_head *mounts) * - still marked for expiry (marked on the last call here; marks are * cleared by mntput()) */ - list_for_each_entry_safe(mnt, next, mounts, mnt_fslink) { + list_for_each_entry_safe(mnt, next, mounts, mnt_expire) { if (!xchg(&mnt->mnt_expiry_mark, 1) || atomic_read(&mnt->mnt_count) != 1) continue; mntget(mnt); - list_move(&mnt->mnt_fslink, &graveyard); + list_move(&mnt->mnt_expire, &graveyard); } /* @@ -912,8 +912,8 @@ void mark_mounts_for_expiry(struct list_head *mounts) * - dispose of the corpse */ while (!list_empty(&graveyard)) { - mnt = list_entry(graveyard.next, struct vfsmount, mnt_fslink); - list_del_init(&mnt->mnt_fslink); + mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire); + list_del_init(&mnt->mnt_expire); /* don't do anything if the namespace is dead - all the * vfsmounts from it are going away anyway */ diff --git a/include/linux/mount.h b/include/linux/mount.h index 8b8d3b9beefd..196d2d6de4a3 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -34,7 +34,7 @@ struct vfsmount int mnt_expiry_mark; /* true if marked for expiry */ char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; - struct list_head mnt_fslink; /* link in fs-specific expiry list */ + struct list_head mnt_expire; /* link in fs-specific expiry list */ struct namespace *mnt_namespace; /* containing namespace */ }; -- cgit v1.3-14-g43fede From 751c404b8f63e8199d5f2f8f2bcfd69b41d11caa Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 7 Jul 2005 17:57:30 -0700 Subject: [PATCH] namespace: rename _mntput to mntput_no_expire This patch renames _mntput() to something a little more descriptive: mntput_no_expire(). Signed-off-by: Miklos Szeredi Acked-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namei.c | 2 +- include/linux/mount.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/fs/namei.c b/fs/namei.c index fa8df81ce8ca..1d93cb4f7c5f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -314,7 +314,7 @@ void path_release(struct nameidata *nd) void path_release_on_umount(struct nameidata *nd) { dput(nd->dentry); - _mntput(nd->mnt); + mntput_no_expire(nd->mnt); } /* diff --git a/include/linux/mount.h b/include/linux/mount.h index 196d2d6de4a3..74b4727a4e30 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -47,7 +47,7 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) extern void __mntput(struct vfsmount *mnt); -static inline void _mntput(struct vfsmount *mnt) +static inline void mntput_no_expire(struct vfsmount *mnt) { if (mnt) { if (atomic_dec_and_test(&mnt->mnt_count)) @@ -59,7 +59,7 @@ static inline void mntput(struct vfsmount *mnt) { if (mnt) { mnt->mnt_expiry_mark = 0; - _mntput(mnt); + mntput_no_expire(mnt); } } -- cgit v1.3-14-g43fede From 1e212f3645a6b355de8c43a23376bc0e2ac49a63 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 7 Jul 2005 17:59:00 -0700 Subject: [PATCH] pcmcia: move event handler Move the "event handler" to struct pcmcia_driver -- the unified event handler will disappear really soon, but switching it to struct pcmcia_driver in the meantime allows for better "step-by-step" patches. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/bluetooth/bluecard_cs.c | 6 +----- drivers/bluetooth/bt3c_cs.c | 6 +----- drivers/bluetooth/btuart_cs.c | 6 +----- drivers/bluetooth/dtl1_cs.c | 6 +----- drivers/char/pcmcia/synclink_cs.c | 6 +----- drivers/ide/legacy/ide-cs.c | 6 +----- drivers/isdn/hardware/avm/avm_cs.c | 6 +----- drivers/isdn/hisax/avma1_cs.c | 6 +----- drivers/isdn/hisax/elsa_cs.c | 6 +----- drivers/isdn/hisax/sedlbauer_cs.c | 6 +----- drivers/isdn/hisax/teles_cs.c | 6 +----- drivers/mtd/maps/pcmciamtd.c | 6 +----- drivers/net/pcmcia/3c574_cs.c | 6 +----- drivers/net/pcmcia/3c589_cs.c | 6 +----- drivers/net/pcmcia/axnet_cs.c | 6 +----- drivers/net/pcmcia/com20020_cs.c | 6 +----- drivers/net/pcmcia/fmvj18x_cs.c | 6 +----- drivers/net/pcmcia/ibmtr_cs.c | 6 +----- drivers/net/pcmcia/nmclan_cs.c | 6 +----- drivers/net/pcmcia/pcnet_cs.c | 6 +----- drivers/net/pcmcia/smc91c92_cs.c | 5 +---- drivers/net/pcmcia/xirc2ps_cs.c | 6 +----- drivers/net/wireless/airo_cs.c | 6 +----- drivers/net/wireless/atmel_cs.c | 16 ++++++---------- drivers/net/wireless/netwave_cs.c | 6 +----- drivers/net/wireless/orinoco_cs.c | 6 +----- drivers/net/wireless/ray_cs.c | 6 +----- drivers/net/wireless/wavelan_cs.c | 7 +------ drivers/net/wireless/wl3501_cs.c | 18 ++++++------------ drivers/parport/parport_cs.c | 6 +----- drivers/pcmcia/cs_internal.h | 3 --- drivers/pcmcia/ds.c | 32 ++++++++++++++++++++------------ drivers/scsi/pcmcia/aha152x_stub.c | 6 +----- drivers/scsi/pcmcia/fdomain_stub.c | 6 +----- drivers/scsi/pcmcia/nsp_cs.c | 16 ++++++---------- drivers/scsi/pcmcia/qlogic_stub.c | 3 +-- drivers/scsi/pcmcia/sym53c500_cs.c | 5 +---- drivers/serial/serial_cs.c | 6 +----- drivers/telephony/ixj_pcmcia.c | 6 +----- drivers/usb/host/sl811_cs.c | 6 +----- include/pcmcia/ds.h | 8 ++++---- sound/pcmcia/pdaudiocf/pdaudiocf.c | 19 ++++++------------- sound/pcmcia/vx/vx_entry.c | 12 ++---------- 43 files changed, 85 insertions(+), 245 deletions(-) (limited to 'include') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 5ef9adb9fe73..53661246100e 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -895,11 +895,6 @@ static dev_link_t *bluecard_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &bluecard_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -1103,6 +1098,7 @@ static struct pcmcia_driver bluecard_driver = { .name = "bluecard_cs", }, .attach = bluecard_attach, + .event = bluecard_event, .detach = bluecard_detach, .id_table = bluecard_ids, }; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 9013cd759afb..06539a542e98 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -696,11 +696,6 @@ static dev_link_t *bt3c_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &bt3c_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -947,6 +942,7 @@ static struct pcmcia_driver bt3c_driver = { .name = "bt3c_cs", }, .attach = bt3c_attach, + .event = bt3c_event, .detach = bt3c_detach, .id_table = bt3c_ids, }; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index c479484a1f7f..f15a9cf2b787 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -615,11 +615,6 @@ static dev_link_t *btuart_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &btuart_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -867,6 +862,7 @@ static struct pcmcia_driver btuart_driver = { .name = "btuart_cs", }, .attach = btuart_attach, + .event = btuart_event, .detach = btuart_detach, .id_table = btuart_ids, }; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index bb12f7daeb91..58b09a9cc4c6 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -594,11 +594,6 @@ static dev_link_t *dtl1_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &dtl1_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -820,6 +815,7 @@ static struct pcmcia_driver dtl1_driver = { .name = "dtl1_cs", }, .attach = dtl1_attach, + .event = dtl1_event, .detach = dtl1_detach, .id_table = dtl1_ids, }; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 8f36b1758eb6..ea691561e083 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -593,11 +593,6 @@ static dev_link_t *mgslpc_attach(void) dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &mgslpc_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -3093,6 +3088,7 @@ static struct pcmcia_driver mgslpc_driver = { .name = "synclink_cs", }, .attach = mgslpc_attach, + .event = mgslpc_event, .detach = mgslpc_detach, .id_table = mgslpc_ids, }; diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 978d27d6452d..fde0d5f1b876 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -134,11 +134,6 @@ static dev_link_t *ide_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ide_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -497,6 +492,7 @@ static struct pcmcia_driver ide_cs_driver = { .name = "ide-cs", }, .attach = ide_attach, + .event = ide_event, .detach = ide_detach, .id_table = ide_ids, }; diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index ee750e9456dd..a30c74fd75da 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -161,11 +161,6 @@ static dev_link_t *avmcs_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &avmcs_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -500,6 +495,7 @@ static struct pcmcia_driver avmcs_driver = { .name = "avm_cs", }, .attach = avmcs_attach, + .event = avmcs_event, .detach = avmcs_detach, .id_table = avmcs_ids, }; diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 67c60e04a37b..d3de0e856192 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -183,11 +183,6 @@ static dev_link_t *avma1cs_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &avma1cs_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -514,6 +509,7 @@ static struct pcmcia_driver avma1cs_driver = { .name = "avma1_cs", }, .attach = avma1cs_attach, + .event = avma1cs_event, .detach = avma1cs_detach, .id_table = avma1cs_ids, }; diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 9146be547044..54f0d68ad796 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -212,11 +212,6 @@ static dev_link_t *elsa_cs_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &elsa_cs_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -521,6 +516,7 @@ static struct pcmcia_driver elsa_cs_driver = { .name = "elsa_cs", }, .attach = elsa_cs_attach, + .event = elsa_cs_event, .detach = elsa_cs_detach, .id_table = elsa_ids, }; diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 058147a69576..baf733e86474 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -226,11 +226,6 @@ static dev_link_t *sedlbauer_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &sedlbauer_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -634,6 +629,7 @@ static struct pcmcia_driver sedlbauer_driver = { .name = "sedlbauer_cs", }, .attach = sedlbauer_attach, + .event = sedlbauer_event, .detach = sedlbauer_detach, .id_table = sedlbauer_ids, }; diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 107376ff5b9b..b8eeb789f901 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -193,11 +193,6 @@ static dev_link_t *teles_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &teles_cs_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -501,6 +496,7 @@ static struct pcmcia_driver teles_cs_driver = { .name = "teles_cs", }, .attach = teles_attach, + .event = teles_cs_event, .detach = teles_detach, .id_table = teles_ids, }; diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index c2655a817e3d..aa820ee4c31a 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -800,11 +800,6 @@ static dev_link_t *pcmciamtd_attach(void) /* Register with Card Services */ client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &pcmciamtd_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; DEBUG(2, "Calling RegisterClient"); @@ -850,6 +845,7 @@ static struct pcmcia_driver pcmciamtd_driver = { .name = "pcmciamtd" }, .attach = pcmciamtd_attach, + .event = pcmciamtd_event, .detach = pcmciamtd_detach, .owner = THIS_MODULE, .id_table = pcmciamtd_ids, diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index f0fc04bd37c4..c942964a49d2 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -312,11 +312,6 @@ static dev_link_t *tc574_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &tc574_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1299,6 +1294,7 @@ static struct pcmcia_driver tc574_driver = { .name = "3c574_cs", }, .attach = tc574_attach, + .event = tc574_event, .detach = tc574_detach, .id_table = tc574_ids, }; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 8fa1b5f0fb68..810864c6d1ea 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -226,11 +226,6 @@ static dev_link_t *tc589_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &tc589_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1074,6 +1069,7 @@ static struct pcmcia_driver tc589_driver = { .name = "3c589_cs", }, .attach = tc589_attach, + .event = tc589_event, .detach = tc589_detach, .id_table = tc589_ids, }; diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 23ce77b1d5b0..3d01079598c8 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -181,11 +181,6 @@ static dev_link_t *axnet_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &axnet_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -884,6 +879,7 @@ static struct pcmcia_driver axnet_cs_driver = { .name = "axnet_cs", }, .attach = axnet_attach, + .event = axnet_event, .detach = axnet_detach, .id_table = axnet_ids, }; diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 68d58cc58d31..b5119607d5af 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -200,11 +200,6 @@ static dev_link_t *com20020_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &com20020_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -495,6 +490,7 @@ static struct pcmcia_driver com20020_cs_driver = { .name = "com20020_cs", }, .attach = com20020_attach, + .event = com20020_event, .detach = com20020_detach, .id_table = com20020_ids, }; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 917adbbf0b5b..c7d9bb1da417 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -288,11 +288,6 @@ static dev_link_t *fmvj18x_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &fmvj18x_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -797,6 +792,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = { .name = "fmvj18x_cs", }, .attach = fmvj18x_attach, + .event = fmvj18x_event, .detach = fmvj18x_detach, .id_table = fmvj18x_ids, }; diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index cf6d073ea558..39cec4a1e4b3 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -190,11 +190,6 @@ static dev_link_t *ibmtr_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ibmtr_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -521,6 +516,7 @@ static struct pcmcia_driver ibmtr_cs_driver = { .name = "ibmtr_cs", }, .attach = ibmtr_attach, + .event = ibmtr_event, .detach = ibmtr_detach, .id_table = ibmtr_ids, }; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index b86e7253fbfc..49124dc26b35 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -502,11 +502,6 @@ static dev_link_t *nmclan_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &nmclan_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1688,6 +1683,7 @@ static struct pcmcia_driver nmclan_cs_driver = { .name = "nmclan_cs", }, .attach = nmclan_attach, + .event = nmclan_event, .detach = nmclan_detach, .id_table = nmclan_ids, }; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 855a45d062b1..b22b354af5c0 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -276,11 +276,6 @@ static dev_link_t *pcnet_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &pcnet_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1844,6 +1839,7 @@ static struct pcmcia_driver pcnet_driver = { .name = "pcnet_cs", }, .attach = pcnet_attach, + .event = pcnet_event, .detach = pcnet_detach, .owner = THIS_MODULE, .id_table = pcnet_ids, diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index bc01c88c6709..6b5471dfb554 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -370,10 +370,6 @@ static dev_link_t *smc91c92_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &smc91c92_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -2365,6 +2361,7 @@ static struct pcmcia_driver smc91c92_cs_driver = { .name = "smc91c92_cs", }, .attach = smc91c92_attach, + .event = smc91c92_event, .detach = smc91c92_detach, .id_table = smc91c92_ids, }; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 0cd225e1595c..03d4c0c6b3fd 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -619,11 +619,6 @@ xirc2ps_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &xirc2ps_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; if ((err = pcmcia_register_client(&link->handle, &client_reg))) { @@ -2016,6 +2011,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = { .name = "xirc2ps_cs", }, .attach = xirc2ps_attach, + .event = xirc2ps_event, .detach = xirc2ps_detach, .id_table = xirc2ps_ids, }; diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index f10a9523034a..fd46393e743e 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -210,11 +210,6 @@ static dev_link_t *airo_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &airo_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -574,6 +569,7 @@ static struct pcmcia_driver airo_driver = { .name = "airo_cs", }, .attach = airo_attach, + .event = airo_event, .detach = airo_detach, .id_table = airo_ids, }; diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 86379d4998ac..863be2995036 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -218,11 +218,6 @@ static dev_link_t *atmel_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &atmel_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -668,12 +663,13 @@ static struct pcmcia_device_id atmel_ids[] = { MODULE_DEVICE_TABLE(pcmcia, atmel_ids); static struct pcmcia_driver atmel_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "atmel_cs", + .owner = THIS_MODULE, + .drv = { + .name = "atmel_cs", }, - .attach = atmel_attach, - .detach = atmel_detach, + .attach = atmel_attach, + .event = atmel_event, + .detach = atmel_detach, .id_table = atmel_ids, }; diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index e12bd75b2694..bdd3e7083d9e 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -491,11 +491,6 @@ static dev_link_t *netwave_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &netwave_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1680,6 +1675,7 @@ static struct pcmcia_driver netwave_driver = { .name = "netwave_cs", }, .attach = netwave_attach, + .event = netwave_event, .detach = netwave_detach, .id_table = netwave_ids, }; diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 597c4586d049..c883404b1d59 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -186,11 +186,6 @@ orinoco_cs_attach(void) dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &orinoco_cs_event; client_reg.Version = 0x0210; /* FIXME: what does this mean? */ client_reg.event_callback_args.client_data = link; @@ -664,6 +659,7 @@ static struct pcmcia_driver orinoco_driver = { .name = DRIVER_NAME, }, .attach = orinoco_cs_attach, + .event = orinoco_cs_event, .detach = orinoco_cs_detach, .id_table = orinoco_cs_ids, }; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 31652af52eac..0643b1b94a39 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -393,11 +393,6 @@ static dev_link_t *ray_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ray_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -2916,6 +2911,7 @@ static struct pcmcia_driver ray_driver = { .name = "ray_cs", }, .attach = ray_attach, + .event = ray_event, .detach = ray_detach, .id_table = ray_ids, }; diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 89532fd92941..f6130a53b796 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4684,12 +4684,6 @@ wavelan_attach(void) /* Register with Card Services */ client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_REGISTRATION_COMPLETE | - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &wavelan_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -4904,6 +4898,7 @@ static struct pcmcia_driver wavelan_driver = { .name = "wavelan_cs", }, .attach = wavelan_attach, + .event = wavelan_event, .detach = wavelan_detach, .id_table = wavelan_ids, }; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index e3a900482d92..e3aaaa5efccf 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -2005,13 +2005,6 @@ static dev_link_t *wl3501_attach(void) link->next = wl3501_dev_list; wl3501_dev_list = link; client_reg.dev_info = &wl3501_dev_info; - client_reg.EventMask = CS_EVENT_CARD_INSERTION | - CS_EVENT_RESET_PHYSICAL | - CS_EVENT_CARD_RESET | - CS_EVENT_CARD_REMOVAL | - CS_EVENT_PM_SUSPEND | - CS_EVENT_PM_RESUME; - client_reg.event_handler = wl3501_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -2246,12 +2239,13 @@ static struct pcmcia_device_id wl3501_ids[] = { MODULE_DEVICE_TABLE(pcmcia, wl3501_ids); static struct pcmcia_driver wl3501_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "wl3501_cs", + .owner = THIS_MODULE, + .drv = { + .name = "wl3501_cs", }, - .attach = wl3501_attach, - .detach = wl3501_detach, + .attach = wl3501_attach, + .event = wl3501_event, + .detach = wl3501_detach, .id_table = wl3501_ids, }; diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index ff45662c4f7c..ad8921a260ec 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -133,11 +133,6 @@ static dev_link_t *parport_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &parport_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -386,6 +381,7 @@ static struct pcmcia_driver parport_cs_driver = { .name = "parport_cs", }, .attach = parport_attach, + .event = parport_event, .detach = parport_detach, .id_table = parport_ids, diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 0b4c18edfa49..e0ba4b5daa13 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -114,9 +114,6 @@ static inline void cs_socket_put(struct pcmcia_socket *skt) #define CHECK_ERASEQ(q) \ (((q) == NULL) || ((q)->eraseq_magic != ERASEQ_MAGIC)) -#define EVENT(h, e, p) \ - ((h)->event_handler((e), (p), &(h)->event_callback_args)) - /* In cardbus.c */ int cb_alloc(struct pcmcia_socket *s); void cb_free(struct pcmcia_socket *s); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index d5afd557fe37..367ebf75beeb 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -207,6 +207,10 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) unsigned int i; u32 hash; + if (!p_drv->attach || !p_drv->event || !p_drv->detach) + printk(KERN_DEBUG "pcmcia: %s does misses a callback function", + p_drv->drv.name); + while (did && did->match_flags) { for (i=0; i<4; i++) { if (!did->prod_id[i]) @@ -914,6 +918,7 @@ struct send_event_data { static int send_event_callback(struct device *dev, void * _data) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); + struct pcmcia_driver *p_drv; struct send_event_data *data = _data; /* we get called for all sockets, but may only pass the event @@ -921,11 +926,16 @@ static int send_event_callback(struct device *dev, void * _data) if (p_dev->socket != data->skt) return 0; + p_drv = to_pcmcia_drv(p_dev->dev.driver); + if (!p_drv) + return 0; + if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE)) return 0; - if (p_dev->client.EventMask & data->event) - return EVENT(&p_dev->client, data->event, data->priority); + if (p_drv->event) + return p_drv->event(data->event, data->priority, + &p_dev->event_callback_args); return 0; } @@ -992,6 +1002,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) client_t *client = NULL; struct pcmcia_socket *s = NULL; struct pcmcia_device *p_dev = NULL; + struct pcmcia_driver *p_drv = NULL; /* Look for unbound client with matching dev_info */ down_read(&pcmcia_socket_list_rwsem); @@ -1006,7 +1017,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) continue; spin_lock_irqsave(&pcmcia_dev_list_lock, flags); list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { - struct pcmcia_driver *p_drv; p_dev = pcmcia_get_dev(p_dev); if (!p_dev) continue; @@ -1036,10 +1046,9 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) *handle = client; client->state &= ~CLIENT_UNBOUND; client->Socket = s; - client->EventMask = req->EventMask; - client->event_handler = req->event_handler; - client->event_callback_args = req->event_callback_args; - client->event_callback_args.client_handle = client; + p_dev->event_callback_args = req->event_callback_args; + p_dev->event_callback_args.client_handle = client; + if (s->state & SOCKET_CARDBUS) client->state |= CLIENT_CARDBUS; @@ -1061,12 +1070,12 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) ds_dbg(1, "register_client(): client 0x%p, dev %s\n", client, p_dev->dev.bus_id); - if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE) - EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW); if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) { - if (client->EventMask & CS_EVENT_CARD_INSERTION) - EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); + if (p_drv->event) + p_drv->event(CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW, + &p_dev->event_callback_args); + } return CS_SUCCESS; @@ -1132,7 +1141,6 @@ int pcmcia_deregister_client(client_handle_t handle) pcmcia_put_dev(p_dev); } else { handle->state = CLIENT_UNBOUND; - handle->event_handler = NULL; } return CS_SUCCESS; diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index f1f6bf596dc9..3dc6957bad10 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -134,11 +134,6 @@ static dev_link_t *aha152x_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.event_handler = &aha152x_event; - client_reg.EventMask = - CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -334,6 +329,7 @@ static struct pcmcia_driver aha152x_cs_driver = { .name = "aha152x_cs", }, .attach = aha152x_attach, + .event = aha152x_event, .detach = aha152x_detach, .id_table = aha152x_ids, }; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 853e6ee9b71a..d2281eba790d 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -120,11 +120,6 @@ static dev_link_t *fdomain_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.event_handler = &fdomain_event; - client_reg.EventMask = - CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -314,6 +309,7 @@ static struct pcmcia_driver fdomain_cs_driver = { .name = "fdomain_cs", }, .attach = fdomain_attach, + .event = fdomain_event, .detach = fdomain_detach, .id_table = fdomain_ids, }; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 91b3f28e7a19..c8755adfd917 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1642,11 +1642,6 @@ static dev_link_t *nsp_cs_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME ; - client_reg.event_handler = &nsp_cs_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -2138,12 +2133,13 @@ static struct pcmcia_device_id nsp_cs_ids[] = { MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids); static struct pcmcia_driver nsp_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "nsp_cs", + .owner = THIS_MODULE, + .drv = { + .name = "nsp_cs", }, - .attach = nsp_cs_attach, - .detach = nsp_cs_detach, + .attach = nsp_cs_attach, + .event = nsp_cs_event, + .detach = nsp_cs_detach, .id_table = nsp_cs_ids, }; #endif diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 0dcf41102abf..e6e496180d11 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -194,8 +194,6 @@ static dev_link_t *qlogic_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.event_handler = &qlogic_event; - client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -423,6 +421,7 @@ static struct pcmcia_driver qlogic_cs_driver = { .name = "qlogic_cs", }, .attach = qlogic_attach, + .event = qlogic_event, .detach = qlogic_detach, .id_table = qlogic_ids, }; diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 7d4b16b6797d..b4b3a1a8a0c7 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -979,10 +979,6 @@ SYM53C500_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.event_handler = &SYM53C500_event; - client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1013,6 +1009,7 @@ static struct pcmcia_driver sym53c500_cs_driver = { .name = "sym53c500_cs", }, .attach = SYM53C500_attach, + .event = SYM53C500_event, .detach = SYM53C500_detach, .id_table = sym53c500_ids, }; diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 73a34b18866f..83bfd11a1cc4 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -232,11 +232,6 @@ static dev_link_t *serial_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &serial_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -883,6 +878,7 @@ static struct pcmcia_driver serial_cs_driver = { .name = "serial_cs", }, .attach = serial_attach, + .event = serial_event, .detach = serial_detach, .id_table = serial_ids, }; diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index ce5ebfe4af2b..2fcb4db3abc5 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -69,11 +69,6 @@ static dev_link_t *ixj_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ixj_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -307,6 +302,7 @@ static struct pcmcia_driver ixj_driver = { .name = "ixj_cs", }, .attach = ixj_attach, + .event = ixj_event, .detach = ixj_detach, .id_table = ixj_ids, }; diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 269d8ef01459..55dfeec6fdb5 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -389,11 +389,6 @@ static dev_link_t *sl811_cs_attach(void) dev_list = link; client_reg.dev_info = (dev_info_t *) &driver_name; client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &sl811_cs_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -418,6 +413,7 @@ static struct pcmcia_driver sl811_cs_driver = { .name = (char *)driver_name, }, .attach = sl811_cs_attach, + .event = sl811_cs_event, .detach = sl811_cs_detach, .id_table = sl811_ids, }; diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 2b52553f2d94..c574ff108148 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -133,6 +133,8 @@ struct pcmcia_socket; struct pcmcia_driver { dev_link_t *(*attach)(void); + int (*event) (event_t event, int priority, + event_callback_args_t *); void (*detach)(dev_link_t *); struct module *owner; struct pcmcia_device_id *id_table; @@ -159,15 +161,13 @@ struct pcmcia_device { /* deprecated, a cleaned up version will be moved into this struct soon */ dev_link_t *instance; + event_callback_args_t event_callback_args; + struct client_t { u_short client_magic; struct pcmcia_socket *Socket; u_char Function; u_int state; - event_t EventMask; - int (*event_handler) (event_t event, int priority, - event_callback_args_t *); - event_callback_args_t event_callback_args; } client; /* information about this device */ diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 2d4f8e28478b..c8622f5f7c3a 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -171,14 +171,6 @@ static dev_link_t *snd_pdacf_attach(void) /* Register with Card Services */ client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL -#ifdef CONFIG_PM - | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET - | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME -#endif - ; - client_reg.event_handler = &pdacf_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -387,12 +379,13 @@ static struct pcmcia_device_id snd_pdacf_ids[] = { MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids); static struct pcmcia_driver pdacf_cs_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "snd-pdaudiocf", + .owner = THIS_MODULE, + .drv = { + .name = "snd-pdaudiocf", }, - .attach = snd_pdacf_attach, - .detach = snd_pdacf_detach, + .attach = snd_pdacf_attach, + .event = pdacf_event, + .detach = snd_pdacf_detach, .id_table = snd_pdacf_ids, }; diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c index 332bbca3dfc4..df7a39ba9680 100644 --- a/sound/pcmcia/vx/vx_entry.c +++ b/sound/pcmcia/vx/vx_entry.c @@ -35,7 +35,6 @@ MODULE_LICENSE("GPL"); * prototypes */ static void vxpocket_config(dev_link_t *link); -static int vxpocket_event(event_t event, int priority, event_callback_args_t *args); static void vxpocket_release(dev_link_t *link) @@ -169,14 +168,6 @@ dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw) /* Register with Card Services */ memset(&client_reg, 0, sizeof(client_reg)); client_reg.dev_info = hw->dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL -#ifdef CONFIG_PM - | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET - | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME -#endif - ; - client_reg.event_handler = &vxpocket_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -321,7 +312,7 @@ failed: /* * event callback */ -static int vxpocket_event(event_t event, int priority, event_callback_args_t *args) +int vxpocket_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; vx_core_t *chip = link->priv; @@ -380,4 +371,5 @@ static int vxpocket_event(event_t event, int priority, event_callback_args_t *ar */ EXPORT_SYMBOL(snd_vxpocket_ops); EXPORT_SYMBOL(snd_vxpocket_attach); +EXPORT_SYMBOL(vxpocket_event); EXPORT_SYMBOL(snd_vxpocket_detach); -- cgit v1.3-14-g43fede From e12a9a93a8417c4f2aa46ce8346c2d27e656b9a2 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 7 Jul 2005 17:59:01 -0700 Subject: [PATCH] pcmcia: remove client_t usage Reduce the occurences of "client_handle_t" which is nothing else than a pointer to struct pcmcia_device by now. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/cs_internal.h | 13 ++----------- drivers/pcmcia/ds.c | 35 +++++++++++++---------------------- drivers/pcmcia/pcmcia_compat.c | 19 ++++--------------- drivers/pcmcia/pcmcia_resource.c | 31 ++++++++----------------------- include/pcmcia/cs_types.h | 4 ++-- include/pcmcia/ds.h | 12 +++--------- 6 files changed, 32 insertions(+), 82 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index e0ba4b5daa13..6bbfbd0e02a5 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -99,20 +99,11 @@ static inline void cs_socket_put(struct pcmcia_socket *skt) } } -#define CHECK_HANDLE(h) \ - (((h) == NULL) || ((h)->client_magic != CLIENT_MAGIC)) - #define CHECK_SOCKET(s) \ (((s) >= sockets) || (socket_table[s]->ops == NULL)) -#define SOCKET(h) (h->Socket) -#define CONFIG(h) (&SOCKET(h)->config[(h)->Function]) - -#define CHECK_REGION(r) \ - (((r) == NULL) || ((r)->region_magic != REGION_MAGIC)) - -#define CHECK_ERASEQ(q) \ - (((q) == NULL) || ((q)->eraseq_magic != ERASEQ_MAGIC)) +#define SOCKET(h) (h->socket) +#define CONFIG(h) (&SOCKET(h)->config[(h)->func]) /* In cardbus.c */ int cb_alloc(struct pcmcia_socket *s); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 367ebf75beeb..1cae9fda4e47 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -163,7 +163,7 @@ static int pcmcia_report_error(client_handle_t handle, error_info_t *err) int i; char *serv; - if (CHECK_HANDLE(handle)) + if (!handle) printk(KERN_NOTICE); else { struct pcmcia_device *p_dev = handle_to_pdev(handle); @@ -380,7 +380,7 @@ static int pcmcia_device_probe(struct device * dev) if (p_drv->attach) { p_dev->instance = p_drv->attach(); - if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) { + if ((!p_dev->instance) || (p_dev->state & CLIENT_UNBOUND)) { printk(KERN_NOTICE "ds: unable to create instance " "of '%s'!\n", p_drv->drv.name); ret = -EINVAL; @@ -520,10 +520,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); /* compat */ - p_dev->client.client_magic = CLIENT_MAGIC; - p_dev->client.Socket = s; - p_dev->client.Function = function; - p_dev->client.state = CLIENT_UNBOUND; + p_dev->state = CLIENT_UNBOUND; /* Add to the list in pcmcia_bus_socket */ spin_lock_irqsave(&pcmcia_dev_list_lock, flags); @@ -930,7 +927,7 @@ static int send_event_callback(struct device *dev, void * _data) if (!p_drv) return 0; - if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE)) + if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE)) return 0; if (p_drv->event) @@ -999,7 +996,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) { - client_t *client = NULL; + struct pcmcia_device *client = NULL; struct pcmcia_socket *s = NULL; struct pcmcia_device *p_dev = NULL; struct pcmcia_driver *p_drv = NULL; @@ -1020,14 +1017,14 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) p_dev = pcmcia_get_dev(p_dev); if (!p_dev) continue; - if (!(p_dev->client.state & CLIENT_UNBOUND) || + if (!(p_dev->state & CLIENT_UNBOUND) || (!p_dev->dev.driver)) { pcmcia_put_dev(p_dev); continue; } p_drv = to_pcmcia_drv(p_dev->dev.driver); if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) { - client = &p_dev->client; + client = p_dev; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); goto found; } @@ -1043,20 +1040,18 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */ - *handle = client; - client->state &= ~CLIENT_UNBOUND; - client->Socket = s; + *handle = p_dev; + p_dev->state &= ~CLIENT_UNBOUND; p_dev->event_callback_args = req->event_callback_args; - p_dev->event_callback_args.client_handle = client; + p_dev->event_callback_args.client_handle = p_dev; if (s->state & SOCKET_CARDBUS) client->state |= CLIENT_CARDBUS; - if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) && - (client->Function != BIND_FN_ALL)) { + if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0)) { cistpl_longlink_mfc_t mfc; - if (pccard_read_tuple(s, client->Function, CISTPL_LONGLINK_MFC, &mfc) + if (pccard_read_tuple(s, client->func, CISTPL_LONGLINK_MFC, &mfc) == CS_SUCCESS) s->functions = mfc.nfn; else @@ -1108,7 +1103,7 @@ static int unbind_request(struct pcmcia_socket *s) } p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); list_del(&p_dev->socket_device_list); - p_dev->client.state |= CLIENT_STALE; + p_dev->state |= CLIENT_STALE; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); device_unregister(&p_dev->dev); @@ -1123,9 +1118,6 @@ int pcmcia_deregister_client(client_handle_t handle) int i; struct pcmcia_device *p_dev = handle_to_pdev(handle); - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); ds_dbg(1, "deregister_client(%p)\n", handle); @@ -1136,7 +1128,6 @@ int pcmcia_deregister_client(client_handle_t handle) goto warn_out; if (handle->state & CLIENT_STALE) { - handle->client_magic = 0; handle->state &= ~CLIENT_STALE; pcmcia_put_dev(p_dev); } else { diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c index 1cc83317e7e3..916de6f85a2f 100644 --- a/drivers/pcmcia/pcmcia_compat.c +++ b/drivers/pcmcia/pcmcia_compat.c @@ -31,28 +31,22 @@ int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) { struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); - return pccard_get_first_tuple(s, handle->Function, tuple); + return pccard_get_first_tuple(s, handle->func, tuple); } EXPORT_SYMBOL(pcmcia_get_first_tuple); int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) { struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); - return pccard_get_next_tuple(s, handle->Function, tuple); + return pccard_get_next_tuple(s, handle->func, tuple); } EXPORT_SYMBOL(pcmcia_get_next_tuple); int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple) { struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); return pccard_get_tuple_data(s, tuple); } @@ -67,10 +61,8 @@ EXPORT_SYMBOL(pcmcia_parse_tuple); int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) { struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); - return pccard_validate_cis(s, handle->Function, info); + return pccard_validate_cis(s, handle->func, info); } EXPORT_SYMBOL(pcmcia_validate_cis); @@ -78,9 +70,7 @@ EXPORT_SYMBOL(pcmcia_validate_cis); int pcmcia_reset_card(client_handle_t handle, client_req_t *req) { struct pcmcia_socket *skt; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; + skt = SOCKET(handle); if (!skt) return CS_BAD_HANDLE; @@ -88,4 +78,3 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req) return pccard_reset_card(skt); } EXPORT_SYMBOL(pcmcia_reset_card); - diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index c01dc6bf1526..ac5c3abe70c0 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -206,10 +206,8 @@ int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg) { struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); - return pccard_access_configuration_register(s, handle->Function, reg); + return pccard_access_configuration_register(s, handle->func, reg); } EXPORT_SYMBOL(pcmcia_access_configuration_register); @@ -276,12 +274,12 @@ int pcmcia_get_configuration_info(client_handle_t handle, { struct pcmcia_socket *s; - if ((CHECK_HANDLE(handle)) || !config) + if (!config) return CS_BAD_HANDLE; s = SOCKET(handle); if (!s) return CS_BAD_HANDLE; - return pccard_get_configuration_info(s, handle->Function, config); + return pccard_get_configuration_info(s, handle->func, config); } EXPORT_SYMBOL(pcmcia_get_configuration_info); @@ -382,10 +380,8 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, int pcmcia_get_status(client_handle_t handle, cs_status_t *status) { struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); - return pccard_get_status(s, handle->Function, status); + return pccard_get_status(s, handle->func, status); } EXPORT_SYMBOL(pcmcia_get_status); @@ -432,8 +428,6 @@ int pcmcia_modify_configuration(client_handle_t handle, struct pcmcia_socket *s; config_t *c; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); c = CONFIG(handle); if (!(s->state & SOCKET_PRESENT)) @@ -478,8 +472,7 @@ int pcmcia_release_configuration(client_handle_t handle) struct pcmcia_socket *s; int i; - if (CHECK_HANDLE(handle) || - !(handle->state & CLIENT_CONFIG_LOCKED)) + if (!(handle->state & CLIENT_CONFIG_LOCKED)) return CS_BAD_HANDLE; handle->state &= ~CLIENT_CONFIG_LOCKED; s = SOCKET(handle); @@ -527,7 +520,7 @@ int pcmcia_release_io(client_handle_t handle, io_req_t *req) { struct pcmcia_socket *s; - if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ)) + if (!(handle->state & CLIENT_IO_REQ)) return CS_BAD_HANDLE; handle->state &= ~CLIENT_IO_REQ; s = SOCKET(handle); @@ -561,7 +554,7 @@ EXPORT_SYMBOL(pcmcia_release_io); int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) { struct pcmcia_socket *s; - if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ)) + if (!(handle->state & CLIENT_IRQ_REQ)) return CS_BAD_HANDLE; handle->state &= ~CLIENT_IRQ_REQ; s = SOCKET(handle); @@ -632,8 +625,6 @@ int pcmcia_request_configuration(client_handle_t handle, config_t *c; pccard_io_map iomap; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; @@ -762,8 +753,6 @@ int pcmcia_request_io(client_handle_t handle, io_req_t *req) struct pcmcia_socket *s; config_t *c; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; @@ -834,8 +823,6 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) int ret = CS_IN_USE, irq = 0; struct pcmcia_device *p_dev = handle_to_pdev(handle); - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; @@ -926,9 +913,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle u_long align; int w; - if (CHECK_HANDLE(*handle)) - return CS_BAD_HANDLE; - s = (*handle)->Socket; + s = (*handle)->socket; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (req->Attributes & (WIN_PAGED | WIN_SHARED)) diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h index 7881d40aac8d..c1d1629fcd27 100644 --- a/include/pcmcia/cs_types.h +++ b/include/pcmcia/cs_types.h @@ -34,8 +34,8 @@ typedef u_int event_t; typedef u_char cisdata_t; typedef u_short page_t; -struct client_t; -typedef struct client_t *client_handle_t; +struct pcmcia_device; +typedef struct pcmcia_device *client_handle_t; struct window_t; typedef struct window_t *window_handle_t; diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index c574ff108148..e0a5acb7fcb7 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -162,13 +162,7 @@ struct pcmcia_device { struct soon */ dev_link_t *instance; event_callback_args_t event_callback_args; - - struct client_t { - u_short client_magic; - struct pcmcia_socket *Socket; - u_char Function; - u_int state; - } client; + u_int state; /* information about this device */ u8 has_manf_id:1; @@ -193,8 +187,8 @@ struct pcmcia_device { #define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev) #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv) -#define handle_to_pdev(handle) container_of(handle, struct pcmcia_device, client); -#define handle_to_dev(handle) ((container_of(handle, struct pcmcia_device, client))->dev) +#define handle_to_pdev(handle) (handle) +#define handle_to_dev(handle) (handle->dev) /* error reporting */ void cs_error(client_handle_t handle, int func, int ret); -- cgit v1.3-14-g43fede From 2bc5a9bdc56fac6f7cbf95b89443e3809141c247 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 7 Jul 2005 17:59:02 -0700 Subject: [PATCH] pcmcia: reduce client_handle_t usage Reduce the occurences of "client_handle_t" which is nothing else than a pointer to struct pcmcia_device by now. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 46 ++++++-------- drivers/pcmcia/pcmcia_compat.c | 36 ++++------- drivers/pcmcia/pcmcia_resource.c | 125 ++++++++++++++------------------------- include/pcmcia/cs.h | 34 +++++------ 4 files changed, 87 insertions(+), 154 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 1cae9fda4e47..3e3c6f12bbe6 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -158,17 +158,15 @@ static const lookup_t service_table[] = { }; -static int pcmcia_report_error(client_handle_t handle, error_info_t *err) +static int pcmcia_report_error(struct pcmcia_device *p_dev, error_info_t *err) { int i; char *serv; - if (!handle) + if (!p_dev) printk(KERN_NOTICE); - else { - struct pcmcia_device *p_dev = handle_to_pdev(handle); + else printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id); - } for (i = 0; i < ARRAY_SIZE(service_table); i++) if (service_table[i].key == err->func) @@ -193,10 +191,10 @@ static int pcmcia_report_error(client_handle_t handle, error_info_t *err) /*======================================================================*/ -void cs_error(client_handle_t handle, int func, int ret) +void cs_error(struct pcmcia_device *p_dev, int func, int ret) { error_info_t err = { func, ret }; - pcmcia_report_error(handle, &err); + pcmcia_report_error(p_dev, &err); } EXPORT_SYMBOL(cs_error); @@ -574,8 +572,6 @@ static int pcmcia_card_add(struct pcmcia_socket *s) else no_funcs = 1; - /* this doesn't handle multifunction devices on one pcmcia function - * yet. */ for (i=0; i < no_funcs; i++) pcmcia_device_add(s, i); @@ -994,9 +990,8 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) -int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) +int pcmcia_register_client(struct pcmcia_device **handle, client_reg_t *req) { - struct pcmcia_device *client = NULL; struct pcmcia_socket *s = NULL; struct pcmcia_device *p_dev = NULL; struct pcmcia_driver *p_drv = NULL; @@ -1024,7 +1019,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) } p_drv = to_pcmcia_drv(p_dev->dev.driver); if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) { - client = p_dev; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); goto found; } @@ -1035,7 +1029,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) } found: up_read(&pcmcia_socket_list_rwsem); - if (!p_dev || !client) + if (!p_dev) return -ENODEV; pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */ @@ -1046,12 +1040,9 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) p_dev->event_callback_args.client_handle = p_dev; - if (s->state & SOCKET_CARDBUS) - client->state |= CLIENT_CARDBUS; - - if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0)) { + if (!s->functions) { cistpl_longlink_mfc_t mfc; - if (pccard_read_tuple(s, client->func, CISTPL_LONGLINK_MFC, &mfc) + if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, &mfc) == CS_SUCCESS) s->functions = mfc.nfn; else @@ -1064,7 +1055,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) } ds_dbg(1, "register_client(): client 0x%p, dev %s\n", - client, p_dev->dev.bus_id); + p_dev, p_dev->dev.bus_id); if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) { if (p_drv->event) @@ -1112,26 +1103,25 @@ static int unbind_request(struct pcmcia_socket *s) return 0; } /* unbind_request */ -int pcmcia_deregister_client(client_handle_t handle) +int pcmcia_deregister_client(struct pcmcia_device *p_dev) { struct pcmcia_socket *s; int i; - struct pcmcia_device *p_dev = handle_to_pdev(handle); - s = SOCKET(handle); - ds_dbg(1, "deregister_client(%p)\n", handle); + s = p_dev->socket; + ds_dbg(1, "deregister_client(%p)\n", p_dev); - if (handle->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) + if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) goto warn_out; for (i = 0; i < MAX_WIN; i++) - if (handle->state & CLIENT_WIN_REQ(i)) + if (p_dev->state & CLIENT_WIN_REQ(i)) goto warn_out; - if (handle->state & CLIENT_STALE) { - handle->state &= ~CLIENT_STALE; + if (p_dev->state & CLIENT_STALE) { + p_dev->state &= ~CLIENT_STALE; pcmcia_put_dev(p_dev); } else { - handle->state = CLIENT_UNBOUND; + p_dev->state = CLIENT_UNBOUND; } return CS_SUCCESS; diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c index 916de6f85a2f..962ca004ac1b 100644 --- a/drivers/pcmcia/pcmcia_compat.c +++ b/drivers/pcmcia/pcmcia_compat.c @@ -28,53 +28,39 @@ #include "cs_internal.h" -int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) +int pcmcia_get_first_tuple(struct pcmcia_device *p_dev, tuple_t *tuple) { - struct pcmcia_socket *s; - s = SOCKET(handle); - return pccard_get_first_tuple(s, handle->func, tuple); + return pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple); } EXPORT_SYMBOL(pcmcia_get_first_tuple); -int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) +int pcmcia_get_next_tuple(struct pcmcia_device *p_dev, tuple_t *tuple) { - struct pcmcia_socket *s; - s = SOCKET(handle); - return pccard_get_next_tuple(s, handle->func, tuple); + return pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple); } EXPORT_SYMBOL(pcmcia_get_next_tuple); -int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple) +int pcmcia_get_tuple_data(struct pcmcia_device *p_dev, tuple_t *tuple) { - struct pcmcia_socket *s; - s = SOCKET(handle); - return pccard_get_tuple_data(s, tuple); + return pccard_get_tuple_data(p_dev->socket, tuple); } EXPORT_SYMBOL(pcmcia_get_tuple_data); -int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +int pcmcia_parse_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, cisparse_t *parse) { return pccard_parse_tuple(tuple, parse); } EXPORT_SYMBOL(pcmcia_parse_tuple); -int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) +int pcmcia_validate_cis(struct pcmcia_device *p_dev, cisinfo_t *info) { - struct pcmcia_socket *s; - s = SOCKET(handle); - return pccard_validate_cis(s, handle->func, info); + return pccard_validate_cis(p_dev->socket, p_dev->func, info); } EXPORT_SYMBOL(pcmcia_validate_cis); -int pcmcia_reset_card(client_handle_t handle, client_req_t *req) +int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req) { - struct pcmcia_socket *skt; - - skt = SOCKET(handle); - if (!skt) - return CS_BAD_HANDLE; - - return pccard_reset_card(skt); + return pccard_reset_card(p_dev->socket); } EXPORT_SYMBOL(pcmcia_reset_card); diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index ac5c3abe70c0..ec2abb37f407 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -202,12 +202,11 @@ int pccard_access_configuration_register(struct pcmcia_socket *s, return CS_SUCCESS; } /* pccard_access_configuration_register */ -int pcmcia_access_configuration_register(client_handle_t handle, +int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg) { - struct pcmcia_socket *s; - s = SOCKET(handle); - return pccard_access_configuration_register(s, handle->func, reg); + return pccard_access_configuration_register(p_dev->socket, + p_dev->func, reg); } EXPORT_SYMBOL(pcmcia_access_configuration_register); @@ -269,17 +268,11 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, return CS_SUCCESS; } /* pccard_get_configuration_info */ -int pcmcia_get_configuration_info(client_handle_t handle, +int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config) { - struct pcmcia_socket *s; - - if (!config) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (!s) - return CS_BAD_HANDLE; - return pccard_get_configuration_info(s, handle->func, config); + return pccard_get_configuration_info(p_dev->socket, p_dev->func, + config); } EXPORT_SYMBOL(pcmcia_get_configuration_info); @@ -422,14 +415,14 @@ EXPORT_SYMBOL(pcmcia_map_mem_page); * * Modify a locked socket configuration */ -int pcmcia_modify_configuration(client_handle_t handle, +int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod) { struct pcmcia_socket *s; config_t *c; - s = SOCKET(handle); - c = CONFIG(handle); + s = p_dev->socket; + c = CONFIG(p_dev); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (!(c->state & CONFIG_LOCKED)) @@ -466,24 +459,18 @@ int pcmcia_modify_configuration(client_handle_t handle, EXPORT_SYMBOL(pcmcia_modify_configuration); -int pcmcia_release_configuration(client_handle_t handle) +int pcmcia_release_configuration(struct pcmcia_device *p_dev) { pccard_io_map io = { 0, 0, 0, 0, 1 }; - struct pcmcia_socket *s; + struct pcmcia_socket *s = p_dev->socket; int i; - if (!(handle->state & CLIENT_CONFIG_LOCKED)) + if (!(p_dev->state & CLIENT_CONFIG_LOCKED)) return CS_BAD_HANDLE; - handle->state &= ~CLIENT_CONFIG_LOCKED; - s = SOCKET(handle); + p_dev->state &= ~CLIENT_CONFIG_LOCKED; -#ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) - return CS_SUCCESS; -#endif - - if (!(handle->state & CLIENT_STALE)) { - config_t *c = CONFIG(handle); + if (!(p_dev->state & CLIENT_STALE)) { + config_t *c = CONFIG(p_dev); if (--(s->lock_count) == 0) { s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ s->socket.Vpp = 0; @@ -516,22 +503,16 @@ EXPORT_SYMBOL(pcmcia_release_configuration); * don't bother checking the port ranges against the current socket * values. */ -int pcmcia_release_io(client_handle_t handle, io_req_t *req) +int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) { - struct pcmcia_socket *s; + struct pcmcia_socket *s = p_dev->socket; - if (!(handle->state & CLIENT_IO_REQ)) + if (!(p_dev->state & CLIENT_IO_REQ)) return CS_BAD_HANDLE; - handle->state &= ~CLIENT_IO_REQ; - s = SOCKET(handle); - -#ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) - return CS_SUCCESS; -#endif + p_dev->state &= ~CLIENT_IO_REQ; - if (!(handle->state & CLIENT_STALE)) { - config_t *c = CONFIG(handle); + if (!(p_dev->state & CLIENT_STALE)) { + config_t *c = CONFIG(p_dev); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if ((c->io.BasePort1 != req->BasePort1) || @@ -551,16 +532,15 @@ int pcmcia_release_io(client_handle_t handle, io_req_t *req) EXPORT_SYMBOL(pcmcia_release_io); -int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) +int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) { - struct pcmcia_socket *s; - if (!(handle->state & CLIENT_IRQ_REQ)) + struct pcmcia_socket *s = p_dev->socket; + if (!(p_dev->state & CLIENT_IRQ_REQ)) return CS_BAD_HANDLE; - handle->state &= ~CLIENT_IRQ_REQ; - s = SOCKET(handle); + p_dev->state &= ~CLIENT_IRQ_REQ; - if (!(handle->state & CLIENT_STALE)) { - config_t *c = CONFIG(handle); + if (!(p_dev->state & CLIENT_STALE)) { + config_t *c = CONFIG(p_dev); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->irq.Attributes != req->Attributes) @@ -616,27 +596,21 @@ int pcmcia_release_window(window_handle_t win) EXPORT_SYMBOL(pcmcia_release_window); -int pcmcia_request_configuration(client_handle_t handle, +int pcmcia_request_configuration(struct pcmcia_device *p_dev, config_req_t *req) { int i; u_int base; - struct pcmcia_socket *s; + struct pcmcia_socket *s = p_dev->socket; config_t *c; pccard_io_map iomap; - s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; -#ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) - return CS_UNSUPPORTED_MODE; -#endif - if (req->IntType & INT_CARDBUS) return CS_UNSUPPORTED_MODE; - c = CONFIG(handle); + c = CONFIG(p_dev); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; @@ -737,7 +711,7 @@ int pcmcia_request_configuration(client_handle_t handle, } c->state |= CONFIG_LOCKED; - handle->state |= CLIENT_CONFIG_LOCKED; + p_dev->state |= CLIENT_CONFIG_LOCKED; return CS_SUCCESS; } /* pcmcia_request_configuration */ EXPORT_SYMBOL(pcmcia_request_configuration); @@ -748,27 +722,17 @@ EXPORT_SYMBOL(pcmcia_request_configuration); * Request_io() reserves ranges of port addresses for a socket. * I have not implemented range sharing or alias addressing. */ -int pcmcia_request_io(client_handle_t handle, io_req_t *req) +int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) { - struct pcmcia_socket *s; + struct pcmcia_socket *s = p_dev->socket; config_t *c; - s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - if (handle->state & CLIENT_CARDBUS) { -#ifdef CONFIG_CARDBUS - handle->state |= CLIENT_IO_REQ; - return CS_SUCCESS; -#else - return CS_UNSUPPORTED_FUNCTION; -#endif - } - if (!req) return CS_UNSUPPORTED_MODE; - c = CONFIG(handle); + c = CONFIG(p_dev); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->state & CONFIG_IO_REQ) @@ -793,7 +757,7 @@ int pcmcia_request_io(client_handle_t handle, io_req_t *req) c->io = *req; c->state |= CONFIG_IO_REQ; - handle->state |= CLIENT_IO_REQ; + p_dev->state |= CLIENT_IO_REQ; return CS_SUCCESS; } /* pcmcia_request_io */ EXPORT_SYMBOL(pcmcia_request_io); @@ -816,17 +780,15 @@ static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs) } #endif -int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) +int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) { - struct pcmcia_socket *s; + struct pcmcia_socket *s = p_dev->socket; config_t *c; int ret = CS_IN_USE, irq = 0; - struct pcmcia_device *p_dev = handle_to_pdev(handle); - s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - c = CONFIG(handle); + c = CONFIG(p_dev); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->state & CONFIG_IRQ_REQ) @@ -890,7 +852,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) s->irq.Config++; c->state |= CONFIG_IRQ_REQ; - handle->state |= CLIENT_IRQ_REQ; + p_dev->state |= CLIENT_IRQ_REQ; #ifdef CONFIG_PCMCIA_PROBE pcmcia_used_irq[irq]++; @@ -906,14 +868,13 @@ EXPORT_SYMBOL(pcmcia_request_irq); * Request_window() establishes a mapping between card memory space * and system memory space. */ -int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh) +int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh) { - struct pcmcia_socket *s; + struct pcmcia_socket *s = (*p_dev)->socket; window_t *win; u_long align; int w; - s = (*handle)->socket; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (req->Attributes & (WIN_PAGED | WIN_SHARED)) @@ -942,7 +903,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle win = &s->win[w]; win->magic = WINDOW_MAGIC; win->index = w; - win->handle = *handle; + win->handle = *p_dev; win->sock = s; if (!(s->features & SS_CAP_STATIC_MAP)) { @@ -951,7 +912,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle if (!win->ctl.res) return CS_IN_USE; } - (*handle)->state |= CLIENT_WIN_REQ(w); + (*p_dev)->state |= CLIENT_WIN_REQ(w); /* Configure the socket controller */ win->ctl.map = w+1; diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index b42ddc0c1143..db73b40429bd 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -77,12 +77,8 @@ typedef struct servinfo_t { } servinfo_t; typedef struct event_callback_args_t { - client_handle_t client_handle; - void *info; - void *mtdrequest; - void *buffer; - void *misc; - void *client_data; + struct pcmcia_device *client_handle; + void *client_data; } event_callback_args_t; /* for GetConfigurationInfo */ @@ -393,25 +389,25 @@ enum service { struct pcmcia_socket; -int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg); -int pcmcia_deregister_client(client_handle_t handle); -int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config); +int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg); +int pcmcia_deregister_client(struct pcmcia_device *p_dev); +int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config); int pcmcia_get_first_window(window_handle_t *win, win_req_t *req); int pcmcia_get_next_window(window_handle_t *win, win_req_t *req); -int pcmcia_get_status(client_handle_t handle, cs_status_t *status); +int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status); int pcmcia_get_mem_page(window_handle_t win, memreq_t *req); int pcmcia_map_mem_page(window_handle_t win, memreq_t *req); -int pcmcia_modify_configuration(client_handle_t handle, modconf_t *mod); +int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod); int pcmcia_register_client(client_handle_t *handle, client_reg_t *req); -int pcmcia_release_configuration(client_handle_t handle); -int pcmcia_release_io(client_handle_t handle, io_req_t *req); -int pcmcia_release_irq(client_handle_t handle, irq_req_t *req); +int pcmcia_release_configuration(struct pcmcia_device *p_dev); +int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req); +int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req); int pcmcia_release_window(window_handle_t win); -int pcmcia_request_configuration(client_handle_t handle, config_req_t *req); -int pcmcia_request_io(client_handle_t handle, io_req_t *req); -int pcmcia_request_irq(client_handle_t handle, irq_req_t *req); -int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh); -int pcmcia_reset_card(client_handle_t handle, client_req_t *req); +int pcmcia_request_configuration(struct pcmcia_device *p_dev, config_req_t *req); +int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req); +int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req); +int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh); +int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req); int pcmcia_suspend_card(struct pcmcia_socket *skt); int pcmcia_resume_card(struct pcmcia_socket *skt); int pcmcia_eject_card(struct pcmcia_socket *skt); -- cgit v1.3-14-g43fede From a00db1ba7c33619cbd7c3153e4746d15881c0383 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 7 Jul 2005 17:59:03 -0700 Subject: [PATCH] pcmcia: remove client services version The Linux PCMCIA code has some data that was apparently used (or meant to be used) to ensure that only proper client drivers are loaded. This is now ensured (to a certain degree) by the fact that the most client drivers are part of the kernel. Also, the version information has not been updated despite major changes in PCMCIA API. This has made it meaningless. This patch removes servinfo_t and pcmcia_get_card_services_info. They are not used in any userspace utilities such as pcmcia-cs and pcmciautils. drivers/pcmcia/pcmcia_ioctl.c is adjusted accordingly. CS_RELEASE and CS_RELEASE_CODE are removed. include/pcmcia/version.h is empty now. It will be removed later, but for now it's left in the tree to avoid touching all PCMCIA clients. The only driver that needs to be changed is drivers/scsi/pcmcia/nsp_cs.c, which uses CS_RELEASE_CODE. Signed-off-by: Pavel Roskin Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/pcmcia_ioctl.c | 26 -------------------------- drivers/scsi/pcmcia/nsp_cs.c | 4 ---- include/pcmcia/cs.h | 8 -------- include/pcmcia/ds.h | 2 -- include/pcmcia/version.h | 3 +-- 5 files changed, 1 insertion(+), 42 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index b883bc151ed0..ee02224dd774 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -71,29 +71,6 @@ extern int ds_pc_debug; #define ds_dbg(lvl, fmt, arg...) do { } while (0) #endif -static const char *release = "Linux Kernel Card Services"; - -/** pcmcia_get_card_services_info - * - * Return information about this version of Card Services - */ -static int pcmcia_get_card_services_info(servinfo_t *info) -{ - unsigned int socket_count = 0; - struct list_head *tmp; - info->Signature[0] = 'C'; - info->Signature[1] = 'S'; - down_read(&pcmcia_socket_list_rwsem); - list_for_each(tmp, &pcmcia_socket_list) - socket_count++; - up_read(&pcmcia_socket_list_rwsem); - info->Count = socket_count; - info->Revision = CS_RELEASE_CODE; - info->CSLevel = 0x0210; - info->VendorString = (char *)release; - return CS_SUCCESS; -} /* get_card_services_info */ - /* backwards-compatible accessing of driver --- by name! */ @@ -591,9 +568,6 @@ static int ds_ioctl(struct inode * inode, struct file * file, case DS_ADJUST_RESOURCE_INFO: ret = pcmcia_adjust_resource_info(&buf->adjust); break; - case DS_GET_CARD_SERVICES_INFO: - ret = pcmcia_get_card_services_info(&buf->servinfo); - break; case DS_GET_CONFIGURATION_INFO: if (buf->config.Function && (buf->config.Function >= s->functions)) diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index c8755adfd917..506bbb446e5e 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -2155,10 +2155,6 @@ static int __init nsp_cs_init(void) nsp_msg(KERN_INFO, "loading..."); pcmcia_get_card_services_info(&serv); - if (serv.Revision != CS_RELEASE_CODE) { - nsp_msg(KERN_DEBUG, "Card Services release does not match!"); - return -EINVAL; - } register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach); nsp_dbg(NSP_DEBUG_INIT, "out"); diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index db73b40429bd..2cab39f49eb2 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -68,14 +68,6 @@ typedef struct adjust_t { #define RES_ALLOCATED 0x20 #define RES_REMOVED 0x40 -typedef struct servinfo_t { - char Signature[2]; - u_int Count; - u_int Revision; - u_int CSLevel; - char *VendorString; -} servinfo_t; - typedef struct event_callback_args_t { struct pcmcia_device *client_handle; void *client_data; diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index e0a5acb7fcb7..0190e766e1a7 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -49,7 +49,6 @@ typedef struct mtd_info_t { } mtd_info_t; typedef union ds_ioctl_arg_t { - servinfo_t servinfo; adjust_t adjust; config_info_t config; tuple_t tuple; @@ -65,7 +64,6 @@ typedef union ds_ioctl_arg_t { cisdump_t cisdump; } ds_ioctl_arg_t; -#define DS_GET_CARD_SERVICES_INFO _IOR ('d', 1, servinfo_t) #define DS_ADJUST_RESOURCE_INFO _IOWR('d', 2, adjust_t) #define DS_GET_CONFIGURATION_INFO _IOWR('d', 3, config_info_t) #define DS_GET_FIRST_TUPLE _IOWR('d', 4, tuple_t) diff --git a/include/pcmcia/version.h b/include/pcmcia/version.h index eb88263fc8d5..5ad9c5e198b6 100644 --- a/include/pcmcia/version.h +++ b/include/pcmcia/version.h @@ -1,4 +1,3 @@ /* version.h 1.94 2000/10/03 17:55:48 (David Hinds) */ -#define CS_RELEASE "3.1.22" -#define CS_RELEASE_CODE 0x3116 +/* This file will be removed, please don't include it */ -- cgit v1.3-14-g43fede From a6ccbbb8865101d83c2e716f08feae1da1c48584 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 7 Jul 2005 17:59:11 -0700 Subject: [PATCH] nfsd4: fix sync'ing of recovery directory We need to fsync the recovery directory after writing to it, but we weren't doing this correctly. (For example, we weren't taking the i_sem when calling ->fsync().) Just reuse the existing nfsd fsync code instead. Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs4recover.c | 29 ++++++++--------------------- fs/nfsd/vfs.c | 2 +- include/linux/nfsd/nfsd.h | 1 + 3 files changed, 10 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 095f1740f3ae..bb40083b6b7d 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -119,25 +119,12 @@ out: return status; } -static int -nfsd4_rec_fsync(struct dentry *dentry) +static void +nfsd4_sync_rec_dir(void) { - struct file *filp; - int status = nfs_ok; - - dprintk("NFSD: nfs4_fsync_rec_dir\n"); - filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR); - if (IS_ERR(filp)) { - status = PTR_ERR(filp); - goto out; - } - if (filp->f_op && filp->f_op->fsync) - status = filp->f_op->fsync(filp, filp->f_dentry, 0); - fput(filp); -out: - if (status) - printk("nfsd4: unable to sync recovery directory\n"); - return status; + down(&rec_dir.dentry->d_inode->i_sem); + nfsd_sync_dir(rec_dir.dentry); + up(&rec_dir.dentry->d_inode->i_sem); } int @@ -176,7 +163,7 @@ out_unlock: up(&rec_dir.dentry->d_inode->i_sem); if (status == 0) { clp->cl_firststate = 1; - status = nfsd4_rec_fsync(rec_dir.dentry); + nfsd4_sync_rec_dir(); } nfs4_reset_user(uid, gid); dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status); @@ -331,7 +318,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); nfs4_reset_user(uid, gid); if (status == 0) - status = nfsd4_rec_fsync(rec_dir.dentry); + nfsd4_sync_rec_dir(); if (status) printk("NFSD: Failed to remove expired client state directory" " %.*s\n", HEXDIR_LEN, clp->cl_recdir); @@ -362,7 +349,7 @@ nfsd4_recdir_purge_old(void) { return; status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old); if (status == 0) - status = nfsd4_rec_fsync(rec_dir.dentry); + nfsd4_sync_rec_dir(); if (status) printk("nfsd4: failed to purge old clients from recovery" " directory %s\n", rec_dir.dentry->d_name.name); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index be24ead89d94..5e0bf3917607 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -733,7 +733,7 @@ nfsd_sync(struct file *filp) up(&inode->i_sem); } -static void +void nfsd_sync_dir(struct dentry *dp) { nfsd_dosync(NULL, dp, dp->d_inode->i_fop); diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 5791dfd30dd0..c2da1b62d416 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -124,6 +124,7 @@ int nfsd_statfs(struct svc_rqst *, struct svc_fh *, int nfsd_notify_change(struct inode *, struct iattr *); int nfsd_permission(struct svc_export *, struct dentry *, int); +void nfsd_sync_dir(struct dentry *dp); #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) #ifdef CONFIG_NFSD_V2_ACL -- cgit v1.3-14-g43fede From 7fb64cee34f5dc743f697041717cafda8a94b5ac Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 7 Jul 2005 17:59:20 -0700 Subject: [PATCH] nfsd4: seqid comments Add some comments on the use of so_seqid, in an attempt to avoid some of the confusion outlined in the previous patch.... Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs4xdr.c | 8 ++++---- include/linux/nfsd/state.h | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 5207068cde1a..1515c5b8096f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1210,10 +1210,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) save = resp->p; /* - * Routine for encoding the result of a - * "seqid-mutating" NFSv4 operation. This is - * where seqids are incremented, and the - * replay cache is filled. + * Routine for encoding the result of a "seqid-mutating" NFSv4 operation. This + * is where sequence id's are incremented, and the replay cache is filled. + * Note that we increment sequence id's here, at the last moment, so we're sure + * we know whether the error to be returned is a sequence id mutating error. */ #define ENCODE_SEQID_OP_TAIL(stateowner) do { \ diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h index a84a3fa99be1..2d19431f47ea 100644 --- a/include/linux/nfsd/state.h +++ b/include/linux/nfsd/state.h @@ -203,7 +203,9 @@ struct nfs4_stateowner { int so_is_open_owner; /* 1=openowner,0=lockowner */ u32 so_id; struct nfs4_client * so_client; - u32 so_seqid; + /* after increment in ENCODE_SEQID_OP_TAIL, represents the next + * sequence id expected from the client: */ + u32 so_seqid; struct xdr_netobj so_owner; /* open owner name */ int so_confirmed; /* successful OPEN_CONFIRM? */ struct nfs4_replay so_replay; -- cgit v1.3-14-g43fede From b700949b781480819e53bdc38a53f053226dd75e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 7 Jul 2005 17:59:23 -0700 Subject: [PATCH] nfsd4: return better error on io incompatible with open mode from RFC 3530: "Share reservations are established by OPEN operations and by their nature are mandatory in that when the OPEN denies READ or WRITE operations, that denial results in such operations being rejected with error NFS4ERR_LOCKED." (Note that share_denied is really only a legal error for OPEN.) Signed-off-by: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs4state.c | 2 +- include/linux/nfsd/nfsd.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index b96714ae3dd7..3647c942915e 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1295,7 +1295,7 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) fp = find_file(ino); if (!fp) return nfs_ok; - ret = nfserr_share_denied; + ret = nfserr_locked; /* Search for conflicting share reservations */ list_for_each_entry(stp, &fp->fi_stateids, st_perfile) { if (test_bit(deny_type, &stp->st_deny_bmap) || diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index c2da1b62d416..6d5a24f3fc6d 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -231,6 +231,7 @@ void nfsd_lockd_shutdown(void); #define nfserr_reclaim_bad __constant_htonl(NFSERR_RECLAIM_BAD) #define nfserr_badname __constant_htonl(NFSERR_BADNAME) #define nfserr_cb_path_down __constant_htonl(NFSERR_CB_PATH_DOWN) +#define nfserr_locked __constant_htonl(NFSERR_LOCKED) /* error codes for internal use */ /* if a request fails due to kmalloc failure, it gets dropped. -- cgit v1.3-14-g43fede From 4c4cd222ee329025840bc2f8cebf71d36c62440c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 7 Jul 2005 17:59:27 -0700 Subject: [PATCH] nfsd4: check lock type against openmode. We shouldn't be allowing, e.g., write locks on files not open for read. To enforce this, we add a pointer from the lock stateid back to the open stateid it came from, so that the check will continue to be correct even after the open is upgraded or downgraded. Signed-off-by: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs4state.c | 49 +++++++++++++++++++++++++++++++--------------- include/linux/nfsd/state.h | 5 +++++ 2 files changed, 38 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 59b214f01b6d..b83f8fb441e1 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1160,6 +1160,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open * stp->st_deny_bmap = 0; __set_bit(open->op_share_access, &stp->st_access_bmap); __set_bit(open->op_share_deny, &stp->st_deny_bmap); + stp->st_openstp = NULL; } static void @@ -2158,12 +2159,18 @@ out: return status; } +static inline int +setlkflg (int type) +{ + return (type == NFS4_READW_LT || type == NFS4_READ_LT) ? + RD_STATE : WR_STATE; +} /* * Checks for sequence id mutating operations. */ static int -nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid) +nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock) { struct nfs4_stateid *stp; struct nfs4_stateowner *sop; @@ -2201,21 +2208,31 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei goto check_replay; } - /* for new lock stateowners: - * check that the lock->v.new.open_stateid - * refers to an open stateowner - * - * check that the lockclid (nfs4_lock->v.new.clientid) is the same - * as the open_stateid->st_stateowner->so_client->clientid - */ - if (lockclid) { + if (lock) { struct nfs4_stateowner *sop = stp->st_stateowner; + clientid_t *lockclid = &lock->v.new.clientid; struct nfs4_client *clp = sop->so_client; + int lkflg = 0; + int status; + + lkflg = setlkflg(lock->lk_type); + + if (lock->lk_is_new) { + if (!sop->so_is_open_owner) + return nfserr_bad_stateid; + if (!cmp_clid(&clp->cl_clientid, lockclid)) + return nfserr_bad_stateid; + /* stp is the open stateid */ + status = nfs4_check_openmode(stp, lkflg); + if (status) + return status; + } else { + /* stp is the lock stateid */ + status = nfs4_check_openmode(stp->st_openstp, lkflg); + if (status) + return status; + } - if (!sop->so_is_open_owner) - return nfserr_bad_stateid; - if (!cmp_clid(&clp->cl_clientid, lockclid)) - return nfserr_bad_stateid; } if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { @@ -2642,6 +2659,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */ stp->st_access_bmap = open_stp->st_access_bmap; stp->st_deny_bmap = open_stp->st_deny_bmap; + stp->st_openstp = open_stp; out: return stp; @@ -2697,8 +2715,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock lock->lk_new_open_seqid, &lock->lk_new_open_stateid, CHECK_FH | OPEN_STATE, - &open_sop, &open_stp, - &lock->v.new.clientid); + &open_sop, &open_stp, lock); if (status) goto out; /* create lockowner and lock stateid */ @@ -2726,7 +2743,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock lock->lk_old_lock_seqid, &lock->lk_old_lock_stateid, CHECK_FH | LOCK_STATE, - &lock->lk_stateowner, &lock_stp, NULL); + &lock->lk_stateowner, &lock_stp, lock); if (status) goto out; } diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h index 2d19431f47ea..8bf23cf8b603 100644 --- a/include/linux/nfsd/state.h +++ b/include/linux/nfsd/state.h @@ -237,6 +237,10 @@ struct nfs4_file { * st_perlockowner: (open stateid) list of lock nfs4_stateowners * st_access_bmap: used only for open stateid * st_deny_bmap: used only for open stateid +* st_openstp: open stateid lock stateid was derived from +* +* XXX: open stateids and lock stateids have diverged sufficiently that +* we should consider defining separate structs for the two cases. */ struct nfs4_stateid { @@ -250,6 +254,7 @@ struct nfs4_stateid { struct file * st_vfs_file; unsigned long st_access_bmap; unsigned long st_deny_bmap; + struct nfs4_stateid * st_openstp; }; /* flags for preprocess_seqid_op() */ -- cgit v1.3-14-g43fede From 316240f66a64c95e373d52dc401d882d77a594ee Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Thu, 7 Jul 2005 17:59:32 -0700 Subject: [PATCH] m32r: framebuffer device support This patch is for supporting Epson s1d13xxx framebuffer device for m32r. # Sorry, a little bigger. The Epson s1d13806 is already supported by 2.6.12 kernel, and its driver is placed as drivers/video/s1d13xxxfb.c. For the m32r, a header file include/asm-m32r/s1d13806.h was prepared for several m32r target platforms. It was originally generated by an Epson tool S1D13806CFG.EXE, and modified manually for the m32r platforms. Signed-off-by: Hayato Fujiwara Signed-off-by: Hirokazu Takata Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m32r/kernel/setup_m32700ut.c | 55 +- arch/m32r/kernel/setup_mappi.c | 51 +- arch/m32r/kernel/setup_mappi2.c | 4 +- arch/m32r/kernel/setup_mappi3.c | 52 +- arch/m32r/kernel/setup_oaks32r.c | 5 +- arch/m32r/kernel/setup_opsput.c | 53 +- drivers/video/logo/Kconfig | 5 + drivers/video/logo/Makefile | 1 + drivers/video/logo/logo.c | 5 + drivers/video/logo/logo_m32r_clut224.ppm | 1292 ++++++++++++++++++++++++++++++ drivers/video/s1d13xxxfb.c | 10 + include/asm-m32r/s1d13806.h | 199 +++++ 12 files changed, 1716 insertions(+), 16 deletions(-) create mode 100644 drivers/video/logo/logo_m32r_clut224.ppm create mode 100644 include/asm-m32r/s1d13806.h (limited to 'include') diff --git a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c index b014e2c1e524..a146b24a556b 100644 --- a/arch/m32r/kernel/setup_m32700ut.c +++ b/arch/m32r/kernel/setup_m32700ut.c @@ -3,8 +3,8 @@ * * Setup routines for Renesas M32700UT Board * - * Copyright (c) 2002 Hiroyuki Kondo, Hirokazu Takata, - * Hitoshi Yamamoto, Takeo Takahashi + * Copyright (c) 2002-2005 Hiroyuki Kondo, Hirokazu Takata, + * Hitoshi Yamamoto, Takeo Takahashi * * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this @@ -435,7 +435,7 @@ void __init init_IRQ(void) icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01; enable_m32700ut_irq(M32R_IRQ_INT2); -//#if defined(CONFIG_VIDEO_M32R_AR) +#if defined(CONFIG_VIDEO_M32R_AR) /* * INT3# is used for AR */ @@ -445,9 +445,11 @@ void __init init_IRQ(void) irq_desc[M32R_IRQ_INT3].depth = 1; icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10; disable_m32700ut_irq(M32R_IRQ_INT3); -//#endif /* CONFIG_VIDEO_M32R_AR */ +#endif /* CONFIG_VIDEO_M32R_AR */ } +#if defined(CONFIG_SMC91X) + #define LAN_IOSTART 0x300 #define LAN_IOEND 0x320 static struct resource smc91x_resources[] = { @@ -469,10 +471,55 @@ static struct platform_device smc91x_device = { .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; +#endif + +#if defined(CONFIG_FB_S1D13XXX) + +#include